RISC-V: Check scalar unaligned access on all CPUs
authorJesse Taube <jesse@rivosinc.com>
Thu, 17 Oct 2024 19:00:18 +0000 (12:00 -0700)
committerPalmer Dabbelt <palmer@rivosinc.com>
Fri, 18 Oct 2024 19:38:10 +0000 (12:38 -0700)
Originally, the check_unaligned_access_emulated_all_cpus function
only checked the boot hart. This fixes the function to check all
harts.

Fixes: 71c54b3d169d ("riscv: report misaligned accesses emulation to hwprobe")
Signed-off-by: Jesse Taube <jesse@rivosinc.com>
Reviewed-by: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Evan Green <evan@rivosinc.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20241017-jesse_unaligned_vector-v10-1-5b33500160f8@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/cpufeature.h
arch/riscv/kernel/traps_misaligned.c

index 45f9c1171a486a4dc6a4e0c80d64bf80a724b48f..dfa5cdddd3671b2f7ab6ec70cb9c1642b527879d 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/jump_label.h>
+#include <linux/workqueue.h>
 #include <asm/hwcap.h>
 #include <asm/alternative-macros.h>
 #include <asm/errno.h>
@@ -60,6 +61,7 @@ void riscv_user_isa_enable(void);
 
 #if defined(CONFIG_RISCV_MISALIGNED)
 bool check_unaligned_access_emulated_all_cpus(void);
+void check_unaligned_access_emulated(struct work_struct *work __always_unused);
 void unaligned_emulation_finish(void);
 bool unaligned_ctl_available(void);
 DECLARE_PER_CPU(long, misaligned_access_speed);
index d4fd8af7aaf5a937de9c3f50f0d52cd51f845645..d076dde5ad20434412a05ff18fe85194f6127bb4 100644 (file)
@@ -526,11 +526,11 @@ int handle_misaligned_store(struct pt_regs *regs)
        return 0;
 }
 
-static bool check_unaligned_access_emulated(int cpu)
+void check_unaligned_access_emulated(struct work_struct *work __always_unused)
 {
+       int cpu = smp_processor_id();
        long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
        unsigned long tmp_var, tmp_val;
-       bool misaligned_emu_detected;
 
        *mas_ptr = RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN;
 
@@ -538,19 +538,16 @@ static bool check_unaligned_access_emulated(int cpu)
                "       "REG_L" %[tmp], 1(%[ptr])\n"
                : [tmp] "=r" (tmp_val) : [ptr] "r" (&tmp_var) : "memory");
 
-       misaligned_emu_detected = (*mas_ptr == RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED);
        /*
         * If unaligned_ctl is already set, this means that we detected that all
         * CPUS uses emulated misaligned access at boot time. If that changed
         * when hotplugging the new cpu, this is something we don't handle.
         */
-       if (unlikely(unaligned_ctl && !misaligned_emu_detected)) {
+       if (unlikely(unaligned_ctl && (*mas_ptr != RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED))) {
                pr_crit("CPU misaligned accesses non homogeneous (expected all emulated)\n");
                while (true)
                        cpu_relax();
        }
-
-       return misaligned_emu_detected;
 }
 
 bool check_unaligned_access_emulated_all_cpus(void)
@@ -562,8 +559,11 @@ bool check_unaligned_access_emulated_all_cpus(void)
         * accesses emulated since tasks requesting such control can run on any
         * CPU.
         */
+       schedule_on_each_cpu(check_unaligned_access_emulated);
+
        for_each_online_cpu(cpu)
-               if (!check_unaligned_access_emulated(cpu))
+               if (per_cpu(misaligned_access_speed, cpu)
+                   != RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED)
                        return false;
 
        unaligned_ctl = true;