With CONFIG_FLATMEM, pfn_to_page() is computed as: mem_map + (pfn - ARCH_PFN_OFFSET) LoongArch currently derives ARCH_PFN_OFFSET from PFN_UP(PHYS_OFFSET), while PHYS_OFFSET defaults to 0. On systems whose first DRAM range does not start at physical address 0, ARCH_PFN_OFFSET becomes smaller than the real RAM base PFN. As a result, pfn_to_page() points past the intended mem_map base during early memmap initialization. This causes struct page initialization to touch wrong entries and can lead to early boot failures in the memmap_init_range() path. Fix this by deriving ARCH_PFN_OFFSET from min_low_pfn, and initialize/ recalculate min_low_pfn from memblock_start_of_DRAM() in LoongArch memory init so PFN-to-page translation matches the actual DRAM base. This change only fixes the FLATMEM PFN base and does not alter the existing VA/PA linear mapping scheme. Signed-off-by: Ethan Yang --- v2: - Fixed tab-to-space formatting. --- arch/loongarch/include/asm/page.h | 3 ++- arch/loongarch/kernel/mem.c | 1 + arch/loongarch/kernel/setup.c | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h index 327bf0bc9..80aea8b51 100644 --- a/arch/loongarch/include/asm/page.h +++ b/arch/loongarch/include/asm/page.h @@ -25,7 +25,8 @@ * used in our early mem init code for all memory models. * So always define it. */ -#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET) +extern unsigned long min_low_pfn; +#define ARCH_PFN_OFFSET min_low_pfn extern void clear_page(void *page); extern void copy_page(void *to, void *from); diff --git a/arch/loongarch/kernel/mem.c b/arch/loongarch/kernel/mem.c index 8ab1ffedc..03835f8cb 100644 --- a/arch/loongarch/kernel/mem.c +++ b/arch/loongarch/kernel/mem.c @@ -46,6 +46,7 @@ void __init memblock_init(void) } } + min_low_pfn = PFN_UP(memblock_start_of_DRAM()); max_pfn = PFN_DOWN(memblock_end_of_DRAM()); max_low_pfn = min(PFN_DOWN(HIGHMEM_START), max_pfn); memblock_set_current_limit(PFN_PHYS(max_low_pfn)); diff --git a/arch/loongarch/kernel/setup.c b/arch/loongarch/kernel/setup.c index 839b23ede..625be2494 100644 --- a/arch/loongarch/kernel/setup.c +++ b/arch/loongarch/kernel/setup.c @@ -394,6 +394,7 @@ static void __init check_kernel_sections_mem(void) static void __init arch_mem_init(char **cmdline_p) { /* Recalculate max_low_pfn for "mem=xxx" */ + min_low_pfn = PFN_UP(memblock_start_of_DRAM()); max_pfn = PFN_DOWN(memblock_end_of_DRAM()); max_low_pfn = min(PFN_DOWN(HIGHMEM_START), max_pfn); -- 2.47.3