[arch][riscv] change secondary cpu bootstrap api

Instead of setting a counter of the number of secondaries to start, have
platform or target code pass in a list of harts to start instead. This
allows for there to be discontinuties in the layout of the cpu harts, or
in the case of some sifive based hardware, hart 0 is otherwise offline.
This commit is contained in:
Travis Geiselbrecht
2024-04-07 22:13:18 -07:00
parent a070819c46
commit 00b06a8302
5 changed files with 125 additions and 49 deletions

View File

@@ -85,12 +85,23 @@ static void reserved_memory_callback(uint64_t base, uint64_t len, void *cookie)
}
}
struct detected_cpus {
size_t count;
struct {
uint hart;
} cpu[SMP_MAX_CPUS];
};
static void cpucallback(uint64_t id, void *cookie) {
int *cpu_count = (int *)cookie;
struct detected_cpus *cpus = cookie;
LTRACEF("id %#llx cookie %p\n", id, cookie);
LTRACEF("hart %#llx\n", id);
(*cpu_count)++;
if (cpus->count < SMP_MAX_CPUS) {
cpus->cpu[cpus->count].hart = id;
cpus->count++;
}
}
struct pcie_detect_state {
@@ -112,8 +123,8 @@ void platform_early_init(void) {
/* look for a flattened device tree in the second arg passed to us */
bool found_mem = false;
int cpu_count = 0;
struct reserved_memory_regions reserved = {0};
struct detected_cpus cpus = {0};
const void *fdt = (void *)lk_boot_args[1];
#if WITH_KERNEL_VM
@@ -126,7 +137,7 @@ void platform_early_init(void) {
.reserved_memory = reserved_memory_callback,
.reserved_memory_cookie = &reserved,
.cpu = cpucallback,
.cpucookie = &cpu_count,
.cpucookie = &cpus,
.pcie = pciecallback,
.pciecookie = &pcie_state,
};
@@ -163,12 +174,31 @@ void platform_early_init(void) {
}
#endif
if (cpu_count > 0) {
printf("FDT: found %d cpu%c\n", cpu_count, cpu_count == 1 ? ' ' : 's');
riscv_set_secondary_count(cpu_count - 1);
} else {
riscv_set_secondary_count(0);
#if WITH_SMP
// TODO: refactor this code into libfdt
if (cpus.count > 0) {
printf("FDT: found %zu cpu%c\n", cpus.count, cpus.count == 1 ? ' ' : 's');
uint harts[SMP_MAX_CPUS - 1];
// copy from the detected cpu list to an array of harts, excluding the boot hart
size_t hart_index = 0;
for (size_t i = 0; i < cpus.count; i++) {
if (cpus.cpu[i].hart != riscv_current_hart()) {
harts[hart_index++] = cpus.cpu[i].hart;
}
// we can start MAX CPUS - 1 secondaries
if (hart_index >= SMP_MAX_CPUS - 1) {
break;
}
}
// tell the riscv layer how many cores we have to start
if (hart_index > 0) {
riscv_set_secondary_harts_to_start(harts, hart_index);
}
}
#endif
LTRACEF("done scanning FDT\n");