summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-02-04 16:48:07 +0100
committerIngo Molnar <mingo@elte.hu>2008-02-04 16:48:07 +0100
commitf4ae5da0e8e92caa168e7c2a7c4a6c4064b082c2 (patch)
treef4b3a98c7e9ea6d158bdc5bf5a479eaeb93c6957 /arch
parent72e458dfa63b3db7a46f66b0eb19e9ff4e17fc0e (diff)
x86: cpa, check if we changed anything and tlb flushing is necessary
Flush tlbs only when there was a real change. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/mm/pageattr.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index d1c08308ecbb..79a9f1b42ddd 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -21,6 +21,7 @@ struct cpa_data {
int numpages;
pgprot_t mask_set;
pgprot_t mask_clr;
+ int flushtlb;
};
static inline int
@@ -329,11 +330,19 @@ repeat:
* not the memory it points to
*/
new_pte = pfn_pte(pte_pfn(old_pte), canon_pgprot(new_prot));
- set_pte_atomic(kpte, new_pte);
+
+ /*
+ * Do we really change anything ?
+ */
+ if (pte_val(old_pte) != pte_val(new_pte)) {
+ set_pte_atomic(kpte, new_pte);
+ cpa->flushtlb = 1;
+ }
} else {
err = split_large_page(kpte, address);
if (!err)
goto repeat;
+ cpa->flushtlb = 1;
}
return err;
}
@@ -438,10 +447,17 @@ static int change_page_attr_set_clr(unsigned long addr, int numpages,
cpa.numpages = numpages;
cpa.mask_set = mask_set;
cpa.mask_clr = mask_clr;
+ cpa.flushtlb = 0;
ret = __change_page_attr_set_clr(&cpa);
/*
+ * Check whether we really changed something:
+ */
+ if (!cpa.flushtlb)
+ return ret;
+
+ /*
* No need to flush, when we did not set any of the caching
* attributes:
*/