Viewing file: tlbflush.h (3.23 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
#ifndef _ALPHA_TLBFLUSH_H #define _ALPHA_TLBFLUSH_H
#include <linux/mm.h> #include <asm/compiler.h>
#ifndef __EXTERN_INLINE #define __EXTERN_INLINE extern inline #define __MMU_EXTERN_INLINE #endif
extern void __load_new_mm_context(struct mm_struct *);
/* Use a few helper functions to hide the ugly broken ASN numbers on early Alphas (ev4 and ev45). */
__EXTERN_INLINE void ev4_flush_tlb_current(struct mm_struct *mm) { __load_new_mm_context(mm); tbiap(); }
__EXTERN_INLINE void ev5_flush_tlb_current(struct mm_struct *mm) { __load_new_mm_context(mm); }
/* Flush just one page in the current TLB set. We need to be very careful about the icache here, there is no way to invalidate a specific icache page. */
__EXTERN_INLINE void ev4_flush_tlb_current_page(struct mm_struct * mm, struct vm_area_struct *vma, unsigned long addr) { int tbi_flag = 2; if (vma->vm_flags & VM_EXEC) { __load_new_mm_context(mm); tbi_flag = 3; } tbi(tbi_flag, addr); }
__EXTERN_INLINE void ev5_flush_tlb_current_page(struct mm_struct * mm, struct vm_area_struct *vma, unsigned long addr) { if (vma->vm_flags & VM_EXEC) __load_new_mm_context(mm); else tbi(2, addr); }
#ifdef CONFIG_ALPHA_GENERIC # define flush_tlb_current alpha_mv.mv_flush_tlb_current # define flush_tlb_current_page alpha_mv.mv_flush_tlb_current_page #else # ifdef CONFIG_ALPHA_EV4 # define flush_tlb_current ev4_flush_tlb_current # define flush_tlb_current_page ev4_flush_tlb_current_page # else # define flush_tlb_current ev5_flush_tlb_current # define flush_tlb_current_page ev5_flush_tlb_current_page # endif #endif
#ifdef __MMU_EXTERN_INLINE #undef __EXTERN_INLINE #undef __MMU_EXTERN_INLINE #endif
/* Flush current user mapping. */ static inline void flush_tlb(void) { flush_tlb_current(current->active_mm); }
/* Flush someone else's user mapping. */ static inline void flush_tlb_other(struct mm_struct *mm) { unsigned long *mmc = &mm->context[smp_processor_id()]; /* Check it's not zero first to avoid cacheline ping pong when possible. */ if (*mmc) *mmc = 0; }
#ifndef CONFIG_SMP /* Flush everything (kernel mapping may also have changed due to vmalloc/vfree). */ static inline void flush_tlb_all(void) { tbia(); }
/* Flush a specified user mapping. */ static inline void flush_tlb_mm(struct mm_struct *mm) { if (mm == current->active_mm) flush_tlb_current(mm); else flush_tlb_other(mm); }
/* Page-granular tlb flush. */ static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { struct mm_struct *mm = vma->vm_mm;
if (mm == current->active_mm) flush_tlb_current_page(mm, vma, addr); else flush_tlb_other(mm); }
/* Flush a specified range of user mapping. On the Alpha we flush the whole user tlb. */ 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 */
extern void flush_tlb_all(void); extern void flush_tlb_mm(struct mm_struct *); extern void flush_tlb_page(struct vm_area_struct *, unsigned long); extern void flush_tlb_range(struct vm_area_struct *, unsigned long, unsigned long);
#endif /* CONFIG_SMP */
#define flush_tlb_kernel_range(start, end) flush_tlb_all()
#endif /* _ALPHA_TLBFLUSH_H */
|