diff options
Diffstat (limited to 'arch/x86/mm/pageattr.c')
-rw-r--r-- | arch/x86/mm/pageattr.c | 35 |
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 | */ | ||
116 | static 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 | ||
310 | static int | 336 | static int |
311 | change_page_attr_addr(unsigned long address, pgprot_t mask_set, | 337 | change_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 |