The branch main has been updated by mhorne: URL: https://cgit.FreeBSD.org/src/commit/?id=04a812ae94e44982ee7f86e5de8a5caccdbc8a81
commit 04a812ae94e44982ee7f86e5de8a5caccdbc8a81 Author: Mitchell Horne <mho...@freebsd.org> AuthorDate: 2025-03-03 15:47:23 +0000 Commit: Mitchell Horne <mho...@freebsd.org> CommitDate: 2025-03-03 16:12:15 +0000 riscv/stand: pass boot hart in loader metadata Use the RISCV_EFI_BOOT_PROTOCOL to fetch the boot hart ID, and communicate this to the kernel via new metadata field (MODINFOMD_BOOT_HART). If the boot hart is not found this way, fall back to the (now deprecated) device-tree method. The assumption that a hart ID can be represented with a 32-bit unsigned integer is unchanged in the kernel, but from the loader we pass the full 64-bit value. This ensures that this API won't need to change in the future, should the wider value become necessary. Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D48887 --- stand/efi/loader/arch/riscv/exec.c | 25 ++++++++++++++++ sys/kern/subr_module.c | 10 +++++++ sys/riscv/include/metadata.h | 1 + sys/riscv/riscv/machdep.c | 61 +++++++++++++++++++++++++------------- 4 files changed, 77 insertions(+), 20 deletions(-) diff --git a/stand/efi/loader/arch/riscv/exec.c b/stand/efi/loader/arch/riscv/exec.c index 0fc28cba78c1..9da61229ef68 100644 --- a/stand/efi/loader/arch/riscv/exec.c +++ b/stand/efi/loader/arch/riscv/exec.c @@ -2,6 +2,7 @@ * Copyright (c) 2001 Benno Rice <be...@freebsd.org> * Copyright (c) 2007 Semihalf, Rafal Jaworowski <r...@semihalf.com> * All rights reserved. + * Copyright (c) 2024 The FreeBSD Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,6 +41,28 @@ #include "bootstrap.h" #include "loader_efi.h" +static void +riscv_set_boot_hart(struct preloaded_file *fp) +{ + EFI_GUID riscvboot = RISCV_EFI_BOOT_PROTOCOL_GUID; + RISCV_EFI_BOOT_PROTOCOL *proto; + EFI_STATUS status = 0; + uint64_t boot_hartid = ULONG_MAX; + + status = BS->LocateProtocol(&riscvboot, NULL, (void **)&proto); + if (EFI_ERROR(status)) { + return; + } + + status = proto->GetBootHartId(proto, &boot_hartid); + if (EFI_ERROR(status)) { + return; + } + + file_addmetadata(fp, MODINFOMD_BOOT_HARTID, sizeof(boot_hartid), + &boot_hartid); +} + static int __elfN(exec)(struct preloaded_file *fp) { @@ -52,6 +75,8 @@ __elfN(exec)(struct preloaded_file *fp) if ((fmp = file_findmetadata(fp, MODINFOMD_ELFHDR)) == NULL) return (EFTYPE); + riscv_set_boot_hart(fp); + e = (Elf_Ehdr *)&fmp->md_data; efi_time_fini(); diff --git a/sys/kern/subr_module.c b/sys/kern/subr_module.c index 596961606577..d07990cebdc3 100644 --- a/sys/kern/subr_module.c +++ b/sys/kern/subr_module.c @@ -442,6 +442,11 @@ preload_modinfo_type(struct sbuf *sbp, int type) case MODINFOMD_SPLASH: sbuf_cat(sbp, "MODINFOMD_SPLASH"); break; +#endif +#ifdef MODINFOMD_BOOT_HARTID + case MODINFOMD_BOOT_HARTID: + sbuf_cat(sbp, "MODINFOMD_BOOT_HARTID"); + break; #endif default: sbuf_cat(sbp, "unrecognized metadata type"); @@ -503,6 +508,11 @@ preload_modinfo_value(struct sbuf *sbp, uint32_t *bptr, int type, int len) case MODINFO_METADATA | MODINFOMD_HOWTO: sbuf_printf(sbp, "0x%08x", *bptr); break; +#ifdef MODINFOMD_BOOT_HARTID + case MODINFO_METADATA | MODINFOMD_BOOT_HARTID: + sbuf_printf(sbp, "0x%lu", *(uint64_t *)bptr); + break; +#endif case MODINFO_METADATA | MODINFOMD_SHDR: case MODINFO_METADATA | MODINFOMD_ELFHDR: case MODINFO_METADATA | MODINFOMD_FW_HANDLE: diff --git a/sys/riscv/include/metadata.h b/sys/riscv/include/metadata.h index 6ade03e15ea3..ddbad3fae3b4 100644 --- a/sys/riscv/include/metadata.h +++ b/sys/riscv/include/metadata.h @@ -31,6 +31,7 @@ #define MODINFOMD_DTBP 0x1001 #define MODINFOMD_EFI_MAP 0x1002 #define MODINFOMD_EFI_FB 0x1003 +#define MODINFOMD_BOOT_HARTID 0x1004 struct efi_map_header { size_t memory_size; diff --git a/sys/riscv/riscv/machdep.c b/sys/riscv/riscv/machdep.c index 03f5926c3739..fea4ca9a7b92 100644 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -419,6 +419,45 @@ fake_preload_metadata(struct riscv_bootparams *rvbp) /* Support for FDT configurations only. */ CTASSERT(FDT); +static void +parse_boot_hartid(void) +{ + uint64_t *mdp; +#ifdef FDT + phandle_t chosen; + uint32_t hart; +#endif + + mdp = (uint64_t *)preload_search_info(preload_kmdp, + MODINFO_METADATA | MODINFOMD_BOOT_HARTID); + if (mdp != NULL && *mdp < UINT32_MAX) { + boot_hart = (uint32_t)*mdp; + goto out; + } + +#ifdef FDT + /* + * Deprecated: + * + * Look for the boot hart ID. This was either passed in directly from + * the SBI firmware and handled by locore, or was stored in the device + * tree by an earlier boot stage. + */ + chosen = OF_finddevice("/chosen"); + if (OF_getencprop(chosen, "boot-hartid", &hart, sizeof(hart)) != -1) { + boot_hart = hart; + } +#endif + + /* We failed... */ + if (boot_hart == BOOT_HART_INVALID) { + panic("Boot hart ID was not properly set"); + } + +out: + PCPU_SET(hart, boot_hart); +} + #ifdef FDT static void parse_fdt_bootargs(void) @@ -462,6 +501,8 @@ parse_metadata(void) if (kern_envp == NULL) parse_fdt_bootargs(); #endif + parse_boot_hartid(); + return (lastaddr); } @@ -474,10 +515,6 @@ initriscv(struct riscv_bootparams *rvbp) int mem_regions_sz; vm_offset_t lastaddr; vm_size_t kernlen; -#ifdef FDT - phandle_t chosen; - uint32_t hart; -#endif char *env; TSRAW(&thread0, TS_ENTER, __func__, NULL); @@ -502,22 +539,6 @@ initriscv(struct riscv_bootparams *rvbp) } lastaddr = parse_metadata(); -#ifdef FDT - /* - * Look for the boot hart ID. This was either passed in directly from - * the SBI firmware and handled by locore, or was stored in the device - * tree by an earlier boot stage. - */ - chosen = OF_finddevice("/chosen"); - if (OF_getencprop(chosen, "boot-hartid", &hart, sizeof(hart)) != -1) { - boot_hart = hart; - } -#endif - if (boot_hart == BOOT_HART_INVALID) { - panic("Boot hart ID was not properly set"); - } - pcpup->pc_hart = boot_hart; - efihdr = (struct efi_map_header *)preload_search_info(preload_kmdp, MODINFO_METADATA | MODINFOMD_EFI_MAP); if (efihdr != NULL) {