diff options
author | Andi Kleen <ak@suse.de> | 2006-09-26 04:52:29 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-09-26 04:52:29 -0400 |
commit | b1c78c0fcc29097567e1afc39701012e6d89adb7 (patch) | |
tree | 9b9a2a302740c7a68003ade0536ab244f20cb08c /include/asm-x86_64/tlbflush.h | |
parent | 3f14c746a61ec932c204aca820c02c293118c5df (diff) |
[PATCH] Clean up and minor fixes to TLB flush
- Convert CR* accesses to dedicated inline functions and rewrite
the rest as C inlines
- Don't do a double flush for global flushes (pointed out by Zach Amsden)
This was a bug workaround for old CPUs that don't do 64bit and is obsolete.
- Add a proper memory clobber to invlpg
- Remove an unused extern
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'include/asm-x86_64/tlbflush.h')
-rw-r--r-- | include/asm-x86_64/tlbflush.h | 70 |
1 files changed, 35 insertions, 35 deletions
diff --git a/include/asm-x86_64/tlbflush.h b/include/asm-x86_64/tlbflush.h index d16d5b60f419..983bd296c81a 100644 --- a/include/asm-x86_64/tlbflush.h +++ b/include/asm-x86_64/tlbflush.h | |||
@@ -4,44 +4,44 @@ | |||
4 | #include <linux/mm.h> | 4 | #include <linux/mm.h> |
5 | #include <asm/processor.h> | 5 | #include <asm/processor.h> |
6 | 6 | ||
7 | #define __flush_tlb() \ | 7 | static inline unsigned long get_cr3(void) |
8 | do { \ | 8 | { |
9 | unsigned long tmpreg; \ | 9 | unsigned long cr3; |
10 | \ | 10 | asm volatile("mov %%cr3,%0" : "=r" (cr3)); |
11 | __asm__ __volatile__( \ | 11 | return cr3; |
12 | "movq %%cr3, %0; # flush TLB \n" \ | 12 | } |
13 | "movq %0, %%cr3; \n" \ | ||
14 | : "=r" (tmpreg) \ | ||
15 | :: "memory"); \ | ||
16 | } while (0) | ||
17 | 13 | ||
18 | /* | 14 | static inline void set_cr3(unsigned long cr3) |
19 | * Global pages have to be flushed a bit differently. Not a real | 15 | { |
20 | * performance problem because this does not happen often. | 16 | asm volatile("mov %0,%%cr3" :: "r" (cr3) : "memory"); |
21 | */ | 17 | } |
22 | #define __flush_tlb_global() \ | 18 | |
23 | do { \ | 19 | static inline void __flush_tlb(void) |
24 | unsigned long tmpreg, cr4, cr4_orig; \ | 20 | { |
25 | \ | 21 | set_cr3(get_cr3()); |
26 | __asm__ __volatile__( \ | 22 | } |
27 | "movq %%cr4, %2; # turn off PGE \n" \ | 23 | |
28 | "movq %2, %1; \n" \ | 24 | static inline unsigned long get_cr4(void) |
29 | "andq %3, %1; \n" \ | 25 | { |
30 | "movq %1, %%cr4; \n" \ | 26 | unsigned long cr4; |
31 | "movq %%cr3, %0; # flush TLB \n" \ | 27 | asm volatile("mov %%cr4,%0" : "=r" (cr4)); |
32 | "movq %0, %%cr3; \n" \ | 28 | return cr4; |
33 | "movq %2, %%cr4; # turn PGE back on \n" \ | 29 | } |
34 | : "=&r" (tmpreg), "=&r" (cr4), "=&r" (cr4_orig) \ | 30 | |
35 | : "i" (~X86_CR4_PGE) \ | 31 | static inline void set_cr4(unsigned long cr4) |
36 | : "memory"); \ | 32 | { |
37 | } while (0) | 33 | asm volatile("mov %0,%%cr4" :: "r" (cr4) : "memory"); |
38 | 34 | } | |
39 | extern unsigned long pgkern_mask; | 35 | |
40 | 36 | static inline void __flush_tlb_all(void) | |
41 | #define __flush_tlb_all() __flush_tlb_global() | 37 | { |
38 | unsigned long cr4 = get_cr4(); | ||
39 | set_cr4(cr4 & ~X86_CR4_PGE); /* clear PGE */ | ||
40 | set_cr4(cr4); /* write old PGE again and flush TLBs */ | ||
41 | } | ||
42 | 42 | ||
43 | #define __flush_tlb_one(addr) \ | 43 | #define __flush_tlb_one(addr) \ |
44 | __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr)) | 44 | __asm__ __volatile__("invlpg (%0)" :: "r" (addr) : "memory") |
45 | 45 | ||
46 | 46 | ||
47 | /* | 47 | /* |