Commit 6898fcf74d13 ("relocator: Switch to own page table while moving
chunks") makes the relocator switch CR3 to a GRUB-owned page table to
prevent chunk movers clobbering firmware-owned page table, with
identical mapping in [0, max_ram_size) range.However, for loaded images that use EFI boot services or MMIO mapped above max_ram_size, those addresses are absent from the preamble page table, causing #PF on access. Fix by copying the firmware's PML4 and only overwriting entries for [0, max_ram_size). Assisted-by: github-copilot:claude-opus-4.7 Signed-off-by: Jiaqing Zhao <[email protected]> --- grub-core/lib/i386/relocator_common_c.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/grub-core/lib/i386/relocator_common_c.c b/grub-core/lib/i386/relocator_common_c.c index c9c5efa72..be4da1fa8 100644 --- a/grub-core/lib/i386/relocator_common_c.c +++ b/grub-core/lib/i386/relocator_common_c.c @@ -109,6 +109,7 @@ grub_cpu_relocator_preamble (void *rels) grub_uint64_t *pt2 = pt3 + (npt3pages << PAGE_IDX_SIZE); grub_uint64_t *endpreamble = pt2 + (npt2pages << PAGE_IDX_SIZE); grub_uint64_t i; + grub_uint64_t firmware_cr3; /* movabs $pt4, %rax. */ *p++ = 0x48; @@ -125,6 +126,13 @@ grub_cpu_relocator_preamble (void *rels) *p++ = 0xe9; *(grub_uint32_t *) p = (grub_uint8_t *) endpreamble - p - 4; + /* + * Inherit the firmware's PML4 so that high mappings (EFI runtime, MMIO, etc.) + * remain reachable while after switching to own page table. + */ + asm volatile ("mov %%cr3, %0" : "=r" (firmware_cr3)); + grub_memcpy (pt4, (void *) (firmware_cr3 & ~0xfffULL), GRUB_PAGE_SIZE); + for (i = 0; i < npt3pages; i++) pt4[i] = ((grub_uint64_t) pt3 + (i << GRUB_PAGE_SHIFT)) | PAGE_PRESENT | PAGE_WRITABLE | PAGE_USER; -- 2.53.0 _______________________________________________ Grub-devel mailing list [email protected] https://lists.gnu.org/mailman/listinfo/grub-devel
