diff --git a/repos/base-nova/include/nova/syscall-generic.h b/repos/base-nova/include/nova/syscall-generic.h index 7842e48f18..69502fb9d5 100644 --- a/repos/base-nova/include/nova/syscall-generic.h +++ b/repos/base-nova/include/nova/syscall-generic.h @@ -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; } /** diff --git a/repos/base-nova/src/core/platform.cc b/repos/base-nova/src/core/platform.cc index 927bd657ba..0b1444895e 100644 --- a/repos/base-nova/src/core/platform.cc +++ b/repos/base-nova/src/core/platform.cc @@ -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");