home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-i386 / tlbflush.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  3.6 KB  |  149 lines

  1. #ifndef _I386_TLBFLUSH_H
  2. #define _I386_TLBFLUSH_H
  3.  
  4. #include <linux/mm.h>
  5. #include <asm/processor.h>
  6.  
  7. #define __flush_tlb()                            \
  8.     do {                                \
  9.         unsigned int tmpreg;                    \
  10.                                     \
  11.         __asm__ __volatile__(                    \
  12.             "movl %%cr3, %0;              \n"        \
  13.             "movl %0, %%cr3;  # flush TLB \n"        \
  14.             : "=r" (tmpreg)                    \
  15.             :: "memory");                    \
  16.     } while (0)
  17.  
  18. /*
  19.  * Global pages have to be flushed a bit differently. Not a real
  20.  * performance problem because this does not happen often.
  21.  */
  22. #define __flush_tlb_global()                        \
  23.     do {                                \
  24.         unsigned int tmpreg, cr4, cr4_orig;            \
  25.                                     \
  26.         __asm__ __volatile__(                    \
  27.             "movl %%cr4, %2;  # turn off PGE     \n"    \
  28.             "movl %2, %1;                        \n"    \
  29.             "andl %3, %1;                        \n"    \
  30.             "movl %1, %%cr4;                     \n"    \
  31.             "movl %%cr3, %0;                     \n"    \
  32.             "movl %0, %%cr3;  # flush TLB        \n"    \
  33.             "movl %2, %%cr4;  # turn PGE back on \n"    \
  34.             : "=&r" (tmpreg), "=&r" (cr4), "=&r" (cr4_orig)    \
  35.             : "i" (~X86_CR4_PGE)                \
  36.             : "memory");                    \
  37.     } while (0)
  38.  
  39. extern unsigned long pgkern_mask;
  40.  
  41. # define __flush_tlb_all()                        \
  42.     do {                                \
  43.         if (cpu_has_pge)                    \
  44.             __flush_tlb_global();                \
  45.         else                            \
  46.             __flush_tlb();                    \
  47.     } while (0)
  48.  
  49. #define cpu_has_invlpg    (boot_cpu_data.x86 > 3)
  50.  
  51. #define __flush_tlb_single(addr) \
  52.     __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
  53.  
  54. #ifdef CONFIG_X86_INVLPG
  55. # define __flush_tlb_one(addr) __flush_tlb_single(addr)
  56. #else
  57. # define __flush_tlb_one(addr)                        \
  58.     do {                                \
  59.         if (cpu_has_invlpg)                    \
  60.             __flush_tlb_single(addr);            \
  61.         else                            \
  62.             __flush_tlb();                    \
  63.     } while (0)
  64. #endif
  65.  
  66. /*
  67.  * TLB flushing:
  68.  *
  69.  *  - flush_tlb() flushes the current mm struct TLBs
  70.  *  - flush_tlb_all() flushes all processes TLBs
  71.  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
  72.  *  - flush_tlb_page(vma, vmaddr) flushes one page
  73.  *  - flush_tlb_range(vma, start, end) flushes a range of pages
  74.  *  - flush_tlb_kernel_range(start, end) flushes a range of kernel pages
  75.  *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
  76.  *
  77.  * ..but the i386 has somewhat limited tlb flushing capabilities,
  78.  * and page-granular flushes are available only on i486 and up.
  79.  */
  80.  
  81. #ifndef CONFIG_SMP
  82.  
  83. #define flush_tlb() __flush_tlb()
  84. #define flush_tlb_all() __flush_tlb_all()
  85. #define local_flush_tlb() __flush_tlb()
  86.  
  87. static inline void flush_tlb_mm(struct mm_struct *mm)
  88. {
  89.     if (mm == current->active_mm)
  90.         __flush_tlb();
  91. }
  92.  
  93. static inline void flush_tlb_page(struct vm_area_struct *vma,
  94.     unsigned long addr)
  95. {
  96.     if (vma->vm_mm == current->active_mm)
  97.         __flush_tlb_one(addr);
  98. }
  99.  
  100. static inline void flush_tlb_range(struct vm_area_struct *vma,
  101.     unsigned long start, unsigned long end)
  102. {
  103.     if (vma->vm_mm == current->active_mm)
  104.         __flush_tlb();
  105. }
  106.  
  107. #else
  108.  
  109. #include <asm/smp.h>
  110.  
  111. #define local_flush_tlb() \
  112.     __flush_tlb()
  113.  
  114. extern void flush_tlb_all(void);
  115. extern void flush_tlb_current_task(void);
  116. extern void flush_tlb_mm(struct mm_struct *);
  117. extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
  118.  
  119. #define flush_tlb()    flush_tlb_current_task()
  120.  
  121. static inline void flush_tlb_range(struct vm_area_struct * vma, unsigned long start, unsigned long end)
  122. {
  123.     flush_tlb_mm(vma->vm_mm);
  124. }
  125.  
  126. #define TLBSTATE_OK    1
  127. #define TLBSTATE_LAZY    2
  128.  
  129. struct tlb_state
  130. {
  131.     struct mm_struct *active_mm;
  132.     int state;
  133.     char __cacheline_padding[L1_CACHE_BYTES-8];
  134. };
  135. DECLARE_PER_CPU(struct tlb_state, cpu_tlbstate);
  136.  
  137.  
  138. #endif
  139.  
  140. #define flush_tlb_kernel_range(start, end) flush_tlb_all()
  141.  
  142. static inline void flush_tlb_pgtables(struct mm_struct *mm,
  143.                       unsigned long start, unsigned long end)
  144. {
  145.     /* i386 does not keep any page table caches in TLB */
  146. }
  147.  
  148. #endif /* _I386_TLBFLUSH_H */
  149.