Skip to content

Commit 0490d6d

Browse files
hcahcaVasily Gorbik
authored andcommitted
s390/mm: enable ARCH_HAS_SET_DIRECT_MAP
Implement the set_direct_map_*() API, which allows to invalidate and set default permissions to pages within the direct mapping. Note that kernel_page_present(), which is also supposed to be part of this API, is intentionally not implemented. The reason for this is that kernel_page_present() is only used (and currently only makes sense) for suspend/resume, which isn't supported on s390. Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
1 parent 17c51b1 commit 0490d6d

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

arch/s390/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ config S390
7777
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
7878
select ARCH_HAS_PTE_SPECIAL
7979
select ARCH_HAS_SCALED_CPUTIME
80+
select ARCH_HAS_SET_DIRECT_MAP
8081
select ARCH_HAS_SET_MEMORY
8182
select ARCH_HAS_STRICT_KERNEL_RWX
8283
select ARCH_HAS_STRICT_MODULE_RWX

arch/s390/include/asm/set_memory.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ enum {
1212
_SET_MEMORY_NX_BIT,
1313
_SET_MEMORY_X_BIT,
1414
_SET_MEMORY_4K_BIT,
15+
_SET_MEMORY_INV_BIT,
16+
_SET_MEMORY_DEF_BIT,
1517
};
1618

1719
#define SET_MEMORY_RO BIT(_SET_MEMORY_RO_BIT)
1820
#define SET_MEMORY_RW BIT(_SET_MEMORY_RW_BIT)
1921
#define SET_MEMORY_NX BIT(_SET_MEMORY_NX_BIT)
2022
#define SET_MEMORY_X BIT(_SET_MEMORY_X_BIT)
2123
#define SET_MEMORY_4K BIT(_SET_MEMORY_4K_BIT)
24+
#define SET_MEMORY_INV BIT(_SET_MEMORY_INV_BIT)
25+
#define SET_MEMORY_DEF BIT(_SET_MEMORY_DEF_BIT)
2226

2327
int __set_memory(unsigned long addr, int numpages, unsigned long flags);
2428

@@ -58,4 +62,7 @@ static inline int set_memory_4k(unsigned long addr, int numpages)
5862
return __set_memory(addr, numpages, SET_MEMORY_4K);
5963
}
6064

65+
int set_direct_map_invalid_noflush(struct page *page);
66+
int set_direct_map_default_noflush(struct page *page);
67+
6168
#endif

arch/s390/mm/pageattr.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
55
*/
66
#include <linux/hugetlb.h>
7+
#include <linux/vmalloc.h>
78
#include <linux/mm.h>
89
#include <asm/cacheflush.h>
910
#include <asm/facility.h>
@@ -101,6 +102,14 @@ static int walk_pte_level(pmd_t *pmdp, unsigned long addr, unsigned long end,
101102
new = set_pte_bit(new, __pgprot(_PAGE_NOEXEC));
102103
else if (flags & SET_MEMORY_X)
103104
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+
}
104113
pgt_set((unsigned long *)ptep, pte_val(new), addr, CRDTE_DTT_PAGE);
105114
ptep++;
106115
addr += PAGE_SIZE;
@@ -151,6 +160,14 @@ static void modify_pmd_page(pmd_t *pmdp, unsigned long addr,
151160
new = set_pmd_bit(new, __pgprot(_SEGMENT_ENTRY_NOEXEC));
152161
else if (flags & SET_MEMORY_X)
153162
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+
}
154171
pgt_set((unsigned long *)pmdp, pmd_val(new), addr, CRDTE_DTT_SEGMENT);
155172
}
156173

@@ -232,6 +249,14 @@ static void modify_pud_page(pud_t *pudp, unsigned long addr,
232249
new = set_pud_bit(new, __pgprot(_REGION_ENTRY_NOEXEC));
233250
else if (flags & SET_MEMORY_X)
234251
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+
}
235260
pgt_set((unsigned long *)pudp, pud_val(new), addr, CRDTE_DTT_REGION3);
236261
}
237262

@@ -325,6 +350,16 @@ int __set_memory(unsigned long addr, int numpages, unsigned long flags)
325350
return change_page_attr(addr, addr + numpages * PAGE_SIZE, flags);
326351
}
327352

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+
328363
#if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KFENCE)
329364

330365
static void ipte_range(pte_t *pte, unsigned long address, int nr)

0 commit comments

Comments
 (0)