Skip to content

Commit 6a35d02

Browse files
Vasily Gorbikhcahca
authored andcommitted
s390/vmem: Support 2G page splitting for KASAN shadow freeing
Export split_pud_page() so it can be used from the vmem code and teach modify_pud_table() to split PUD-sized mappings when only a subrange needs to be removed. If the range to be removed covers a full PUD-sized mapping, keep the existing behavior: clear the PUD entry and free the backing large page (for non-direct mappings). Otherwise, split the PUD-mapped page into PMD mappings and let the walker handle the smaller ranges. This is needed for KASAN early shadow removal support: memory hotplug freeing the KASAN early shadow is the only expected caller that will try to free 2G PUD-mapped regions of non-direct mappings. Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Reviewed-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
1 parent 1442bb8 commit 6a35d02

3 files changed

Lines changed: 8 additions & 2 deletions

File tree

arch/s390/include/asm/page.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ static inline int page_reset_referenced(unsigned long addr)
166166
return CC_TRANSFORM(cc);
167167
}
168168

169+
int split_pud_page(pud_t *pudp, unsigned long addr);
170+
169171
/* Bits int the storage key */
170172
#define _PAGE_CHANGED 0x02 /* HW changed bit */
171173
#define _PAGE_REFERENCED 0x04 /* HW referenced bit */

arch/s390/mm/pageattr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ static int walk_pmd_level(pud_t *pudp, unsigned long addr, unsigned long end,
204204
return rc;
205205
}
206206

207-
static int split_pud_page(pud_t *pudp, unsigned long addr)
207+
int split_pud_page(pud_t *pudp, unsigned long addr)
208208
{
209209
unsigned long pmd_addr, prot;
210210
pmd_t *pm_dir, *pmdp;

arch/s390/mm/vmem.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,10 +330,14 @@ static int modify_pud_table(p4d_t *p4d, unsigned long addr, unsigned long end,
330330
if (pud_leaf(*pud)) {
331331
if (IS_ALIGNED(addr, PUD_SIZE) &&
332332
IS_ALIGNED(next, PUD_SIZE)) {
333+
if (!direct)
334+
vmem_free_pages(pud_deref(*pud), get_order(PUD_SIZE), altmap);
333335
pud_clear(pud);
334336
pages++;
337+
continue;
338+
} else {
339+
split_pud_page(pud, addr & PUD_MASK);
335340
}
336-
continue;
337341
}
338342
} else if (pud_none(*pud)) {
339343
if (IS_ALIGNED(addr, PUD_SIZE) &&

0 commit comments

Comments
 (0)