|
4 | 4 | * Author(s): Jan Glauber <jang@linux.vnet.ibm.com> |
5 | 5 | */ |
6 | 6 | #include <linux/hugetlb.h> |
| 7 | +#include <linux/vmalloc.h> |
7 | 8 | #include <linux/mm.h> |
8 | 9 | #include <asm/cacheflush.h> |
9 | 10 | #include <asm/facility.h> |
@@ -101,6 +102,14 @@ static int walk_pte_level(pmd_t *pmdp, unsigned long addr, unsigned long end, |
101 | 102 | new = set_pte_bit(new, __pgprot(_PAGE_NOEXEC)); |
102 | 103 | else if (flags & SET_MEMORY_X) |
103 | 104 | new = clear_pte_bit(new, __pgprot(_PAGE_NOEXEC)); |
| 105 | + if (flags & SET_MEMORY_INV) { |
| 106 | + new = set_pte_bit(new, __pgprot(_PAGE_INVALID)); |
| 107 | + } else if (flags & SET_MEMORY_DEF) { |
| 108 | + new = __pte(pte_val(new) & PAGE_MASK); |
| 109 | + new = set_pte_bit(new, PAGE_KERNEL); |
| 110 | + if (!MACHINE_HAS_NX) |
| 111 | + new = clear_pte_bit(new, __pgprot(_PAGE_NOEXEC)); |
| 112 | + } |
104 | 113 | pgt_set((unsigned long *)ptep, pte_val(new), addr, CRDTE_DTT_PAGE); |
105 | 114 | ptep++; |
106 | 115 | addr += PAGE_SIZE; |
@@ -151,6 +160,14 @@ static void modify_pmd_page(pmd_t *pmdp, unsigned long addr, |
151 | 160 | new = set_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_NOEXEC)); |
152 | 161 | else if (flags & SET_MEMORY_X) |
153 | 162 | new = clear_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_NOEXEC)); |
| 163 | + if (flags & SET_MEMORY_INV) { |
| 164 | + new = set_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_INVALID)); |
| 165 | + } else if (flags & SET_MEMORY_DEF) { |
| 166 | + new = __pmd(pmd_val(new) & PMD_MASK); |
| 167 | + new = set_pmd_bit(new, SEGMENT_KERNEL); |
| 168 | + if (!MACHINE_HAS_NX) |
| 169 | + new = clear_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_NOEXEC)); |
| 170 | + } |
154 | 171 | pgt_set((unsigned long *)pmdp, pmd_val(new), addr, CRDTE_DTT_SEGMENT); |
155 | 172 | } |
156 | 173 |
|
@@ -232,6 +249,14 @@ static void modify_pud_page(pud_t *pudp, unsigned long addr, |
232 | 249 | new = set_pud_bit(new, __pgprot(_REGION_ENTRY_NOEXEC)); |
233 | 250 | else if (flags & SET_MEMORY_X) |
234 | 251 | new = clear_pud_bit(new, __pgprot(_REGION_ENTRY_NOEXEC)); |
| 252 | + if (flags & SET_MEMORY_INV) { |
| 253 | + new = set_pud_bit(new, __pgprot(_REGION_ENTRY_INVALID)); |
| 254 | + } else if (flags & SET_MEMORY_DEF) { |
| 255 | + new = __pud(pud_val(new) & PUD_MASK); |
| 256 | + new = set_pud_bit(new, REGION3_KERNEL); |
| 257 | + if (!MACHINE_HAS_NX) |
| 258 | + new = clear_pud_bit(new, __pgprot(_REGION_ENTRY_NOEXEC)); |
| 259 | + } |
235 | 260 | pgt_set((unsigned long *)pudp, pud_val(new), addr, CRDTE_DTT_REGION3); |
236 | 261 | } |
237 | 262 |
|
@@ -325,6 +350,16 @@ int __set_memory(unsigned long addr, int numpages, unsigned long flags) |
325 | 350 | return change_page_attr(addr, addr + numpages * PAGE_SIZE, flags); |
326 | 351 | } |
327 | 352 |
|
| 353 | +int set_direct_map_invalid_noflush(struct page *page) |
| 354 | +{ |
| 355 | + return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_INV); |
| 356 | +} |
| 357 | + |
| 358 | +int set_direct_map_default_noflush(struct page *page) |
| 359 | +{ |
| 360 | + return __set_memory((unsigned long)page_to_virt(page), 1, SET_MEMORY_DEF); |
| 361 | +} |
| 362 | + |
328 | 363 | #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE) |
329 | 364 |
|
330 | 365 | static void ipte_range(pte_t *pte, unsigned long address, int nr) |
|
0 commit comments