Message ID | 20210107092652.3438696-3-atish.patra@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Assorted fixes for RV32 | expand |
On Thu, Jan 7, 2021 at 2:57 PM Atish Patra <atish.patra@wdc.com> wrote: > > Currently, linux kernel can not use last 4k bytes of addressable space because > IS_ERR_VALUE macro treats those as an error. This will be an issue for RV32 > as any memblock allocator potentially allocate chunk of memory from the end > of DRAM (2GB) leading bad address error even though the address was technically > valid. > > Fix this issue by limiting the memblock if available memory spans the entire > address space. > > Signed-off-by: Atish Patra <atish.patra@wdc.com> > --- > arch/riscv/mm/init.c | 16 ++++++++++++++-- > 1 file changed, 14 insertions(+), 2 deletions(-) > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > index bf5379135e39..da53902ef0fc 100644 > --- a/arch/riscv/mm/init.c > +++ b/arch/riscv/mm/init.c > @@ -157,9 +157,10 @@ static void __init setup_initrd(void) > void __init setup_bootmem(void) > { > phys_addr_t mem_start = 0; > - phys_addr_t start, end = 0; > + phys_addr_t start, dram_end, end = 0; > phys_addr_t vmlinux_end = __pa_symbol(&_end); > phys_addr_t vmlinux_start = __pa_symbol(&_start); > + phys_addr_t max_mapped_addr = __pa(PHYS_ADDR_MAX); Using PHYS_ADDR_MAX as the max virtual address does not look right. Better use __pa(~(ulong)0) here. Otherwise looks good to me. Reviewed-by: Anup Patel <anup@brainfault.org> > u64 i; > > /* Find the memory region containing the kernel */ > @@ -181,7 +182,18 @@ void __init setup_bootmem(void) > /* Reserve from the start of the kernel to the end of the kernel */ > memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); > > - max_pfn = PFN_DOWN(memblock_end_of_DRAM()); > + dram_end = memblock_end_of_DRAM(); > + > + /* > + * memblock allocator is not aware of the fact that last 4K bytes of > + * the addressable memory can not be mapped because of IS_ERR_VALUE > + * macro. Make sure that last 4k bytes are not usable by memblock > + * if end of dram is equal to maximum addressable memory. > + */ > + if (max_mapped_addr == (dram_end - 1)) > + memblock_set_current_limit(max_mapped_addr - 4096); > + > + max_pfn = PFN_DOWN(dram_end); > max_low_pfn = max_pfn; > dma32_phys_limit = min(4UL * SZ_1G, (unsigned long)PFN_PHYS(max_low_pfn)); > set_max_mapnr(max_low_pfn); > -- > 2.25.1 > > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv Regards, Anup
On Sun, Jan 10, 2021 at 7:59 PM Anup Patel <anup@brainfault.org> wrote: > > On Thu, Jan 7, 2021 at 2:57 PM Atish Patra <atish.patra@wdc.com> wrote: > > > > Currently, linux kernel can not use last 4k bytes of addressable space because > > IS_ERR_VALUE macro treats those as an error. This will be an issue for RV32 > > as any memblock allocator potentially allocate chunk of memory from the end > > of DRAM (2GB) leading bad address error even though the address was technically > > valid. > > > > Fix this issue by limiting the memblock if available memory spans the entire > > address space. > > > > Signed-off-by: Atish Patra <atish.patra@wdc.com> > > --- > > arch/riscv/mm/init.c | 16 ++++++++++++++-- > > 1 file changed, 14 insertions(+), 2 deletions(-) > > > > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c > > index bf5379135e39..da53902ef0fc 100644 > > --- a/arch/riscv/mm/init.c > > +++ b/arch/riscv/mm/init.c > > @@ -157,9 +157,10 @@ static void __init setup_initrd(void) > > void __init setup_bootmem(void) > > { > > phys_addr_t mem_start = 0; > > - phys_addr_t start, end = 0; > > + phys_addr_t start, dram_end, end = 0; > > phys_addr_t vmlinux_end = __pa_symbol(&_end); > > phys_addr_t vmlinux_start = __pa_symbol(&_start); > > + phys_addr_t max_mapped_addr = __pa(PHYS_ADDR_MAX); > > Using PHYS_ADDR_MAX as the max virtual address does not look right. > > Better use __pa(~(ulong)0) here. Otherwise looks good to me. > ok will change it. Thanks for the review. > Reviewed-by: Anup Patel <anup@brainfault.org> > > > u64 i; > > > > /* Find the memory region containing the kernel */ > > @@ -181,7 +182,18 @@ void __init setup_bootmem(void) > > /* Reserve from the start of the kernel to the end of the kernel */ > > memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); > > > > - max_pfn = PFN_DOWN(memblock_end_of_DRAM()); > > + dram_end = memblock_end_of_DRAM(); > > + > > + /* > > + * memblock allocator is not aware of the fact that last 4K bytes of > > + * the addressable memory can not be mapped because of IS_ERR_VALUE > > + * macro. Make sure that last 4k bytes are not usable by memblock > > + * if end of dram is equal to maximum addressable memory. > > + */ > > + if (max_mapped_addr == (dram_end - 1)) > > + memblock_set_current_limit(max_mapped_addr - 4096); > > + > > + max_pfn = PFN_DOWN(dram_end); > > max_low_pfn = max_pfn; > > dma32_phys_limit = min(4UL * SZ_1G, (unsigned long)PFN_PHYS(max_low_pfn)); > > set_max_mapnr(max_low_pfn); > > -- > > 2.25.1 > > > > > > _______________________________________________ > > linux-riscv mailing list > > linux-riscv@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/linux-riscv > > Regards, > Anup > > _______________________________________________ > linux-riscv mailing list > linux-riscv@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-riscv
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index bf5379135e39..da53902ef0fc 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -157,9 +157,10 @@ static void __init setup_initrd(void) void __init setup_bootmem(void) { phys_addr_t mem_start = 0; - phys_addr_t start, end = 0; + phys_addr_t start, dram_end, end = 0; phys_addr_t vmlinux_end = __pa_symbol(&_end); phys_addr_t vmlinux_start = __pa_symbol(&_start); + phys_addr_t max_mapped_addr = __pa(PHYS_ADDR_MAX); u64 i; /* Find the memory region containing the kernel */ @@ -181,7 +182,18 @@ void __init setup_bootmem(void) /* Reserve from the start of the kernel to the end of the kernel */ memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start); - max_pfn = PFN_DOWN(memblock_end_of_DRAM()); + dram_end = memblock_end_of_DRAM(); + + /* + * memblock allocator is not aware of the fact that last 4K bytes of + * the addressable memory can not be mapped because of IS_ERR_VALUE + * macro. Make sure that last 4k bytes are not usable by memblock + * if end of dram is equal to maximum addressable memory. + */ + if (max_mapped_addr == (dram_end - 1)) + memblock_set_current_limit(max_mapped_addr - 4096); + + max_pfn = PFN_DOWN(dram_end); max_low_pfn = max_pfn; dma32_phys_limit = min(4UL * SZ_1G, (unsigned long)PFN_PHYS(max_low_pfn)); set_max_mapnr(max_low_pfn);
Currently, linux kernel can not use last 4k bytes of addressable space because IS_ERR_VALUE macro treats those as an error. This will be an issue for RV32 as any memblock allocator potentially allocate chunk of memory from the end of DRAM (2GB) leading bad address error even though the address was technically valid. Fix this issue by limiting the memblock if available memory spans the entire address space. Signed-off-by: Atish Patra <atish.patra@wdc.com> --- arch/riscv/mm/init.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)