Currently, we set hwcap based on first valid hart from DT. This may not
be correct always as that hart might not be current booting cpu or may
have a different capability.

Set hwcap as the capabilities supported by all possible harts with "okay"
status.

Signed-off-by: Atish Patra <atish.pa...@wdc.com>
---
 arch/riscv/kernel/cpufeature.c | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index e7a4701f..bc29b010 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -20,6 +20,7 @@
 #include <linux/of.h>
 #include <asm/processor.h>
 #include <asm/hwcap.h>
+#include <asm/smp.h>
 
 unsigned long elf_hwcap __read_mostly;
 #ifdef CONFIG_FPU
@@ -42,28 +43,30 @@ void riscv_fill_hwcap(void)
 
        elf_hwcap = 0;
 
-       /*
-        * We don't support running Linux on hertergenous ISA systems.  For
-        * now, we just check the ISA of the first "okay" processor.
-        */
        for_each_of_cpu_node(node) {
-               if (riscv_of_processor_hartid(node) >= 0)
-                       break;
-       }
-       if (!node) {
-               pr_warn("Unable to find \"cpu\" devicetree entry\n");
-               return;
-       }
+               unsigned long this_hwcap = 0;
 
-       if (of_property_read_string(node, "riscv,isa", &isa)) {
-               pr_warn("Unable to find \"riscv,isa\" devicetree entry\n");
-               of_node_put(node);
-               return;
-       }
-       of_node_put(node);
+               if (riscv_of_processor_hartid(node) < 0)
+                       continue;
 
-       for (i = 0; i < strlen(isa); ++i)
-               elf_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
+               if (of_property_read_string(node, "riscv,isa", &isa)) {
+                       pr_warn("Unable to find \"riscv,isa\" devicetree 
entry\n");
+                       continue;
+               }
+
+               for (i = 0; i < strlen(isa); ++i)
+                       this_hwcap |= isa2hwcap[(unsigned char)(isa[i])];
+
+               /*
+                * All "okay" hart should have same isa. Set HWCAP based on
+                * common capabilities of every "okay" hart, in case they don't
+                * have.
+                */
+               if (elf_hwcap)
+                       elf_hwcap &= this_hwcap;
+               else
+                       elf_hwcap = this_hwcap;
+       }
 
        /* We don't support systems with F but without D, so mask those out
         * here. */
-- 
2.7.4

Reply via email to