x86 32-bit Operating Systems Aren't Dead Yet: New Linux Patches Improve 32-bit PAE

Longtime Linux developer Dave Hansen with Intel has posted a set of patches to simplify the PAE page table handling code. For anyone running serious Linux 32-bit systems, outside of any legacy embedded devices chances are you are making relying on the 32-bit PAE kernel for addressing more than 4GB of physical memory. To much surprise this is a nice PAE improvement for the Linux kernel in 2025 for those making use of Page Table Isolation (PTI), which chances are you would be for the default CPU security mitigiations.
Dave Hansen explained the situation and improvement well in the RFC patch series cover letter:
"tl;dr: 32-bit PAE page table handing is a bit different when PTI is on and off. Making the handling uniform removes a good amount of code at the cost of not sharing kernel PMDs. The downside of this simplification is bloating non-PTI PAE kernels by ~2 pages per process.
Anyone who cares about security on 32-bit is running with PTI and PAE because PAE has the No-eXecute page table bit. They are already
paying the 2-page penalty. Anyone who cares more about memory footprint than security is probably already running a !PAE kernel and will not be affected by this.
--
There are two 32-bit x86 hardware page table formats. A 2-level one with 32-bit pte_t's and a 3-level one with 64-bit pte_t's called PAE. But the PAE one is wonky. It effectively loses a bit of addressing radix per level since its PTEs are twice as large. It makes up for that by adding the third level, but with only 4 entries in the level.
This leads to all kinds of fun because this level only needs 32 bytes instead of a whole page. Also, since it has only 4 entries in the top level, the hardware just always caches the entire thing aggressively. Modifying a PAE pgd_t ends up needing different rules than the other other x86 paging modes and probably every other architecture too.
PAE support got even weirder when Xen came along. Xen wants to trap into the hypervisor on page table writes and so it protects the guest page tables with paging protections. It can't protect a 32 byte object with paging protections so it bloats the 32-byte object out to a page. Xen also didn't support sharing kernel PMD pages. This is mostly moot now because the Xen support running as a 32-bit guest was ripped out, but there are still remnants around.
PAE also interacts with PTI in fun and exciting ways. Since pgd updates are so fraught, the PTI PAE implementation just chose to avoid pgd updates by preallocating all the PMDs up front since there are only 4 instead of 512 or 1024 in the other x86 paging modes.
Make PAE less weird:
* Always allocate a page for PAE PGDs. This brings them in line with the other 2 paging modes. It was done for Xen and for PTI already and nobody screamed, so just do it everywhere.
* Never share kernel PMD pages. This brings PAE in line with 32-bit !PAE and 64-bit.
* Always preallocate all PAE PMD pages. This basically makes all PAE kernels behave like PTI ones. It might waste a page of memory, but all 4 pages probably get allocated in the common case anyway."
We'll see if there is enough interest to get this work past the request for comments (RFC) stage and ultimately upstreamed into the mainline Linux kernel.
One of the few remaining x86 32-bit systems still functioning at Phoronix is the Intel Xeon LV "Sossaman" processors, albeit it's been probably 15+ years since last powering it up but one of the last 32-bit platforms I have fond memories of... Are you still using any x86 32-bit systems? Share your thoughts on this 2025 kernel activity in the forums.
40 Comments