diff --git a/stand/efi/loader/arch/riscv/exec.c b/stand/efi/loader/arch/riscv/exec.c --- 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 * Copyright (c) 2007 Semihalf, Rafal Jaworowski * 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 @@ 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 --- a/sys/kern/subr_module.c +++ b/sys/kern/subr_module.c @@ -442,6 +442,11 @@ 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 @@ 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 --- 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 --- a/sys/riscv/riscv/machdep.c +++ b/sys/riscv/riscv/machdep.c @@ -418,6 +418,45 @@ /* 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) @@ -461,6 +500,8 @@ if (kern_envp == NULL) parse_fdt_bootargs(); #endif + parse_boot_hartid(); + return (lastaddr); } @@ -472,10 +513,6 @@ 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); @@ -500,22 +537,6 @@ } 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; - #ifdef FDT /* * Exclude reserved memory specified by the device tree. Typically,