From ff31452b6ea5032f26f16140d45dc6596260cd9c Mon Sep 17 00:00:00 2001
From: Thomas Gleixner <tglx@linutronix.de>
Date: Wed, 30 Jan 2008 13:34:08 +0100
Subject: [PATCH] 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>
---
 arch/x86/mm/pageattr.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

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.
-- 
GitLab