mirror of
https://github.com/opnsense/src.git
synced 2026-06-07 07:42:26 -04:00
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
This commit is contained in:
parent
62c0997d43
commit
04a812ae94
4 changed files with 77 additions and 20 deletions
|
|
@ -2,6 +2,7 @@
|
|||
* Copyright (c) 2001 Benno Rice <benno@FreeBSD.org>
|
||||
* Copyright (c) 2007 Semihalf, Rafal Jaworowski <raj@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();
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue