diff options
Diffstat (limited to 'arch/mn10300/include/asm/tlbflush.h')
-rw-r--r-- | arch/mn10300/include/asm/tlbflush.h | 174 |
1 files changed, 124 insertions, 50 deletions
diff --git a/arch/mn10300/include/asm/tlbflush.h b/arch/mn10300/include/asm/tlbflush.h index 1a7e29281c5..efddd6e1ade 100644 --- a/arch/mn10300/include/asm/tlbflush.h +++ b/arch/mn10300/include/asm/tlbflush.h @@ -11,24 +11,78 @@ #ifndef _ASM_TLBFLUSH_H #define _ASM_TLBFLUSH_H +#include <linux/mm.h> #include <asm/processor.h> -#define __flush_tlb() \ -do { \ - int w; \ - __asm__ __volatile__ \ - (" mov %1,%0 \n" \ - " or %2,%0 \n" \ - " mov %0,%1 \n" \ - : "=d"(w) \ - : "m"(MMUCTR), "i"(MMUCTR_IIV|MMUCTR_DIV) \ - : "cc", "memory" \ - ); \ -} while (0) +struct tlb_state { + struct mm_struct *active_mm; + int state; +}; +DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate); -#define __flush_tlb_all() __flush_tlb() -#define __flush_tlb_one(addr) __flush_tlb() +/** + * local_flush_tlb - Flush the current MM's entries from the local CPU's TLBs + */ +static inline void local_flush_tlb(void) +{ + int w; + asm volatile( + " mov %1,%0 \n" + " or %2,%0 \n" + " mov %0,%1 \n" + : "=d"(w) + : "m"(MMUCTR), "i"(MMUCTR_IIV|MMUCTR_DIV) + : "cc", "memory"); +} + +/** + * local_flush_tlb_all - Flush all entries from the local CPU's TLBs + */ +static inline void local_flush_tlb_all(void) +{ + local_flush_tlb(); +} +/** + * local_flush_tlb_one - Flush one entry from the local CPU's TLBs + */ +static inline void local_flush_tlb_one(unsigned long addr) +{ + local_flush_tlb(); +} + +/** + * local_flush_tlb_page - Flush a page's entry from the local CPU's TLBs + * @mm: The MM to flush for + * @addr: The address of the target page in RAM (not its page struct) + */ +static inline +void local_flush_tlb_page(struct mm_struct *mm, unsigned long addr) +{ + unsigned long pteu, flags, cnx; + + addr &= PAGE_MASK; + + local_irq_save(flags); + + cnx = 1; +#ifdef CONFIG_MN10300_TLB_USE_PIDR + cnx = mm->context.tlbpid[smp_processor_id()]; +#endif + if (cnx) { + pteu = addr; +#ifdef CONFIG_MN10300_TLB_USE_PIDR + pteu |= cnx & xPTEU_PID; +#endif + IPTEU = pteu; + DPTEU = pteu; + if (IPTEL & xPTEL_V) + IPTEL = 0; + if (DPTEL & xPTEL_V) + DPTEL = 0; + } + local_irq_restore(flags); +} /* * TLB flushing: @@ -40,41 +94,61 @@ do { \ * - flush_tlb_range(mm, start, end) flushes a range of pages * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables */ -#define flush_tlb_all() \ -do { \ - preempt_disable(); \ - __flush_tlb_all(); \ - preempt_enable(); \ -} while (0) - -#define flush_tlb_mm(mm) \ -do { \ - preempt_disable(); \ - __flush_tlb_all(); \ - preempt_enable(); \ -} while (0) - -#define flush_tlb_range(vma, start, end) \ -do { \ - unsigned long __s __attribute__((unused)) = (start); \ - unsigned long __e __attribute__((unused)) = (end); \ - preempt_disable(); \ - __flush_tlb_all(); \ - preempt_enable(); \ -} while (0) - - -#define __flush_tlb_global() flush_tlb_all() -#define flush_tlb() flush_tlb_all() -#define flush_tlb_kernel_range(start, end) \ -do { \ - unsigned long __s __attribute__((unused)) = (start); \ - unsigned long __e __attribute__((unused)) = (end); \ - flush_tlb_all(); \ -} while (0) - -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr); - -#define flush_tlb_pgtables(mm, start, end) do {} while (0) +#ifdef CONFIG_SMP + +#include <asm/smp.h> + +extern void flush_tlb_all(void); +extern void flush_tlb_current_task(void); +extern void flush_tlb_mm(struct mm_struct *); +extern void flush_tlb_page(struct vm_area_struct *, unsigned long); + +#define flush_tlb() flush_tlb_current_task() + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + flush_tlb_mm(vma->vm_mm); +} + +#else /* CONFIG_SMP */ + +static inline void flush_tlb_all(void) +{ + preempt_disable(); + local_flush_tlb_all(); + preempt_enable(); +} + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + preempt_disable(); + local_flush_tlb_all(); + preempt_enable(); +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + preempt_disable(); + local_flush_tlb_all(); + preempt_enable(); +} + +#define flush_tlb_page(vma, addr) local_flush_tlb_page((vma)->vm_mm, addr) +#define flush_tlb() flush_tlb_all() + +#endif /* CONFIG_SMP */ + +static inline void flush_tlb_kernel_range(unsigned long start, + unsigned long end) +{ + flush_tlb_all(); +} + +static inline void flush_tlb_pgtables(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ +} #endif /* _ASM_TLBFLUSH_H */ |