aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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}