From nobody Mon Jun 8 16:44:28 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4gYyYm6qqyz6gM0c for ; Mon, 08 Jun 2026 16:44:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4gYyYm68zHz3DjN for ; Mon, 08 Jun 2026 16:44:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780937068; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RuANojvttz/jDCcMkFTQA+AfoSfRIZK9HncSNplK//k=; b=P7EJslknF6n+0cfuBIrAH2mGsryza0zExr2laGtZdqUGYLgN9joC2ehrgDrn64p1QCkPkz QbxZhuAw09aXR3LkQYyWP8fkken1AQBGxFv9xnn83gX5TY2pIa1XFMWImfxosQ7/hgTMbS pLs51PivGH5bBr5fnJasrvX2h4V0n0cHu5KgUrzfB7tBbVSY2/oRhIMdR4+Yv2by215PV5 0uo7YBa5q0xIMj4nPx2kZS6VsL43KiDG77nM8CrQm5h0MnmOVFlH+2u1lHajQDNTfcwEKy UEnOze8SyYDQxn8HOkJRjv3DF+9lCyc76rszzPTj5ECkJqZXrn7Cx45upZY5hQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1780937068; a=rsa-sha256; cv=none; b=hzE4Q+VO5fXsqzXmXFgIoItSnTnlgh7Ivm+5G9LJGJ0uipXDkq9kQ5+tFNdnQix5y/BBHM sPu5jUZbcBUFCPelPE7BrQRiaqPvdoRrf/aa+IDWe1UPk/SUslttUrB+5WiqWPag5X4O3n pCmoI63a0KtGw0xyTsz5y+wW2/pKXdcr0kfyHbePKpvaxYcXr2YkYDAitLTTMcTnLjU7u0 7IFLV4i6eEvnIjXHnHemXG+zI4okN0DwkDNDwN6iqoYnAIXYMxpIWhkCXM/EocgRzKnCVg ZSSf6o6ceCFQxvUMr9NZz/6ieowc5A1CQCPfApzA2kgU9+QsJNvngT/1ipq+3w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1780937068; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=RuANojvttz/jDCcMkFTQA+AfoSfRIZK9HncSNplK//k=; b=T6sZoRI0W4QVkQn8AjTw89seAk2bhgNVJWXBsVfeG3bfYefgWuZqSgo4yAKjnm7957QGzO tlsx8QKA5eva+NUDf7TXvuGCXpPNE41OwdgMSMR9G5jM4o7VloYK64jqZD1y7yYDqRgps+ VEuonRLyBe5nVIzS9plB1Af42HFF3InQFuvsTUDtUaVhxFvuoTzPT6KTSdlbD8abTEJcTd YHEUcz+fxSgvcScoZFLUVqbXKxhc5KzETByadwQ3UpbSZuEBM87E2ePmxnL+orWS9scpDS Ge+LgmTOhB6lDfHq5kxAmd5Jw2fAqDhayhxQc0V3QGm7ORqRHqHLwI6xucBbOw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4gYyYm5hhTzx0v for ; Mon, 08 Jun 2026 16:44:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 25786 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 08 Jun 2026 16:44:28 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Warner Losh Subject: git: 8dca7fccfa65 - stable/14 - loader.efi: Fix when staging moves late List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 8dca7fccfa6514b0a48a290683572fadbb4e2a68 Auto-Submitted: auto-generated Date: Mon, 08 Jun 2026 16:44:28 +0000 Message-Id: <6a26f16c.25786.51544913@gitrepo.freebsd.org> The branch stable/14 has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=8dca7fccfa6514b0a48a290683572fadbb4e2a68 commit 8dca7fccfa6514b0a48a290683572fadbb4e2a68 Author: Warner Losh AuthorDate: 2026-06-05 05:18:40 +0000 Commit: Warner Losh CommitDate: 2026-06-08 16:34:58 +0000 loader.efi: Fix when staging moves late Prior to this commit, we'd compute the page tables and have the last entries point to the staging area. We'd then add some more metadata to the image and boot. This assumed the staging area didn't need to move for this last bit of data. However, if we go over the staging limit, when we copyin new data, we grow the staging area, usually be moving it to a lower address. This overage usually happens when we're loading modules and so things work out nicely. Sometimes we're close to the limit, and we need to do this growing inside bi_load, after we've computed the page table, making the page table wrong, and the code we jump to random rather than the btext routine we normally start at. To fix this, move computation of the table (but not its allocation) to after bi_load, but before we call the trampoline. This problem was most observed when loading microcode for many peole, but Gleb reproduced the error with a set of modules that didn't include ucode. This bug hunt was greatly assisted by Claude who looked at the crash from the EFI boot loader and surmised that we weren't jumping to the code we thought we were jumping to. After inspecting the code, I asked claude how corruption could happen (I thought overwriting the page table), but claude notice the possibility that staging might change after we computed the page table, and this fix is the result. Claude didn't suggest a diff, but did provide many helpful clues that lead me to this fix. PR: 294630 Reviewed by: kib (prior version) Sponsored by: Netflix MFC After: insta per re@ request Differential Revision: https://reviews.freebsd.org/D57462 (cherry picked from commit 3915ffb1c3e04b26d1506bf35d3f665b2e25a915) --- stand/efi/loader/arch/amd64/elf64_freebsd.c | 47 ++++++++++++++++++----------- stand/efi/loader/bootinfo.c | 19 +++++++++++- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/stand/efi/loader/arch/amd64/elf64_freebsd.c b/stand/efi/loader/arch/amd64/elf64_freebsd.c index 91dd979a677e..72c8d558d8a6 100644 --- a/stand/efi/loader/arch/amd64/elf64_freebsd.c +++ b/stand/efi/loader/arch/amd64/elf64_freebsd.c @@ -94,7 +94,7 @@ elf64_exec(struct preloaded_file *fp) Elf_Ehdr *ehdr; vm_offset_t modulep, kernend, trampcode, trampstack; int err, i; - bool copy_auto; + bool copy_auto, needs_pt4; copy_auto = copy_staging == COPY_STAGING_AUTO; if (copy_auto) @@ -162,6 +162,7 @@ elf64_exec(struct preloaded_file *fp) PT2[i] = (pd_entry_t)i * (2 * 1024 * 1024); PT2[i] |= PG_V | PG_RW | PG_PS; } + needs_pt4 = false; } else { PT4 = (pml4_entry_t *)0x0000000100000000; /* 4G */ err = BS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 9, @@ -173,7 +174,35 @@ elf64_exec(struct preloaded_file *fp) copy_staging = COPY_STAGING_AUTO; return (ENOMEM); } + needs_pt4 = true; + } + + printf("%scopying staging tramp %p PT4 %p\n", + copy_staging == COPY_STAGING_ENABLE ? "" : "not ", + trampoline, PT4); + printf("Start @ 0x%lx ...\n", ehdr->e_entry); + + /* + * we have to cleanup here because net_cleanup() doesn't work after + * we call ExitBootServices + */ + dev_cleanup(); + + efi_time_fini(); + err = bi_load(fp->f_args, &modulep, &kernend, true); + if (err != 0) { + efi_time_init(); + if (copy_auto) + copy_staging = COPY_STAGING_AUTO; + return (err); + } + /* + * staging might move in bi_load because we automatiaclly move when we + * copy data in. At this point, staging can't move anymore, so create + * PT4 with the correct value. + */ + if (needs_pt4) { bzero(PT4, 9 * EFI_PAGE_SIZE); PT3_l = &PT4[NPML4EPG * 1]; @@ -210,22 +239,6 @@ elf64_exec(struct preloaded_file *fp) } } - printf("staging %#lx (%scopying) tramp %p PT4 %p\n", - staging, copy_staging == COPY_STAGING_ENABLE ? "" : "not ", - trampoline, PT4); - printf("Start @ 0x%lx ...\n", ehdr->e_entry); - - efi_time_fini(); - err = bi_load(fp->f_args, &modulep, &kernend, true); - if (err != 0) { - efi_time_init(); - if (copy_auto) - copy_staging = COPY_STAGING_AUTO; - return (err); - } - - dev_cleanup(); - trampoline(trampstack, copy_staging == COPY_STAGING_ENABLE ? efi_copy_finish : efi_copy_finish_nop, kernend, modulep, PT4, ehdr->e_entry); diff --git a/stand/efi/loader/bootinfo.c b/stand/efi/loader/bootinfo.c index 2961b8b97fb7..e56cd90ed7b8 100644 --- a/stand/efi/loader/bootinfo.c +++ b/stand/efi/loader/bootinfo.c @@ -213,6 +213,17 @@ bi_load_efi_data(struct preloaded_file *kfp, bool exit_bs) } #endif +#if defined(__amd64__) || defined(__i386__) + extern uint64_t staging; + /* + * Staging can't move after this point, so report the final value before + * we try to exit boot services below. The metadata added is added to + * the malloced arena that we setup when we started and doesn't interact + * with boot services. + */ + printf("staging %#jx\n", (uintmax_t)staging); +#endif + do_vmap = true; efi_novmap = getenv("efi_disable_vmap"); if (efi_novmap != NULL) @@ -302,14 +313,20 @@ bi_load_efi_data(struct preloaded_file *kfp, bool exit_bs) * loader.conf(5). By default we will setup the virtual * map entries. */ - if (do_vmap) efi_do_vmap(mm, sz, dsz, mmver); + + /* + * Add the memory map to the metadata. addmetadata copies the data into + * the malloc arena, so we can safely free the memory map pages after. + * Or could if boot services was still running. + */ efihdr->memory_size = sz; efihdr->descriptor_size = dsz; efihdr->descriptor_version = mmver; file_addmetadata(kfp, MODINFOMD_EFI_MAP, efisz + sz, efihdr); + /* BS->FreePages(addr, pages); */ return (0); }