Thread (32 messages) 32 messages, 10 authors, 2025-03-15

Re: [PATCH 10/13] arch, mm: set high_memory in free_area_init()

From: "Russell King (Oracle)" <linux@armlinux.org.uk>
Date: 2025-03-11 22:00:20
Also in: linux-alpha, linux-arch, linux-m68k, linux-mips, linux-mm, linux-riscv, linux-s390, linux-sh, linux-um, lkml, loongarch, sparclinux

On Tue, Mar 11, 2025 at 05:51:06PM +0000, Mark Brown wrote:
On Thu, Mar 06, 2025 at 08:51:20PM +0200, Mike Rapoport wrote:
quoted
From: "Mike Rapoport (Microsoft)" <rppt@kernel.org>

high_memory defines upper bound on the directly mapped memory.
This bound is defined by the beginning of ZONE_HIGHMEM when a system has
high memory and by the end of memory otherwise.

All this is known to generic memory management initialization code that
can set high_memory while initializing core mm structures.

Remove per-architecture calculation of high_memory and add a generic
version to free_area_init().
This patch appears to be causing breakage on a number of 32 bit arm
platforms, including qemu's virt-2.11,gic-version=3.  Affected platforms
die on boot with no output, a bisect with qemu points at this commit and
those for physical platforms appear to be converging on the same place.
I'm not convinced that the old and the new code is doing the same
thing.

The new code:

+       phys_addr_t highmem = memblock_end_of_DRAM();
+
+#ifdef CONFIG_HIGHMEM
+       unsigned long pfn = arch_zone_lowest_possible_pfn[ZONE_HIGHMEM];
+
+       if (arch_has_descending_max_zone_pfns() || highmem > PFN_PHYS(pfn))
+               highmem = PFN_PHYS(pfn);
+#endif
+
+       high_memory = phys_to_virt(highmem - 1) + 1;

First, when CONFIG_HIGHMEM is disabled, this code assumes that the last
byte of DRAM declared to memblock is the highmem limit. This _could_
overflow phys_to_virt() and lead to an invalid value for high_memory.

Second, arch_zone_lowest_possible_pfn[ZONE_HIGHMEM] is the _start_ of
highmem. This is not what arch code sets high_memory to - because
the start of highmem may not contiguously follow on from lowmem.

In arch/arm/mm/mmu.c, lowmem_limit is computed to be the highest + 1
physical address that lowmem can possibly be, taking into account the
amount of vmalloc memory that is required. This is used to set
high_memory.

We also limit the amount of usable RAM via memblock_set_current_limit()
which memblock_end_of_DRAM() doesn't respect.

I don't think the proposed generic version is suitable for 32-bit arm.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help