Commit 855ad0f7 authored by Palmer Dabbelt's avatar Palmer Dabbelt

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.deSigned-off-by: default avatarPalmer Dabbelt <palmer@rivosinc.com>
parents a2a4d4a6 fb1cf087
...@@ -683,6 +683,9 @@ void __init create_pgd_mapping(pgd_t *pgdp, ...@@ -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, static uintptr_t __init best_map_size(phys_addr_t pa, uintptr_t va,
phys_addr_t size) phys_addr_t size)
{ {
if (debug_pagealloc_enabled())
return PAGE_SIZE;
if (pgtable_l5_enabled && if (pgtable_l5_enabled &&
!(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE) !(pa & (P4D_SIZE - 1)) && !(va & (P4D_SIZE - 1)) && size >= P4D_SIZE)
return P4D_SIZE; return P4D_SIZE;
......
...@@ -387,17 +387,33 @@ int set_direct_map_default_noflush(struct page *page) ...@@ -387,17 +387,33 @@ int set_direct_map_default_noflush(struct page *page)
} }
#ifdef CONFIG_DEBUG_PAGEALLOC #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) void __kernel_map_pages(struct page *page, int numpages, int enable)
{ {
if (!debug_pagealloc_enabled()) if (!debug_pagealloc_enabled())
return; return;
if (enable) unsigned long start = (unsigned long)page_address(page);
__set_memory((unsigned long)page_address(page), numpages, unsigned long size = PAGE_SIZE * numpages;
__pgprot(_PAGE_PRESENT), __pgprot(0));
else apply_to_existing_page_range(&init_mm, start, size, debug_pagealloc_set_page, &enable);
__set_memory((unsigned long)page_address(page), numpages,
__pgprot(0), __pgprot(_PAGE_PRESENT)); flush_tlb_kernel_range(start, start + size);
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment