aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-02-04 10:48:05 -0500
committerIngo Molnar <mingo@elte.hu>2008-02-04 10:48:05 -0500
commitcc0f21bbc12dc9f05b2e7f2469128f8717b2f4d3 (patch)
tree55ede62b277fae1fd836a843274561c235802fb4
parent16c02ed74361433a4fc5d8bd5f67abbac6e1c5ca (diff)
x86: teach the static_protection function about high mappings
Right now, enforcing that the high mapping of the kernel text doesn't get the NX bit is done deep in the guts of CPA, rather than in the static_protection() function that enforces all other per-arch sanity checks. This patch moves this sanity check into the central static_protection() function instead, and makes it apply ONLY to the kernel text, not to all other areas in the high mapping. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/mm/pageattr.c35
1 files changed, 31 insertions, 4 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 877b5cca2cb8..bf5e33f6a322 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -106,6 +106,22 @@ static void cpa_flush_range(unsigned long start, int numpages)
106 } 106 }
107} 107}
108 108
109#define HIGH_MAP_START __START_KERNEL_map
110#define HIGH_MAP_END (__START_KERNEL_map + KERNEL_TEXT_SIZE)
111
112
113/*
114 * Converts a virtual address to a X86-64 highmap address
115 */
116static unsigned long virt_to_highmap(void *address)
117{
118#ifdef CONFIG_X86_64
119 return __pa((unsigned long)address) + HIGH_MAP_START - phys_base;
120#else
121 return (unsigned long)address;
122#endif
123}
124
109/* 125/*
110 * Certain areas of memory on x86 require very specific protection flags, 126 * Certain areas of memory on x86 require very specific protection flags,
111 * for example the BIOS area or kernel text. Callers don't always get this 127 * for example the BIOS area or kernel text. Callers don't always get this
@@ -129,12 +145,24 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
129 */ 145 */
130 if (within(address, (unsigned long)_text, (unsigned long)_etext)) 146 if (within(address, (unsigned long)_text, (unsigned long)_etext))
131 pgprot_val(forbidden) |= _PAGE_NX; 147 pgprot_val(forbidden) |= _PAGE_NX;
148 /*
149 * Do the same for the x86-64 high kernel mapping
150 */
151 if (within(address, virt_to_highmap(_text), virt_to_highmap(_etext)))
152 pgprot_val(forbidden) |= _PAGE_NX;
153
132 154
133#ifdef CONFIG_DEBUG_RODATA 155#ifdef CONFIG_DEBUG_RODATA
134 /* The .rodata section needs to be read-only */ 156 /* The .rodata section needs to be read-only */
135 if (within(address, (unsigned long)__start_rodata, 157 if (within(address, (unsigned long)__start_rodata,
136 (unsigned long)__end_rodata)) 158 (unsigned long)__end_rodata))
137 pgprot_val(forbidden) |= _PAGE_RW; 159 pgprot_val(forbidden) |= _PAGE_RW;
160 /*
161 * Do the same for the x86-64 high kernel mapping
162 */
163 if (within(address, virt_to_highmap(__start_rodata),
164 virt_to_highmap(__end_rodata)))
165 pgprot_val(forbidden) |= _PAGE_RW;
138#endif 166#endif
139 167
140 prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); 168 prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
@@ -304,8 +332,6 @@ repeat:
304 * Modules and drivers should use the set_memory_* APIs instead. 332 * Modules and drivers should use the set_memory_* APIs instead.
305 */ 333 */
306 334
307#define HIGH_MAP_START __START_KERNEL_map
308#define HIGH_MAP_END (__START_KERNEL_map + KERNEL_TEXT_SIZE)
309 335
310static int 336static int
311change_page_attr_addr(unsigned long address, pgprot_t mask_set, 337change_page_attr_addr(unsigned long address, pgprot_t mask_set,
@@ -338,10 +364,11 @@ change_page_attr_addr(unsigned long address, pgprot_t mask_set,
338 /* 364 /*
339 * Calc the high mapping address. See __phys_addr() 365 * Calc the high mapping address. See __phys_addr()
340 * for the non obvious details. 366 * for the non obvious details.
367 *
368 * Note that NX and other required permissions are
369 * checked in static_protections().
341 */ 370 */
342 address = phys_addr + HIGH_MAP_START - phys_base; 371 address = phys_addr + HIGH_MAP_START - phys_base;
343 /* Make sure the kernel mappings stay executable */
344 pgprot_val(mask_clr) |= _PAGE_NX;
345 372
346 /* 373 /*
347 * Our high aliases are imprecise, because we check 374 * Our high aliases are imprecise, because we check