nova: support to run on e-core only SOCs

The code to group together SMT threads of one CPU and to move P-Core to
the beginning of Genode's affinity-space, did not consider to run on
SOCs with only E-Core CPUs.

Re-structure the code to support e-Core only SOCs.

Additionally, provide a fallback mapping in case of CPU id reordering problems.
Track faulty re-mapping and delay the reporting until core_log is initialized,
so that the warnings is visible to consumers, e.g. on Sculpt OS.

Related to discussion of #5304

Fixes #5307
This commit is contained in:
Alexander Boettcher 2024-07-25 11:42:37 +02:00 committed by Christian Helmuth
parent 044d8bca44
commit eaadc6aad6
2 changed files with 51 additions and 26 deletions

View File

@ -178,21 +178,39 @@ namespace Nova {
}
/**
* Map kernel cpu ids to virtual cpu ids.
* Resort CPU ids such, that
* - the boot CPU id is ever logical CPU id 0
* - SMT threads of one CPU have logical CPU ids close together
* - P-Core has a smaller logical CPU id than E-Core CPUs
*
* Returns true, if re-mapping succeeded otherwise false.
*
* In case of failure, map_cpus will contain a 1:1 fallback mapping
* without any sorting as mentioned above.
*/
bool remap_cpu_ids(uint16_t *map_cpus, unsigned const boot_cpu) const
bool remap_cpu_ids(uint16_t *map_cpus, unsigned const max_cpus,
unsigned const boot_cpu) const
{
unsigned const num_cpus = cpus();
bool too_many_cpus = false;
unsigned cpu_i = 0;
/* fallback lambda in case re-ordering fails */
auto remap_failure = [&] {
for (uint16_t i = 0; i < max_cpus; i++) { map_cpus[i] = i; }
return false;
};
/* assign boot cpu ever the virtual cpu id 0 */
Cpu_desc const * const boot = cpu_desc_of_cpu(boot_cpu);
if (!boot || !is_cpu_enabled(boot_cpu) || boot->e_core())
return false;
if (!boot)
return remap_failure();
map_cpus[cpu_i++] = (uint8_t)boot_cpu;
if (cpu_i >= num_cpus)
return true;
if (cpu_i >= max_cpus)
return remap_failure();
/* assign cores + SMT threads first and skip E-cores */
bool done = for_all_cpus([&](auto const &cpu, auto const kernel_cpu_id) {
@ -204,25 +222,32 @@ namespace Nova {
return false;
map_cpus[cpu_i++] = (uint8_t)kernel_cpu_id;
return (cpu_i >= num_cpus);
too_many_cpus = !!(cpu_i >= max_cpus);
return (cpu_i >= num_cpus || too_many_cpus);
});
if (done)
return too_many_cpus ? remap_failure() : true;
/* assign remaining E-cores */
if (!done) {
done = for_all_cpus([&](auto &cpu, auto &kernel_cpu_id) {
if (kernel_cpu_id == boot_cpu)
return false;
done = for_all_cpus([&](auto &cpu, auto &kernel_cpu_id) {
if (kernel_cpu_id == boot_cpu)
return false;
/* handle solely E-core */
if (!cpu.e_core())
return false;
/* handle solely E-core */
if (!cpu.e_core())
return false;
map_cpus[cpu_i++] = (uint16_t)kernel_cpu_id;
return (cpu_i >= num_cpus);
});
}
map_cpus[cpu_i++] = (uint16_t)kernel_cpu_id;
return done;
too_many_cpus = !!(cpu_i >= max_cpus);
return (cpu_i >= num_cpus || too_many_cpus);
});
return too_many_cpus ? remap_failure() : done;
}
/**

View File

@ -307,6 +307,8 @@ Core::Platform::Platform()
_irq_alloc(&core_mem_alloc()),
_vm_base(0x1000), _vm_size(0), _cpus(Affinity::Space(1,1))
{
bool warn_reorder = false;
Hip const &hip = *(Hip *)__initial_sp;
/* check for right API version */
if (hip.api_version != 9)
@ -365,15 +367,9 @@ Core::Platform::Platform()
}
/* init genode cpu ids based on kernel cpu ids (used for syscalls) */
if (sizeof(map_cpu_ids) / sizeof(map_cpu_ids[0]) < hip.cpu_max()) {
error("number of max CPUs is larger than expected - ", hip.cpu_max(),
" vs ", sizeof(map_cpu_ids) / sizeof(map_cpu_ids[0]));
nova_die();
}
if (!hip.remap_cpu_ids(map_cpu_ids, (unsigned)boot_cpu())) {
error("re-ording cpu_id failed");
nova_die();
}
warn_reorder = !hip.remap_cpu_ids(map_cpu_ids,
sizeof(map_cpu_ids) / sizeof(map_cpu_ids[0]),
(unsigned)boot_cpu());
/* map idle SCs */
unsigned const log2cpu = log2(hip.cpu_max());
@ -773,6 +769,10 @@ Core::Platform::Platform()
new (core_mem_alloc())
Rom_module(_rom_fs, "kernel_log", hyp_log, hyp_log_size);
/* show all warnings/errors after init_core_log setup core_log */
if (warn_reorder)
warning("re-ordering of CPU ids for SMT and P/E cores failed");
if (verbose_boot_info) {
if (hip.has_feature_iommu())
log("Hypervisor features IOMMU");