On November 12, 2026 3:25:27 AM PST, Arnd Bergmann <[email protected]> wrote: >From: Arnd Bergmann <[email protected]> > >Most of the common 32-bit architectures (x86, arm, powerpc) all use the >default virtual memory layout that was already in place for i386 systems >in the 1990s, using exactly 3GiB of user TASK_SIZE, with the upper 1GiB >of addresses split between (at most 896MiB) lowmem and vmalloc. > >Linux-2.3 introduced CONFIG_HIGHMEM for large x86 server machines that >had 4GiB of RAM or more, with the VMSPLIT_3G/2G/1G options added in >v2.6.16 for machines that had one or two gigabytes of memory but wanted >to avoid the overhead from managing highmem. Over time, similar options >appeared on other 32-bit architectures. > >Twenty years later, it makes sense to reconsider the default settings, >as the tradeoffs have changed a bit: > > - Configurations with more than 2GiB have become extremely rare, > as any users with large memory have moved on to 64-bit systems. > There were only ever a few Laptop models in this category: Apple > Powerbook G4 (2005), Macbook (2006), IBM Thinkpad X60 (2006), Arm > Chromebooks based on Exynos 5800 (2014), Tegra K1 (2014) and RK3288 > (2015), and manufacturer support for all of these has ended in 2020 > or (much) earlier. > Embedded systems with more than 2GiB use additional SoCs of a > similar vintage: Intel Atom Z5xx (2008), Freescale QorIQ (2008), > Marvell Armada XP (2010), Freescale i.MX6Q (2011), LSI Axxia (2013), > TI Keystone2 (2014), Renesas RZ/G1M (2015). Most boards based on > these have stopped receiving kernel upgrades and later 32-bit chips > only support smaller memory configurations, though in particular the > i.MX6Q and Keystone2 families have expected support cycles past 2035. > While 32-bit server installations used to support even larger memory, > none of those seem to still be used in production on any architecture. > > - While general-purpose distributes for 32-bit targets were common, > it was rather risky to change the CONFIG_VMSPLIT setting because > there is always a possibility of running into device driver bugs or > applications that need a large virtual memory size. Presumably > a lot of these issues have been resolved now, so most setups should > be fine using a custom vmsplit instead of highmem now. > > - As fewer users test highmem, the expectation is that it will > increasingly break in the future, so getting users to change the > vmsplit means that even if there is a bug to fix initially, > it improves the situation in the long run. > > - Highmem will ultimately need to be removed, at least for the page > cache and most other code using it today. In a previous discussion, I > had suggested doing this as early as 2029, but based on the discussions > since ELC, the plan is now to leave highmem-enabled page cache as an > option until at least 2029, at which point remaining users will have > the choice between no longer updating kernels or using a combination of > a custom vmsplit and zram/zswap. Changing the defaults now should both > speed up the highmem deprecation and make it less painful for users. > > - The most VM space intensive applications tend to be web browsers, > specifcally Chrome/ChromeOS and Firefox. Both have now stopped > providing binary updates. > Testing various combinations on Debian/armhf, I found that Firefox 140 > can still show complex websites with VMSPLIT_2G_OPT with and without > HIGHMEM, though it failed for me both with the small address space > of VMSPLIT_1G and the small lowmem of VMSPLIT_3G_OPT when HIGHMEM > is disabled. > This is likely to get worse with future versions, so embedded users > may still be forced to migrate to specialized browsers like WPE Webkit > when HIGHMEM pagecache is finally removed. > >Based on the above observations and the discussion at the kernel summit, >change the defaults to the most appropriate values: use 1GiB of lowmem on >non-highmem configurations, and either 2GiB or 1.75GiB of lowmem on highmem >builds, depending on what is available on the architecture. As ARM_LPAE >and X86_PAE builds both require a gigabyte-aligned vmsplit, those get >to use VMSPLIT_2G. The result is that the majority of previous highmem >users now only need lowmem. For platform specific defconfig files that >are known to only support up to 1GiB of RAM, drop the CONFIG_HIGHMEM line >as well as a simplification. > >On PowerPC and Microblaze, the options have somewhat different names but >should have the same effect. MIPS and Xtensa cannot support a larger >than 512MB of lowmem but are limited to small DDR2 memory in most >implementations, with MT7621 being a notable exception. ARC and C-Sky >could support a configurable vmsplit in theory, but it's not clear >if anyone still cares. >SPARC is currently limited to 192MB of lowmem and should get patched >to behave either like arm/x86 or powerpc/microblaze to support 2GiB >of lowmem. > >There are likely going to be regressions from the changed defaults, >in particular when hitting previously hidden device driver bugs >that fail to set the correct DMA mask, or from applications that >need a large virtual address space. >Ideally the in-kernel problems should all be fixable, but as a fallback, >the previous behavior is still selectable based on CONFIG_EXPERT=y. > >Cc: Russell King <[email protected]> >Cc: [email protected] >Cc: Thomas Gleixner <[email protected]> >Cc: Ingo Molnar <[email protected]> >Cc: Borislav Petkov <[email protected]> >Cc: Dave Hansen <[email protected]> >Cc: [email protected] >Cc: "H. Peter Anvin" <[email protected]> >Cc: Madhavan Srinivasan <[email protected]> >Cc: Michael Ellerman <[email protected]> >Cc: Nicholas Piggin <[email protected]> >Cc: Christophe Leroy (CS GROUP) <[email protected]> >Cc: [email protected] >Cc: Michal Simek <[email protected]> >Cc: Andrew Morton <[email protected]> >Cc: David Hildenbrand <[email protected]> >Cc: Lorenzo Stoakes <[email protected]> >Cc: Liam R. Howlett <[email protected]> >Cc: Vlastimil Babka <[email protected]> >Cc: Mike Rapoport <[email protected]> >Cc: Suren Baghdasaryan <[email protected]> >Cc: Michal Hocko <[email protected]> >Cc: Matthew Wilcox <[email protected]> >Cc: [email protected] >Cc: Richard Weinberger <[email protected]> >Cc: Linus Walleij <[email protected]> >Cc: Nishanth Menon <[email protected]> >Cc: Andreas Larsson <[email protected]> >Cc: Lucas Stach <[email protected]> >Signed-off-by: Arnd Bergmann <[email protected]> >--- > arch/arm/Kconfig | 5 ++++- > arch/arm/configs/aspeed_g5_defconfig | 1 - > arch/arm/configs/u8500_defconfig | 1 - > arch/arm/configs/vt8500_v6_v7_defconfig | 2 -- > arch/arm/mach-omap2/Kconfig | 1 - > arch/microblaze/Kconfig | 9 ++++++--- > arch/microblaze/configs/mmu_defconfig | 1 - > arch/powerpc/Kconfig | 14 +++++++++----- > arch/powerpc/configs/44x/akebono_defconfig | 1 - > arch/powerpc/configs/85xx/ksi8560_defconfig | 1 - > arch/powerpc/configs/85xx/stx_gp3_defconfig | 1 - > arch/x86/Kconfig | 4 +++- > 12 files changed, 22 insertions(+), 19 deletions(-) > >diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig >index fc66d52d847e..797705a94b28 100644 >--- a/arch/arm/Kconfig >+++ b/arch/arm/Kconfig >@@ -1025,7 +1025,8 @@ config BL_SWITCHER_DUMMY_IF > choice > prompt "Memory split" > depends on MMU >- default VMSPLIT_3G >+ default VMSPLIT_2G if HIGHMEM || ARM_LPAE >+ default VMSPLIT_3G_OPT > help > Select the desired split between kernel and user memory. > >@@ -1034,8 +1035,10 @@ choice > > config VMSPLIT_3G > bool "3G/1G user/kernel split" >+ depends on !HIGHMEM || EXPERT > config VMSPLIT_3G_OPT > depends on !ARM_LPAE >+ depends on !HIGHMEM || EXPERT > bool "3G/1G user/kernel split (for full 1G low memory)" > config VMSPLIT_2G > bool "2G/2G user/kernel split" >diff --git a/arch/arm/configs/aspeed_g5_defconfig >b/arch/arm/configs/aspeed_g5_defconfig >index 1327a09e163a..7f077c667478 100644 >--- a/arch/arm/configs/aspeed_g5_defconfig >+++ b/arch/arm/configs/aspeed_g5_defconfig >@@ -27,7 +27,6 @@ CONFIG_SMP=y > # CONFIG_ARM_CPU_TOPOLOGY is not set > CONFIG_VMSPLIT_2G=y > CONFIG_NR_CPUS=2 >-CONFIG_HIGHMEM=y > CONFIG_UACCESS_WITH_MEMCPY=y > CONFIG_VFP=y > CONFIG_NEON=y >diff --git a/arch/arm/configs/u8500_defconfig >b/arch/arm/configs/u8500_defconfig >index 2fe25f5eb9a5..b284c2c31758 100644 >--- a/arch/arm/configs/u8500_defconfig >+++ b/arch/arm/configs/u8500_defconfig >@@ -6,7 +6,6 @@ CONFIG_KALLSYMS_ALL=y > CONFIG_ARCH_U8500=y > CONFIG_SMP=y > CONFIG_NR_CPUS=2 >-CONFIG_HIGHMEM=y > CONFIG_ARM_APPENDED_DTB=y > CONFIG_ARM_ATAG_DTB_COMPAT=y > CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8" >diff --git a/arch/arm/configs/vt8500_v6_v7_defconfig >b/arch/arm/configs/vt8500_v6_v7_defconfig >index 2925a1f1dbb6..1f6dca21d569 100644 >--- a/arch/arm/configs/vt8500_v6_v7_defconfig >+++ b/arch/arm/configs/vt8500_v6_v7_defconfig >@@ -8,8 +8,6 @@ CONFIG_ARM_ERRATA_720789=y > CONFIG_ARM_ERRATA_754322=y > CONFIG_ARM_ERRATA_775420=y > CONFIG_HAVE_ARM_ARCH_TIMER=y >-CONFIG_HIGHMEM=y >-CONFIG_HIGHPTE=y > CONFIG_ARM_APPENDED_DTB=y > CONFIG_ARM_ATAG_DTB_COMPAT=y > CONFIG_VFP=y >diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig >index f0f1d7a8640c..d145e448a6b8 100644 >--- a/arch/arm/mach-omap2/Kconfig >+++ b/arch/arm/mach-omap2/Kconfig >@@ -135,7 +135,6 @@ config ARCH_OMAP2PLUS_TYPICAL > bool "Typical OMAP configuration" > default y > select AEABI >- select HIGHMEM if !CPU_CACHE_VIVT > select I2C > select I2C_OMAP > select MENELAUS if ARCH_OMAP2 >diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig >index 9063a91cfb41..8ce8d108bfd7 100644 >--- a/arch/microblaze/Kconfig >+++ b/arch/microblaze/Kconfig >@@ -164,7 +164,8 @@ config LOWMEM_SIZE_BOOL > > config LOWMEM_SIZE > hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL >- default "0x30000000" >+ default "0x80000000" if HIGHMEM >+ default "0x40000000" > > config MANUAL_RESET_VECTOR > hex "Microblaze reset vector address setup" >@@ -190,7 +191,8 @@ config KERNEL_START_BOOL > > config KERNEL_START > hex "Virtual address of kernel base" if KERNEL_START_BOOL >- default "0xc0000000" >+ default "0x70000000" if HIGHMEM >+ default "0xb0000000" > > config TASK_SIZE_BOOL > bool "Set custom user task size" >@@ -204,7 +206,8 @@ config TASK_SIZE_BOOL > > config TASK_SIZE > hex "Size of user task space" if TASK_SIZE_BOOL >- default "0x80000000" >+ default "0x70000000" if HIGHMEM >+ default "0xb0000000" > > config MB_MANAGER > bool "Support for Microblaze Manager" >diff --git a/arch/microblaze/configs/mmu_defconfig >b/arch/microblaze/configs/mmu_defconfig >index 7f9b19d0d9db..19a13d3ece5c 100644 >--- a/arch/microblaze/configs/mmu_defconfig >+++ b/arch/microblaze/configs/mmu_defconfig >@@ -15,7 +15,6 @@ CONFIG_XILINX_MICROBLAZE0_USE_FPU=2 > CONFIG_HZ_100=y > CONFIG_CMDLINE_BOOL=y > CONFIG_CMDLINE_FORCE=y >-CONFIG_HIGHMEM=y > CONFIG_MODULES=y > CONFIG_MODULE_UNLOAD=y > CONFIG_PARTITION_ADVANCED=y >diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig >index c3b6cd655606..31e68cd32a10 100644 >--- a/arch/powerpc/Kconfig >+++ b/arch/powerpc/Kconfig >@@ -489,6 +489,7 @@ menu "Kernel options" > config HIGHMEM > bool "High memory support" > depends on PPC32 >+ depends on PPC_BOOK3S_32 || PPC_85xx || 44x > select KMAP_LOCAL > > source "kernel/Kconfig.hz" >@@ -1190,7 +1191,8 @@ config LOWMEM_SIZE_BOOL > > config LOWMEM_SIZE > hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL >- default "0x30000000" >+ default "0x80000000" if HIGHMEM >+ default "0x40000000" > > config LOWMEM_CAM_NUM_BOOL > bool "Set number of CAMs to use to map low memory" >@@ -1242,7 +1244,8 @@ config PAGE_OFFSET_BOOL > > config PAGE_OFFSET > hex "Virtual address of memory base" if PAGE_OFFSET_BOOL >- default "0xc0000000" >+ default "0x70000000" if HIGHMEM >+ default "0xb0000000" > > config KERNEL_START_BOOL > bool "Set custom kernel base address" >@@ -1258,8 +1261,9 @@ config KERNEL_START_BOOL > config KERNEL_START > hex "Virtual address of kernel base" if KERNEL_START_BOOL > default PAGE_OFFSET if PAGE_OFFSET_BOOL >- default "0xc2000000" if CRASH_DUMP && !NONSTATIC_KERNEL >- default "0xc0000000" >+ default "0x72000000" if HIGHMEM && CRASH_DUMP && !NONSTATIC_KERNEL >+ default "0xb2000000" if CRASH_DUMP && !NONSTATIC_KERNEL >+ default PAGE_OFFSET > > config PHYSICAL_START_BOOL > bool "Set physical address where the kernel is loaded" >@@ -1295,7 +1299,7 @@ config TASK_SIZE_BOOL > config TASK_SIZE > hex "Size of maximum user task space" if TASK_SIZE_BOOL > default "0x80000000" if PPC_8xx >- default "0xc0000000" >+ default PAGE_OFFSET > > config MODULES_SIZE_BOOL > bool "Set custom size for modules/execmem area" >diff --git a/arch/powerpc/configs/44x/akebono_defconfig >b/arch/powerpc/configs/44x/akebono_defconfig >index bdb0e6ece6ec..cc1e3da5f8f5 100644 >--- a/arch/powerpc/configs/44x/akebono_defconfig >+++ b/arch/powerpc/configs/44x/akebono_defconfig >@@ -14,7 +14,6 @@ CONFIG_MODULE_UNLOAD=y > CONFIG_PPC_47x=y > # CONFIG_EBONY is not set > CONFIG_AKEBONO=y >-CONFIG_HIGHMEM=y > CONFIG_HZ_100=y > CONFIG_IRQ_ALL_CPUS=y > # CONFIG_COMPACTION is not set >diff --git a/arch/powerpc/configs/85xx/ksi8560_defconfig >b/arch/powerpc/configs/85xx/ksi8560_defconfig >index 9cb211fb6d1e..f2ac1fc41303 100644 >--- a/arch/powerpc/configs/85xx/ksi8560_defconfig >+++ b/arch/powerpc/configs/85xx/ksi8560_defconfig >@@ -9,7 +9,6 @@ CONFIG_PARTITION_ADVANCED=y > CONFIG_KSI8560=y > CONFIG_CPM2=y > CONFIG_GEN_RTC=y >-CONFIG_HIGHMEM=y > CONFIG_BINFMT_MISC=y > CONFIG_MATH_EMULATION=y > # CONFIG_SECCOMP is not set >diff --git a/arch/powerpc/configs/85xx/stx_gp3_defconfig >b/arch/powerpc/configs/85xx/stx_gp3_defconfig >index 0a42072fa23c..1033977711d6 100644 >--- a/arch/powerpc/configs/85xx/stx_gp3_defconfig >+++ b/arch/powerpc/configs/85xx/stx_gp3_defconfig >@@ -7,7 +7,6 @@ CONFIG_MODULES=y > CONFIG_MODVERSIONS=y > # CONFIG_BLK_DEV_BSG is not set > CONFIG_STX_GP3=y >-CONFIG_HIGHMEM=y > CONFIG_BINFMT_MISC=m > CONFIG_MATH_EMULATION=y > CONFIG_PCI=y >diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig >index 58dce0b66179..18b3eeebb7ce 100644 >--- a/arch/x86/Kconfig >+++ b/arch/x86/Kconfig >@@ -1410,7 +1410,9 @@ config HIGHMEM4G > > choice > prompt "Memory split" if EXPERT >- default VMSPLIT_3G >+ default VMSPLIT_2G_OPT if HIGHMEM && !X86_PAE >+ default VMSPLIT_2G if X86_PAE >+ default VMSPLIT_3G_OPT > depends on X86_32 > help > Select the desired split between kernel and user memory.
The usage of 32-but kernels has certainly drifted, but I do remember us having tried this at one point and having to revert it. Then again, it is kind of valid to squeeze the users here: these days if you have that kind of constraints the answer really is "use a 64-bit CPU, silly." As the price of memory is expected to remain high for much of the remaining decade, the cost-benefit tradeoff for not using your gigabytes of memory well versus the incremental cost of a 64-bit CPU should make the choice trivial. That leaves *very* memory-constrained systems (< 1 GiB) and legacy systems as the main target. Legacy systems presumably will want to change as little as possible, which means at least leaving the current split as an option (and will then be picked up by their previous kernel config, even); for the severely memory-constrained systems it doesn't matter all that much. One advantage of reducing the split line is that for architectures with gigabyte split lines you actually get to fit *all* of a 1 GiB RAM in the virtual space, helping systems with exactly 1 GiB as pushing a few hundred MiB into highmem probably is more expensive than that memory is worth!
