diff options
author | Andi Kleen <ak@suse.de> | 2006-12-06 20:14:05 -0500 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2006-12-06 20:14:05 -0500 |
commit | 3760dd6efa75c98e223643da2eb7040406433053 (patch) | |
tree | 2af24364ffedbf2c21c975c028d7fee80da28335 /arch | |
parent | 770d132f03ac15b12919f1bac481f4beda13e094 (diff) |
[PATCH] i386: Use CLFLUSH instead of WBINVD in change_page_attr
CLFLUSH is a lot faster than WBINVD so try to use that.
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/mm/pageattr.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/arch/i386/mm/pageattr.c b/arch/i386/mm/pageattr.c index 8564b6ae17e3..ad91528bdc14 100644 --- a/arch/i386/mm/pageattr.c +++ b/arch/i386/mm/pageattr.c | |||
@@ -67,11 +67,17 @@ static struct page *split_large_page(unsigned long address, pgprot_t prot, | |||
67 | return base; | 67 | return base; |
68 | } | 68 | } |
69 | 69 | ||
70 | static void flush_kernel_map(void *dummy) | 70 | static void flush_kernel_map(void *arg) |
71 | { | 71 | { |
72 | /* Could use CLFLUSH here if the CPU supports it (Hammer,P4) */ | 72 | unsigned long adr = (unsigned long)arg; |
73 | if (boot_cpu_data.x86_model >= 4) | 73 | |
74 | if (adr && cpu_has_clflush) { | ||
75 | int i; | ||
76 | for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) | ||
77 | asm volatile("clflush (%0)" :: "r" (adr + i)); | ||
78 | } else if (boot_cpu_data.x86_model >= 4) | ||
74 | wbinvd(); | 79 | wbinvd(); |
80 | |||
75 | /* Flush all to work around Errata in early athlons regarding | 81 | /* Flush all to work around Errata in early athlons regarding |
76 | * large page flushing. | 82 | * large page flushing. |
77 | */ | 83 | */ |
@@ -173,9 +179,9 @@ __change_page_attr(struct page *page, pgprot_t prot) | |||
173 | return 0; | 179 | return 0; |
174 | } | 180 | } |
175 | 181 | ||
176 | static inline void flush_map(void) | 182 | static inline void flush_map(void *adr) |
177 | { | 183 | { |
178 | on_each_cpu(flush_kernel_map, NULL, 1, 1); | 184 | on_each_cpu(flush_kernel_map, adr, 1, 1); |
179 | } | 185 | } |
180 | 186 | ||
181 | /* | 187 | /* |
@@ -217,9 +223,13 @@ void global_flush_tlb(void) | |||
217 | spin_lock_irq(&cpa_lock); | 223 | spin_lock_irq(&cpa_lock); |
218 | list_replace_init(&df_list, &l); | 224 | list_replace_init(&df_list, &l); |
219 | spin_unlock_irq(&cpa_lock); | 225 | spin_unlock_irq(&cpa_lock); |
220 | flush_map(); | 226 | if (!cpu_has_clflush) |
221 | list_for_each_entry_safe(pg, next, &l, lru) | 227 | flush_map(0); |
228 | list_for_each_entry_safe(pg, next, &l, lru) { | ||
229 | if (cpu_has_clflush) | ||
230 | flush_map(page_address(pg)); | ||
222 | __free_page(pg); | 231 | __free_page(pg); |
232 | } | ||
223 | } | 233 | } |
224 | 234 | ||
225 | #ifdef CONFIG_DEBUG_PAGEALLOC | 235 | #ifdef CONFIG_DEBUG_PAGEALLOC |