From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- include/asm-x86_64/tlbflush.h | 119 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 include/asm-x86_64/tlbflush.h (limited to 'include/asm-x86_64/tlbflush.h') diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h new file mode 100644 index 000000000000..2e811ac262af --- /dev/null +++ b/include/asm-x86_64/tlbflush.h @@ -0,0 +1,119 @@ +#ifndef _X8664_TLBFLUSH_H +#define _X8664_TLBFLUSH_H + +#include +#include +#include + +#define __flush_tlb() \ + do { \ + unsigned long tmpreg; \ + \ + __asm__ __volatile__( \ + "movq %%cr3, %0; # flush TLB \n" \ + "movq %0, %%cr3; \n" \ + : "=r" (tmpreg) \ + :: "memory"); \ + } while (0) + +/* + * Global pages have to be flushed a bit differently. Not a real + * performance problem because this does not happen often. + */ +#define __flush_tlb_global() \ + do { \ + unsigned long tmpreg; \ + \ + __asm__ __volatile__( \ + "movq %1, %%cr4; # turn off PGE \n" \ + "movq %%cr3, %0; # flush TLB \n" \ + "movq %0, %%cr3; \n" \ + "movq %2, %%cr4; # turn PGE back on \n" \ + : "=&r" (tmpreg) \ + : "r" (mmu_cr4_features & ~X86_CR4_PGE), \ + "r" (mmu_cr4_features) \ + : "memory"); \ + } while (0) + +extern unsigned long pgkern_mask; + +#define __flush_tlb_all() __flush_tlb_global() + +#define __flush_tlb_one(addr) \ + __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr)) + + +/* + * TLB flushing: + * + * - flush_tlb() flushes the current mm struct TLBs + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_mm(mm) flushes the specified mm context TLB's + * - flush_tlb_page(vma, vmaddr) flushes one page + * - flush_tlb_range(vma, start, end) flushes a range of pages + * - flush_tlb_kernel_range(start, end) flushes a range of kernel pages + * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables + * + * ..but the x86_64 has somewhat limited tlb flushing capabilities, + * and page-granular flushes are available only on i486 and up. + */ + +#ifndef CONFIG_SMP + +#define flush_tlb() __flush_tlb() +#define flush_tlb_all() __flush_tlb_all() +#define local_flush_tlb() __flush_tlb() + +static inline void flush_tlb_mm(struct mm_struct *mm) +{ + if (mm == current->active_mm) + __flush_tlb(); +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long addr) +{ + if (vma->vm_mm == current->active_mm) + __flush_tlb_one(addr); +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + if (vma->vm_mm == current->active_mm) + __flush_tlb(); +} + +#else + +#include + +#define local_flush_tlb() \ + __flush_tlb() + +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); +} + +#define TLBSTATE_OK 1 +#define TLBSTATE_LAZY 2 + +#endif + +#define flush_tlb_kernel_range(start, end) flush_tlb_all() + +static inline void flush_tlb_pgtables(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + /* x86_64 does not keep any page table caches in TLB */ +} + +#endif /* _X8664_TLBFLUSH_H */ -- cgit v1.2.1