aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/pageattr.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-01-30 07:34:08 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:34:08 -0500
commit57a6a46aa26d6e39c62daf8b3b96e94f76e6846f (patch)
treeaab1dc72f7048da7eda699cb52ae1430738c1c03 /arch/x86/mm/pageattr.c
parent56744546b3e5379177a70e7306c6283f727e4732 (diff)
x86: cpa: implement clflush optimization
Use clflush on CPUs which support this. clflush is only used when the page attribute operation has been successful. On CPUs which do not support clflush and in the case of error the old fashioned global_flush_tlb() is called. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r--arch/x86/mm/pageattr.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 7823adab96e4..bbe691dd272e 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -52,6 +52,37 @@ static void global_flush_tlb(void)
52 on_each_cpu(flush_kernel_map, NULL, 1, 1); 52 on_each_cpu(flush_kernel_map, NULL, 1, 1);
53} 53}
54 54
55struct clflush_data {
56 unsigned long addr;
57 int numpages;
58};
59
60static void __cpa_flush_range(void *arg)
61{
62 struct clflush_data *cld = arg;
63
64 /*
65 * We could optimize that further and do individual per page
66 * tlb invalidates for a low number of pages. Caveat: we must
67 * flush the high aliases on 64bit as well.
68 */
69 __flush_tlb_all();
70
71 clflush_cache_range((void *) cld->addr, cld->numpages * PAGE_SIZE);
72}
73
74static void cpa_flush_range(unsigned long addr, int numpages)
75{
76 struct clflush_data cld;
77
78 BUG_ON(irqs_disabled());
79
80 cld.addr = addr;
81 cld.numpages = numpages;
82
83 on_each_cpu(__cpa_flush_range, &cld, 1, 1);
84}
85
55/* 86/*
56 * Certain areas of memory on x86 require very specific protection flags, 87 * Certain areas of memory on x86 require very specific protection flags,
57 * for example the BIOS area or kernel text. Callers don't always get this 88 * for example the BIOS area or kernel text. Callers don't always get this
@@ -316,7 +347,16 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
316 int ret = __change_page_attr_set_clr(addr, numpages, mask_set, 347 int ret = __change_page_attr_set_clr(addr, numpages, mask_set,
317 mask_clr); 348 mask_clr);
318 349
319 global_flush_tlb(); 350 /*
351 * On success we use clflush, when the CPU supports it to
352 * avoid the wbindv. If the CPU does not support it and in the
353 * error case we fall back to global_flush_tlb (which uses
354 * wbindv):
355 */
356 if (!ret && cpu_has_clflush)
357 cpa_flush_range(addr, numpages);
358 else
359 global_flush_tlb();
320 360
321 return ret; 361 return ret;
322} 362}