aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-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