diff options
author | Palmer Dabbelt <palmer@rivosinc.com> | 2024-05-22 09:15:12 -0700 |
---|---|---|
committer | Palmer Dabbelt <palmer@rivosinc.com> | 2024-05-22 16:12:50 -0700 |
commit | 855ad0f7a167304936ce42e9d0737bbecfa8b6de (patch) | |
tree | 981adf56ee36e26d619f7c3e8e9dc921c7698e83 /arch/riscv | |
parent | a2a4d4a6a0bf5eba66f8b0b32502cc20d82715a0 (diff) | |
parent | fb1cf0878328fe75d47f0aed0a65b30126fcefc4 (diff) |
Merge patch series "riscv: fix debug_pagealloc"
Nam Cao <namcao@linutronix.de> says:
The debug_pagealloc feature is not functional on RISCV. With this feature
enabled (CONFIG_DEBUG_PAGEALLOC=y and debug_pagealloc=on), kernel crashes
early during boot.
QEMU command that can reproduce this problem:
qemu-system-riscv64 -machine virt \
-kernel Image \
-append "console=ttyS0 root=/dev/vda debug_pagealloc=on" \
-nographic \
-drive "file=root.img,format=raw,id=hd0" \
-device virtio-blk-device,drive=hd0 \
-m 4G \
This series makes debug_pagealloc functional.
* b4-shazam-merge:
riscv: rewrite __kernel_map_pages() to fix sleeping in invalid context
riscv: force PAGE_SIZE linear mapping if debug_pagealloc is enabled
Link: https://lore.kernel.org/r/cover.1715750938.git.namcao@linutronix.de
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv')
-rw-r--r-- | arch/riscv/mm/init.c | 3 | ||||
-rw-r--r-- | arch/riscv/mm/pageattr.c | 28 |
2 files changed, 25 insertions, 6 deletions
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 7e12925fc660..e3218d65f21d 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -683,6 +683,9 @@ void __init create_pgd_mapping(pgd_t *pgdp, static uintptr_t __init best_map_size(phys_addr_t pa, uintptr_t va, phys_addr_t size) { + if (debug_pagealloc_enabled()) + return PAGE_SIZE; + if (pgtable_l5_enabled && !(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE) return P4D_SIZE; diff --git a/arch/riscv/mm/pageattr.c b/arch/riscv/mm/pageattr.c index 410056a50aa9..271d01a5ba4d 100644 --- a/arch/riscv/mm/pageattr.c +++ b/arch/riscv/mm/pageattr.c @@ -387,17 +387,33 @@ int set_direct_map_default_noflush(struct page *page) } #ifdef CONFIG_DEBUG_PAGEALLOC +static int debug_pagealloc_set_page(pte_t *pte, unsigned long addr, void *data) +{ + int enable = *(int *)data; + + unsigned long val = pte_val(ptep_get(pte)); + + if (enable) + val |= _PAGE_PRESENT; + else + val &= ~_PAGE_PRESENT; + + set_pte(pte, __pte(val)); + + return 0; +} + void __kernel_map_pages(struct page *page, int numpages, int enable) { if (!debug_pagealloc_enabled()) return; - if (enable) - __set_memory((unsigned long)page_address(page), numpages, - __pgprot(_PAGE_PRESENT), __pgprot(0)); - else - __set_memory((unsigned long)page_address(page), numpages, - __pgprot(0), __pgprot(_PAGE_PRESENT)); + unsigned long start = (unsigned long)page_address(page); + unsigned long size = PAGE_SIZE * numpages; + + apply_to_existing_page_range(&init_mm, start, size, debug_pagealloc_set_page, &enable); + + flush_tlb_kernel_range(start, start + size); } #endif |