diff --git a/sys/riscv/riscv/identcpu.c b/sys/riscv/riscv/identcpu.c --- a/sys/riscv/riscv/identcpu.c +++ b/sys/riscv/riscv/identcpu.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include @@ -48,7 +47,6 @@ #include #include #include -#include #ifdef FDT #include @@ -263,12 +261,13 @@ #ifdef FDT static void -fill_elf_hwcap(void *dummy __unused) +identify_cpu_features_fdt(struct cpu_desc *desc) { char isa[1024]; u_long hwcap; phandle_t node; ssize_t len; + pcell_t reg; node = OF_finddevice("/cpus"); if (node == -1) { @@ -278,16 +277,19 @@ } /* - * Iterate through the CPUs and examine their ISA string. While we - * could assign elf_hwcap to be whatever the boot CPU supports, to - * handle the (unusual) case of running a system with hetergeneous - * ISAs, keep only the extension bits that are common to all harts. + * Locate our current CPU's node in the device-tree, and parse its + * contents to detect supported CPU/ISA features and extensions. */ for (node = OF_child(node); node > 0; node = OF_peer(node)) { /* Skip any non-CPU nodes, such as cpu-map. */ if (!ofw_bus_node_is_compatible(node, "riscv")) continue; + /* Find this CPU */ + if (OF_getencprop(node, "reg", ®, sizeof(reg)) <= 0 || + reg != PCPU_GET(hart)) + continue; + len = OF_getprop(node, "riscv,isa", isa, sizeof(isa)); KASSERT(len <= sizeof(isa), ("ISA string truncated")); if (len == -1) { @@ -314,11 +316,24 @@ elf_hwcap &= hwcap; else elf_hwcap = hwcap; + + /* We are done. */ + break; + } + if (node <= 0) { + printf("%s: could not find FDT node for CPU %u, hart %u\n", + __func__, PCPU_GET(cpuid), PCPU_GET(hart)); } } +#endif -SYSINIT(identcpu, SI_SUB_CPU, SI_ORDER_ANY, fill_elf_hwcap, NULL); +static void +identify_cpu_features(struct cpu_desc *desc) +{ +#ifdef FDT + identify_cpu_features_fdt(desc); #endif +} static void identify_cpu_vendor(struct cpu_desc *desc) @@ -377,6 +392,8 @@ identify_cpu_vendor(desc); identify_cpu_microarch(desc); + + identify_cpu_features(desc); } void