Use the HSM SBI extension to start APs

The addition of the HSM SBI extension to OpenSBI introduces a new
breaking change: secondary harts will remain parked in the firmware,
until they are brought up explicitly via sbi_hsm_hart_start(). Add
the call to do this, sending the secondary harts to mpentry.

If the HSM extension is not present, secondary harts are assumed to be
released by the firmware, as is the case for OpenSBI =< v0.6 and BBL.

In the case that the HSM call fails we exclude the CPU, notify the
user, and allow the system to proceed with booting.

Reviewed by:	markj (older version)
Differential Revision:	https://reviews.freebsd.org/D24497
This commit is contained in:
Mitchell Horne 2020-05-01 21:58:19 +00:00
parent bfe918fa0e
commit c74959537c

View File

@ -97,6 +97,7 @@ static uint32_t cpu_reg[MAXCPU][2];
#endif
static device_t cpu_list[MAXCPU];
void mpentry(u_long hartid);
void init_secondary(uint64_t);
static struct mtx ap_boot_mtx;
@ -297,7 +298,7 @@ smp_after_idle_runnable(void *arg __unused)
struct pcpu *pc;
int cpu;
for (cpu = 1; cpu < mp_ncpus; cpu++) {
for (cpu = 1; cpu <= mp_maxid; cpu++) {
if (bootstacks[cpu] != NULL) {
pc = pcpu_find(cpu);
while (atomic_load_ptr(&pc->pc_curpcb) == NULL)
@ -399,9 +400,11 @@ static boolean_t
cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
{
struct pcpu *pcpup;
vm_paddr_t start_addr;
uint64_t hart;
u_int cpuid;
int naps;
int error;
/* Check if this hart supports MMU. */
if (OF_getproplen(node, "mmu-type") < 0)
@ -441,6 +444,23 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
if (cpuid > mp_maxid)
return (0);
/*
* Depending on the SBI implementation, APs are waiting either in
* locore.S or to be activated explicitly, via SBI call.
*/
if (sbi_probe_extension(SBI_EXT_ID_HSM) != 0) {
start_addr = pmap_kextract((vm_offset_t)mpentry);
error = sbi_hsm_hart_start(hart, start_addr, 0);
if (error != 0) {
mp_ncpus--;
/* Send a warning to the user and continue. */
printf("AP %u (hart %lu) failed to start, error %d\n",
cpuid, hart, error);
return (0);
}
}
pcpup = &__pcpu[cpuid];
pcpu_init(pcpup, cpuid, sizeof(struct pcpu));
pcpup->pc_hart = hart;