From 97dcbc010b830a2417858a8dba521ac4e4123390 Mon Sep 17 00:00:00 2001 From: Marco Casaroli Date: Sun, 26 Jul 2026 17:24:57 +0200 Subject: [PATCH] arch/x86_64: inherit the kernel low memory mapping in an address environment. copy_kernel_mappings() copies exactly one PDPT entry, the 1GB linear window that maps physical 0-1GB at 4GB-5GB. The boot identity mapping of the low 4GB, which lives in PDPT entries 0-3 of g_pdpt_low (intel64_head.S:756, one page directory per 1GB) and is where every MMIO register is reached, is not carried over. A kernel thread never gets an address environment of its own and addrenv_switch() leaves the last one in place for it, so as soon as any process exists, kernel code touching MMIO faults. The HPET at 0xfed00000 finds it immediately -- CR2=fed000f0, in intel64_hpet_getreg() under clock_systime_ticks() on the lpwork thread -- and any MMIO driver would. Inherit the four boot PDPT entries. They point at the boot page directories rather than at copies, so anything intel64_map_region() adds later is inherited too, and they carry no X86_PAGE_USER, so user code still cannot reach them. Impact: runtime, CONFIG_ARCH_ADDRENV builds only. User-space access is unchanged; the entries added are supervisor-only. Assisted-by: Claude:claude-opus-5 Signed-off-by: Marco Casaroli --- arch/x86_64/src/common/x86_64_addrenv.c | 10 ++++++++++ arch/x86_64/src/common/x86_64_mmu.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/arch/x86_64/src/common/x86_64_addrenv.c b/arch/x86_64/src/common/x86_64_addrenv.c index b8396b84bc0..1473987b37b 100644 --- a/arch/x86_64/src/common/x86_64_addrenv.c +++ b/arch/x86_64/src/common/x86_64_addrenv.c @@ -70,6 +70,8 @@ #include +#include + #include "addrenv.h" #include "pgalloc.h" #include "x86_64_mmu.h" @@ -192,10 +194,18 @@ static int create_spgtables(arch_addrenv_t *addrenv) static void copy_kernel_mappings(arch_addrenv_t *addrenv) { uintptr_t *pdpt = (uintptr_t *)x86_64_pgvaddr(addrenv->spgtables[1]); + int i; /* Kernel mapping - lower 1GB maps to 4GB-5GB */ pdpt[4] = X86_PDPT_KERNEL_MAP; + + /* Inherit the boot identity mapping of the low 4GB. */ + + for (i = 0; i < X86_MMU_LOWMEM_PDPTS; i++) + { + pdpt[i] = g_pdpt[i]; + } } /**************************************************************************** diff --git a/arch/x86_64/src/common/x86_64_mmu.h b/arch/x86_64/src/common/x86_64_mmu.h index e029075a194..634a60d1b97 100644 --- a/arch/x86_64/src/common/x86_64_mmu.h +++ b/arch/x86_64/src/common/x86_64_mmu.h @@ -57,6 +57,10 @@ #define X86_MMU_VADDR_INDEX(vaddr, ptlevel) \ ((vaddr >> X86_MMU_VADDR_SHIFT(ptlevel)) & X86_MMU_VPN_MASK) +/* Number of PDPT entries in the boot low-memory identity mapping. */ + +#define X86_MMU_LOWMEM_PDPTS 4 + /**************************************************************************** * Public Function Prototypes ****************************************************************************/