[RFC V2 PATCH 7/9] riscv: report misaligned accesses emulation to hwprobe

From: Clément Léger
Date: Tue Jul 04 2023 - 10:12:05 EST


hwprobe provides a way to report if misaligned access are emulated. In
order to correctly populate that feature, if the SBI delegated us
misaligned access handling, then we can check if it actually traps when
doing a misaligned access. This can be checked using an exception table
entry which will actually be used when a misaligned access is done from
kernel mode.

Signed-off-by: Clément Léger <cleger@xxxxxxxxxxxx>
---
arch/riscv/include/asm/cpufeature.h | 2 ++
arch/riscv/kernel/setup.c | 2 ++
arch/riscv/kernel/traps_misaligned.c | 32 ++++++++++++++++++++++++++++
3 files changed, 36 insertions(+)

diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h
index 808d5403f2ac..7e968499db49 100644
--- a/arch/riscv/include/asm/cpufeature.h
+++ b/arch/riscv/include/asm/cpufeature.h
@@ -20,4 +20,6 @@ DECLARE_PER_CPU(struct riscv_cpuinfo, riscv_cpuinfo);

DECLARE_PER_CPU(long, misaligned_access_speed);

+void __init misaligned_emulation_init(void);
+
#endif
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 36b026057503..820a8158e4f7 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -23,6 +23,7 @@

#include <asm/alternative.h>
#include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
#include <asm/early_ioremap.h>
#include <asm/pgtable.h>
@@ -284,6 +285,7 @@ void __init setup_arch(char **cmdline_p)

init_resources();
sbi_init();
+ misaligned_emulation_init();

#ifdef CONFIG_KASAN
kasan_init();
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 39ec6caa6234..243ef9314734 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -14,6 +14,8 @@
#include <asm/ptrace.h>
#include <asm/csr.h>
#include <asm/entry-common.h>
+#include <asm/hwprobe.h>
+#include <asm/cpufeature.h>

#define INSN_MATCH_LB 0x3
#define INSN_MASK_LB 0x707f
@@ -441,3 +443,33 @@ int handle_misaligned_store(struct pt_regs *regs)

return 0;
}
+
+void __init misaligned_emulation_init(void)
+{
+ int cpu;
+ unsigned long emulated = 1, tmp_var;
+
+ /* Temporarily disable unaligned accesses support so that we fixup the
+ * exception for code below.
+ */
+ unaligned_enabled = 0;
+
+ __asm__ __volatile__ (
+ "1:\n"
+ " ld %[tmp], 1(%[ptr])\n"
+ " li %[emulated], 0\n"
+ "2:\n"
+ _ASM_EXTABLE(1b, 2b)
+ : [emulated] "+r" (emulated), [tmp] "=r" (tmp_var)
+ : [ptr] "r" (&tmp_var)
+ : "memory" );
+
+ unaligned_enabled = 1;
+ if (!emulated)
+ return;
+
+ for_each_possible_cpu(cpu) {
+ per_cpu(misaligned_access_speed, cpu) =
+ RISCV_HWPROBE_MISALIGNED_EMULATED;
+ }
+}
--
2.40.1