summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-01-30 13:34:08 +0100
committerIngo Molnar <mingo@elte.hu>2008-01-30 13:34:08 +0100
commitff31452b6ea5032f26f16140d45dc6596260cd9c (patch)
treeb18035ad80e0286737490fdac2f037e1451c92a7
parent72932c7ad2cc309b0ba6149aa31faa26aaee54d5 (diff)
x86: cpa create set_and_clr function
Create a set_and_clr function to avoid the duplicate loops. Allows also to do combined operations for optimization. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/mm/pageattr.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 55f5b5cdb12e..c54832b75069 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -282,6 +282,45 @@ static int change_page_attr_addr(unsigned long address, pgprot_t prot)
return err;
}
+static int __change_page_attr_set_clr(unsigned long addr, int numpages,
+ pgprot_t mask_set, pgprot_t mask_clr)
+{
+ pgprot_t new_prot;
+ int level;
+ pte_t *pte;
+ int i, ret;
+
+ for (i = 0; i < numpages ; i++) {
+
+ pte = lookup_address(addr, &level);
+ if (!pte)
+ return -EINVAL;
+
+ new_prot = pte_pgprot(*pte);
+
+ pgprot_val(new_prot) &= ~pgprot_val(mask_clr);
+ pgprot_val(new_prot) |= pgprot_val(mask_set);
+
+ ret = change_page_attr_addr(addr, new_prot);
+ if (ret)
+ return ret;
+ addr += PAGE_SIZE;
+ }
+
+ return 0;
+}
+
+static int change_page_attr_set_clr(unsigned long addr, int numpages,
+ pgprot_t mask_set, pgprot_t mask_clr)
+{
+ int ret = __change_page_attr_set_clr(addr, numpages, mask_set,
+ mask_clr);
+
+ global_flush_tlb();
+
+ return ret;
+}
+
/**
* change_page_attr_set - Change page table attributes in the linear mapping.
* @addr: Virtual address in linear mapping.