[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20080208227.168531243@suse.de>
Date: Fri, 8 Feb 2008 14:27:44 +0100 (CET)
From: Andi Kleen <ak@...e.de>
To: mingo@...e.hu, tglx@...utronix.de, linux-kernel@...r.kernel.org
Subject: [PATCH] [1/5] CPA: Split static_protections into required_static_prot and advised_static_prot
There is a big difference between NX and RO. NX absolutely has to be cleared
or the kernel will fail while RO just can be set, but does not need to.
And for a large page area not setting NX if there is a area below
it that needs it is essential, while making it ro is optional again.
This is needed for a followup patch who uses requred_static_prot() for large
pages where it is inconvenient to check all pages.
No behaviour change in this patch.
[Lines > 80 characters are changed in followup patch]
Signed-off-by: Andi Kleen <ak@...e.de>
---
arch/x86/mm/pageattr.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
Index: linux/arch/x86/mm/pageattr.c
===================================================================
--- linux.orig/arch/x86/mm/pageattr.c
+++ linux/arch/x86/mm/pageattr.c
@@ -149,7 +149,7 @@ static unsigned long virt_to_highmap(voi
* right (again, ioremap() on BIOS memory is not uncommon) so this function
* checks and fixes these known static required protection bits.
*/
-static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
+static inline pgprot_t required_static_prot(pgprot_t prot, unsigned long address)
{
pgprot_t forbidden = __pgprot(0);
@@ -173,21 +173,25 @@ static inline pgprot_t static_protection
pgprot_val(forbidden) |= _PAGE_NX;
+ prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
+
+ return prot;
+}
+
+static inline pgprot_t advised_static_prot(pgprot_t prot, unsigned long address)
+{
#ifdef CONFIG_DEBUG_RODATA
/* The .rodata section needs to be read-only */
if (within(address, (unsigned long)__start_rodata,
(unsigned long)__end_rodata))
- pgprot_val(forbidden) |= _PAGE_RW;
+ pgprot_val(prot) &= ~_PAGE_RW;
/*
* Do the same for the x86-64 high kernel mapping
*/
if (within(address, virt_to_highmap(__start_rodata),
virt_to_highmap(__end_rodata)))
- pgprot_val(forbidden) |= _PAGE_RW;
+ pgprot_val(prot) &= ~_PAGE_RW;
#endif
-
- prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
-
return prot;
}
@@ -318,7 +322,8 @@ try_preserve_large_page(pte_t *kpte, uns
pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
- new_prot = static_protections(new_prot, address);
+ new_prot = required_static_prot(new_prot, address);
+ new_prot = advised_static_prot(new_prot, address);
/*
* If there are no changes, return. maxpages has been updated
@@ -456,7 +461,8 @@ repeat:
pgprot_val(new_prot) &= ~pgprot_val(cpa->mask_clr);
pgprot_val(new_prot) |= pgprot_val(cpa->mask_set);
- new_prot = static_protections(new_prot, address);
+ new_prot = required_static_prot(new_prot, address);
+ new_prot = advised_static_prot(new_prot, address);
/*
* We need to keep the pfn from the existing PTE,
@@ -546,7 +552,7 @@ static int change_page_attr_addr(struct
* for the non obvious details.
*
* Note that NX and other required permissions are
- * checked in static_protections().
+ * checked in required_static_prot().
*/
address = phys_addr + HIGH_MAP_START - phys_base;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists