riscv: Decouple emulated unaligned accesses from access speed

Detecting if a system traps into the kernel on an unaligned access
can be performed separately from checking the speed of unaligned
accesses. This decoupling will make it possible to selectively enable
or disable each of these checks.

Signed-off-by: Charlie Jenkins <charlie@rivosinc.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
Tested-by: Samuel Holland <samuel.holland@sifive.com>
Link: https://lore.kernel.org/r/20240308-disable_misaligned_probe_config-v9-3-a388770ba0ce@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Change-Id: Ibdd387fc1a9729ef272901fef77db90cb5f1dd0c
This commit is contained in:
Charlie Jenkins 2024-03-08 10:25:57 -08:00 committed by zhangmeng
parent 429f0d5a78
commit 2f19d7b882
3 changed files with 36 additions and 12 deletions

View file

@ -33,6 +33,32 @@ extern struct riscv_isainfo hart_isa[NR_CPUS];
void riscv_user_isa_enable(void); void riscv_user_isa_enable(void);
#if defined(CONFIG_RISCV_MISALIGNED)
bool check_unaligned_access_emulated_all_cpus(void);
void unaligned_emulation_finish(void);
bool unaligned_ctl_available(void);
DECLARE_PER_CPU(long, misaligned_access_speed);
#else
static inline bool unaligned_ctl_available(void)
{
return false;
}
#endif
#if defined(CONFIG_RISCV_PROBE_UNALIGNED_ACCESS)
DECLARE_STATIC_KEY_FALSE(fast_unaligned_access_speed_key);
static __always_inline bool has_fast_unaligned_accesses(void)
{
return static_branch_likely(&fast_unaligned_access_speed_key);
}
#else
static __always_inline bool has_fast_unaligned_accesses(void)
{
if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
return true;
else
return false;
}
#endif
unsigned long riscv_get_elf_hwcap(void); unsigned long riscv_get_elf_hwcap(void);
struct riscv_isa_ext_data { struct riscv_isa_ext_data {

View file

@ -26,9 +26,8 @@
#include <linux/sched/task_stack.h> #include <linux/sched/task_stack.h>
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <asm/cpufeature.h> #include <asm/cacheflush.h>
#include <asm/cpu_ops.h> #include <asm/cpu_ops.h>
#include <asm/cpufeature.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/numa.h> #include <asm/numa.h>
@ -247,8 +246,7 @@ asmlinkage __visible void smp_callin(void)
riscv_ipi_enable(); riscv_ipi_enable();
numa_add_cpu(curr_cpuid); numa_add_cpu(curr_cpuid);
check_unaligned_access(curr_cpuid); set_cpu_online(curr_cpuid, true);
set_cpu_online(curr_cpuid, 1);
if (has_vector()) { if (has_vector()) {
if (riscv_v_setup_vsize()) if (riscv_v_setup_vsize())
@ -261,6 +259,7 @@ asmlinkage __visible void smp_callin(void)
* Remote TLB flushes are ignored while the CPU is offline, so emit * Remote TLB flushes are ignored while the CPU is offline, so emit
* a local TLB flush right now just in case. * a local TLB flush right now just in case.
*/ */
local_flush_icache_all();
local_flush_tlb_all(); local_flush_tlb_all();
complete(&cpu_running); complete(&cpu_running);
/* /*

View file

@ -600,7 +600,7 @@ int handle_misaligned_store(struct pt_regs *regs)
return 0; return 0;
} }
bool check_unaligned_access_emulated(int cpu) static bool check_unaligned_access_emulated(int cpu)
{ {
long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu); long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
unsigned long tmp_var, tmp_val; unsigned long tmp_var, tmp_val;
@ -627,7 +627,7 @@ bool check_unaligned_access_emulated(int cpu)
return misaligned_emu_detected; return misaligned_emu_detected;
} }
void unaligned_emulation_finish(void) bool check_unaligned_access_emulated_all_cpus(void)
{ {
int cpu; int cpu;
@ -636,13 +636,12 @@ void unaligned_emulation_finish(void)
* accesses emulated since tasks requesting such control can run on any * accesses emulated since tasks requesting such control can run on any
* CPU. * CPU.
*/ */
for_each_present_cpu(cpu) { for_each_online_cpu(cpu)
if (per_cpu(misaligned_access_speed, cpu) != if (!check_unaligned_access_emulated(cpu))
RISCV_HWPROBE_MISALIGNED_EMULATED) { return false;
return;
}
}
unaligned_ctl = true; unaligned_ctl = true;
return true;
} }
bool unaligned_ctl_available(void) bool unaligned_ctl_available(void)