1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2020 Western Digital Corporation or its affiliates.
5 #include <linux/kernel.h>
6 #include <linux/init.h>
8 #include <linux/module.h>
9 #include <linux/perf_event.h>
10 #include <linux/irq.h>
11 #include <linux/stringify.h>
13 #include <asm/processor.h>
14 #include <asm/ptrace.h>
16 #include <asm/entry-common.h>
17 #include <asm/hwprobe.h>
18 #include <asm/cpufeature.h>
19 #include <asm/vector.h>
21 #define INSN_MATCH_LB 0x3
22 #define INSN_MASK_LB 0x707f
23 #define INSN_MATCH_LH 0x1003
24 #define INSN_MASK_LH 0x707f
25 #define INSN_MATCH_LW 0x2003
26 #define INSN_MASK_LW 0x707f
27 #define INSN_MATCH_LD 0x3003
28 #define INSN_MASK_LD 0x707f
29 #define INSN_MATCH_LBU 0x4003
30 #define INSN_MASK_LBU 0x707f
31 #define INSN_MATCH_LHU 0x5003
32 #define INSN_MASK_LHU 0x707f
33 #define INSN_MATCH_LWU 0x6003
34 #define INSN_MASK_LWU 0x707f
35 #define INSN_MATCH_SB 0x23
36 #define INSN_MASK_SB 0x707f
37 #define INSN_MATCH_SH 0x1023
38 #define INSN_MASK_SH 0x707f
39 #define INSN_MATCH_SW 0x2023
40 #define INSN_MASK_SW 0x707f
41 #define INSN_MATCH_SD 0x3023
42 #define INSN_MASK_SD 0x707f
44 #define INSN_MATCH_FLW 0x2007
45 #define INSN_MASK_FLW 0x707f
46 #define INSN_MATCH_FLD 0x3007
47 #define INSN_MASK_FLD 0x707f
48 #define INSN_MATCH_FLQ 0x4007
49 #define INSN_MASK_FLQ 0x707f
50 #define INSN_MATCH_FSW 0x2027
51 #define INSN_MASK_FSW 0x707f
52 #define INSN_MATCH_FSD 0x3027
53 #define INSN_MASK_FSD 0x707f
54 #define INSN_MATCH_FSQ 0x4027
55 #define INSN_MASK_FSQ 0x707f
57 #define INSN_MATCH_C_LD 0x6000
58 #define INSN_MASK_C_LD 0xe003
59 #define INSN_MATCH_C_SD 0xe000
60 #define INSN_MASK_C_SD 0xe003
61 #define INSN_MATCH_C_LW 0x4000
62 #define INSN_MASK_C_LW 0xe003
63 #define INSN_MATCH_C_SW 0xc000
64 #define INSN_MASK_C_SW 0xe003
65 #define INSN_MATCH_C_LDSP 0x6002
66 #define INSN_MASK_C_LDSP 0xe003
67 #define INSN_MATCH_C_SDSP 0xe002
68 #define INSN_MASK_C_SDSP 0xe003
69 #define INSN_MATCH_C_LWSP 0x4002
70 #define INSN_MASK_C_LWSP 0xe003
71 #define INSN_MATCH_C_SWSP 0xc002
72 #define INSN_MASK_C_SWSP 0xe003
74 #define INSN_MATCH_C_FLD 0x2000
75 #define INSN_MASK_C_FLD 0xe003
76 #define INSN_MATCH_C_FLW 0x6000
77 #define INSN_MASK_C_FLW 0xe003
78 #define INSN_MATCH_C_FSD 0xa000
79 #define INSN_MASK_C_FSD 0xe003
80 #define INSN_MATCH_C_FSW 0xe000
81 #define INSN_MASK_C_FSW 0xe003
82 #define INSN_MATCH_C_FLDSP 0x2002
83 #define INSN_MASK_C_FLDSP 0xe003
84 #define INSN_MATCH_C_FSDSP 0xa002
85 #define INSN_MASK_C_FSDSP 0xe003
86 #define INSN_MATCH_C_FLWSP 0x6002
87 #define INSN_MASK_C_FLWSP 0xe003
88 #define INSN_MATCH_C_FSWSP 0xe002
89 #define INSN_MASK_C_FSWSP 0xe003
91 #define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4)
93 #if defined(CONFIG_64BIT)
94 #define LOG_REGBYTES 3
97 #define LOG_REGBYTES 2
100 #define REGBYTES (1 << LOG_REGBYTES)
101 #define XLEN_MINUS_16 ((XLEN) - 16)
108 #define RV_X(x, s, n) (((x) >> (s)) & ((1 << (n)) - 1))
109 #define RVC_LW_IMM(x) ((RV_X(x, 6, 1) << 2) | \
110 (RV_X(x, 10, 3) << 3) | \
111 (RV_X(x, 5, 1) << 6))
112 #define RVC_LD_IMM(x) ((RV_X(x, 10, 3) << 3) | \
113 (RV_X(x, 5, 2) << 6))
114 #define RVC_LWSP_IMM(x) ((RV_X(x, 4, 3) << 2) | \
115 (RV_X(x, 12, 1) << 5) | \
116 (RV_X(x, 2, 2) << 6))
117 #define RVC_LDSP_IMM(x) ((RV_X(x, 5, 2) << 3) | \
118 (RV_X(x, 12, 1) << 5) | \
119 (RV_X(x, 2, 3) << 6))
120 #define RVC_SWSP_IMM(x) ((RV_X(x, 9, 4) << 2) | \
121 (RV_X(x, 7, 2) << 6))
122 #define RVC_SDSP_IMM(x) ((RV_X(x, 10, 3) << 3) | \
123 (RV_X(x, 7, 3) << 6))
124 #define RVC_RS1S(insn) (8 + RV_X(insn, SH_RD, 3))
125 #define RVC_RS2S(insn) (8 + RV_X(insn, SH_RS2C, 3))
126 #define RVC_RS2(insn) RV_X(insn, SH_RS2C, 5)
128 #define SHIFT_RIGHT(x, y) \
129 ((y) < 0 ? ((x) << -(y)) : ((x) >> (y)))
132 ((1 << (5 + LOG_REGBYTES)) - (1 << LOG_REGBYTES))
134 #define REG_OFFSET(insn, pos) \
135 (SHIFT_RIGHT((insn), (pos) - LOG_REGBYTES) & REG_MASK)
137 #define REG_PTR(insn, pos, regs) \
138 (ulong *)((ulong)(regs) + REG_OFFSET(insn, pos))
140 #define GET_RS1(insn, regs) (*REG_PTR(insn, SH_RS1, regs))
141 #define GET_RS2(insn, regs) (*REG_PTR(insn, SH_RS2, regs))
142 #define GET_RS1S(insn, regs) (*REG_PTR(RVC_RS1S(insn), 0, regs))
143 #define GET_RS2S(insn, regs) (*REG_PTR(RVC_RS2S(insn), 0, regs))
144 #define GET_RS2C(insn, regs) (*REG_PTR(insn, SH_RS2C, regs))
145 #define GET_SP(regs) (*REG_PTR(2, 0, regs))
146 #define SET_RD(insn, regs, val) (*REG_PTR(insn, SH_RD, regs) = (val))
147 #define IMM_I(insn) ((s32)(insn) >> 20)
148 #define IMM_S(insn) (((s32)(insn) >> 25 << 5) | \
149 (s32)(((insn) >> 7) & 0x1f))
150 #define MASK_FUNCT3 0x7000
152 #define GET_PRECISION(insn) (((insn) >> 25) & 3)
153 #define GET_RM(insn) (((insn) >> 12) & 7)
154 #define PRECISION_S 0
155 #define PRECISION_D 1
159 #define FP_GET_RD(insn) (insn >> 7 & 0x1F)
161 extern void put_f32_reg(unsigned long fp_reg
, unsigned long value
);
163 static int set_f32_rd(unsigned long insn
, struct pt_regs
*regs
,
166 unsigned long fp_reg
= FP_GET_RD(insn
);
168 put_f32_reg(fp_reg
, val
);
169 regs
->status
|= SR_FS_DIRTY
;
174 extern void put_f64_reg(unsigned long fp_reg
, unsigned long value
);
176 static int set_f64_rd(unsigned long insn
, struct pt_regs
*regs
, u64 val
)
178 unsigned long fp_reg
= FP_GET_RD(insn
);
181 #if __riscv_xlen == 32
182 value
= (unsigned long) &val
;
186 put_f64_reg(fp_reg
, value
);
187 regs
->status
|= SR_FS_DIRTY
;
192 #if __riscv_xlen == 32
193 extern void get_f64_reg(unsigned long fp_reg
, u64
*value
);
195 static u64
get_f64_rs(unsigned long insn
, u8 fp_reg_offset
,
196 struct pt_regs
*regs
)
198 unsigned long fp_reg
= (insn
>> fp_reg_offset
) & 0x1F;
201 get_f64_reg(fp_reg
, &val
);
202 regs
->status
|= SR_FS_DIRTY
;
208 extern unsigned long get_f64_reg(unsigned long fp_reg
);
210 static unsigned long get_f64_rs(unsigned long insn
, u8 fp_reg_offset
,
211 struct pt_regs
*regs
)
213 unsigned long fp_reg
= (insn
>> fp_reg_offset
) & 0x1F;
216 val
= get_f64_reg(fp_reg
);
217 regs
->status
|= SR_FS_DIRTY
;
224 extern unsigned long get_f32_reg(unsigned long fp_reg
);
226 static unsigned long get_f32_rs(unsigned long insn
, u8 fp_reg_offset
,
227 struct pt_regs
*regs
)
229 unsigned long fp_reg
= (insn
>> fp_reg_offset
) & 0x1F;
232 val
= get_f32_reg(fp_reg
);
233 regs
->status
|= SR_FS_DIRTY
;
238 #else /* CONFIG_FPU */
239 static void set_f32_rd(unsigned long insn
, struct pt_regs
*regs
,
240 unsigned long val
) {}
242 static void set_f64_rd(unsigned long insn
, struct pt_regs
*regs
, u64 val
) {}
244 static unsigned long get_f64_rs(unsigned long insn
, u8 fp_reg_offset
,
245 struct pt_regs
*regs
)
250 static unsigned long get_f32_rs(unsigned long insn
, u8 fp_reg_offset
,
251 struct pt_regs
*regs
)
258 #define GET_F64_RS2(insn, regs) (get_f64_rs(insn, 20, regs))
259 #define GET_F64_RS2C(insn, regs) (get_f64_rs(insn, 2, regs))
260 #define GET_F64_RS2S(insn, regs) (get_f64_rs(RVC_RS2S(insn), 0, regs))
262 #define GET_F32_RS2(insn, regs) (get_f32_rs(insn, 20, regs))
263 #define GET_F32_RS2C(insn, regs) (get_f32_rs(insn, 2, regs))
264 #define GET_F32_RS2S(insn, regs) (get_f32_rs(RVC_RS2S(insn), 0, regs))
266 #define __read_insn(regs, insn, insn_addr, type) \
270 if (user_mode(regs)) { \
271 __ret = __get_user(insn, (type __user *) insn_addr); \
273 insn = *(type *)insn_addr; \
280 static inline int get_insn(struct pt_regs
*regs
, ulong epc
, ulong
*r_insn
)
287 if (__read_insn(regs
, insn
, epc
, u16
))
289 /* __get_user() uses regular "lw" which sign extend the loaded
290 * value make sure to clear higher order bits in case we "or" it
291 * below with the upper 16 bits half.
293 insn
&= GENMASK(15, 0);
294 if ((insn
& __INSN_LENGTH_MASK
) != __INSN_LENGTH_32
) {
299 if (__read_insn(regs
, tmp
, epc
, u16
))
301 *r_insn
= (tmp
<< 16) | insn
;
305 if (__read_insn(regs
, insn
, epc
, u32
))
307 if ((insn
& __INSN_LENGTH_MASK
) == __INSN_LENGTH_32
) {
311 insn
&= GENMASK(15, 0);
325 int unaligned_enabled __read_mostly
= 1; /* Enabled by default */
327 #ifdef CONFIG_RISCV_VECTOR_MISALIGNED
328 static int handle_vector_misaligned_load(struct pt_regs
*regs
)
330 unsigned long epc
= regs
->epc
;
333 if (get_insn(regs
, epc
, &insn
))
336 /* Only return 0 when in check_vector_unaligned_access_emulated */
337 if (*this_cpu_ptr(&vector_misaligned_access
) == RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN
) {
338 *this_cpu_ptr(&vector_misaligned_access
) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED
;
339 regs
->epc
= epc
+ INSN_LEN(insn
);
343 /* If vector instruction we don't emulate it yet */
348 static int handle_vector_misaligned_load(struct pt_regs
*regs
)
354 static int handle_scalar_misaligned_load(struct pt_regs
*regs
)
357 unsigned long epc
= regs
->epc
;
359 unsigned long addr
= regs
->badaddr
;
360 int fp
= 0, shift
= 0, len
= 0;
362 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS
, 1, regs
, addr
);
364 #ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS
365 *this_cpu_ptr(&misaligned_access_speed
) = RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED
;
368 if (!unaligned_enabled
)
371 if (user_mode(regs
) && (current
->thread
.align_ctl
& PR_UNALIGN_SIGBUS
))
374 if (get_insn(regs
, epc
, &insn
))
379 if ((insn
& INSN_MASK_LW
) == INSN_MATCH_LW
) {
381 shift
= 8 * (sizeof(unsigned long) - len
);
382 #if defined(CONFIG_64BIT)
383 } else if ((insn
& INSN_MASK_LD
) == INSN_MATCH_LD
) {
385 shift
= 8 * (sizeof(unsigned long) - len
);
386 } else if ((insn
& INSN_MASK_LWU
) == INSN_MATCH_LWU
) {
389 } else if ((insn
& INSN_MASK_FLD
) == INSN_MATCH_FLD
) {
392 } else if ((insn
& INSN_MASK_FLW
) == INSN_MATCH_FLW
) {
395 } else if ((insn
& INSN_MASK_LH
) == INSN_MATCH_LH
) {
397 shift
= 8 * (sizeof(unsigned long) - len
);
398 } else if ((insn
& INSN_MASK_LHU
) == INSN_MATCH_LHU
) {
400 #if defined(CONFIG_64BIT)
401 } else if ((insn
& INSN_MASK_C_LD
) == INSN_MATCH_C_LD
) {
403 shift
= 8 * (sizeof(unsigned long) - len
);
404 insn
= RVC_RS2S(insn
) << SH_RD
;
405 } else if ((insn
& INSN_MASK_C_LDSP
) == INSN_MATCH_C_LDSP
&&
406 ((insn
>> SH_RD
) & 0x1f)) {
408 shift
= 8 * (sizeof(unsigned long) - len
);
410 } else if ((insn
& INSN_MASK_C_LW
) == INSN_MATCH_C_LW
) {
412 shift
= 8 * (sizeof(unsigned long) - len
);
413 insn
= RVC_RS2S(insn
) << SH_RD
;
414 } else if ((insn
& INSN_MASK_C_LWSP
) == INSN_MATCH_C_LWSP
&&
415 ((insn
>> SH_RD
) & 0x1f)) {
417 shift
= 8 * (sizeof(unsigned long) - len
);
418 } else if ((insn
& INSN_MASK_C_FLD
) == INSN_MATCH_C_FLD
) {
421 insn
= RVC_RS2S(insn
) << SH_RD
;
422 } else if ((insn
& INSN_MASK_C_FLDSP
) == INSN_MATCH_C_FLDSP
) {
425 #if defined(CONFIG_32BIT)
426 } else if ((insn
& INSN_MASK_C_FLW
) == INSN_MATCH_C_FLW
) {
429 insn
= RVC_RS2S(insn
) << SH_RD
;
430 } else if ((insn
& INSN_MASK_C_FLWSP
) == INSN_MATCH_C_FLWSP
) {
439 if (!IS_ENABLED(CONFIG_FPU
) && fp
)
443 if (user_mode(regs
)) {
444 if (copy_from_user(&val
, (u8 __user
*)addr
, len
))
447 memcpy(&val
, (u8
*)addr
, len
);
451 SET_RD(insn
, regs
, val
.data_ulong
<< shift
>> shift
);
453 set_f64_rd(insn
, regs
, val
.data_u64
);
455 set_f32_rd(insn
, regs
, val
.data_ulong
);
457 regs
->epc
= epc
+ INSN_LEN(insn
);
462 static int handle_scalar_misaligned_store(struct pt_regs
*regs
)
465 unsigned long epc
= regs
->epc
;
467 unsigned long addr
= regs
->badaddr
;
470 perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS
, 1, regs
, addr
);
472 if (!unaligned_enabled
)
475 if (user_mode(regs
) && (current
->thread
.align_ctl
& PR_UNALIGN_SIGBUS
))
478 if (get_insn(regs
, epc
, &insn
))
483 val
.data_ulong
= GET_RS2(insn
, regs
);
485 if ((insn
& INSN_MASK_SW
) == INSN_MATCH_SW
) {
487 #if defined(CONFIG_64BIT)
488 } else if ((insn
& INSN_MASK_SD
) == INSN_MATCH_SD
) {
491 } else if ((insn
& INSN_MASK_FSD
) == INSN_MATCH_FSD
) {
494 val
.data_u64
= GET_F64_RS2(insn
, regs
);
495 } else if ((insn
& INSN_MASK_FSW
) == INSN_MATCH_FSW
) {
498 val
.data_ulong
= GET_F32_RS2(insn
, regs
);
499 } else if ((insn
& INSN_MASK_SH
) == INSN_MATCH_SH
) {
501 #if defined(CONFIG_64BIT)
502 } else if ((insn
& INSN_MASK_C_SD
) == INSN_MATCH_C_SD
) {
504 val
.data_ulong
= GET_RS2S(insn
, regs
);
505 } else if ((insn
& INSN_MASK_C_SDSP
) == INSN_MATCH_C_SDSP
) {
507 val
.data_ulong
= GET_RS2C(insn
, regs
);
509 } else if ((insn
& INSN_MASK_C_SW
) == INSN_MATCH_C_SW
) {
511 val
.data_ulong
= GET_RS2S(insn
, regs
);
512 } else if ((insn
& INSN_MASK_C_SWSP
) == INSN_MATCH_C_SWSP
) {
514 val
.data_ulong
= GET_RS2C(insn
, regs
);
515 } else if ((insn
& INSN_MASK_C_FSD
) == INSN_MATCH_C_FSD
) {
518 val
.data_u64
= GET_F64_RS2S(insn
, regs
);
519 } else if ((insn
& INSN_MASK_C_FSDSP
) == INSN_MATCH_C_FSDSP
) {
522 val
.data_u64
= GET_F64_RS2C(insn
, regs
);
523 #if !defined(CONFIG_64BIT)
524 } else if ((insn
& INSN_MASK_C_FSW
) == INSN_MATCH_C_FSW
) {
527 val
.data_ulong
= GET_F32_RS2S(insn
, regs
);
528 } else if ((insn
& INSN_MASK_C_FSWSP
) == INSN_MATCH_C_FSWSP
) {
531 val
.data_ulong
= GET_F32_RS2C(insn
, regs
);
538 if (!IS_ENABLED(CONFIG_FPU
) && fp
)
541 if (user_mode(regs
)) {
542 if (copy_to_user((u8 __user
*)addr
, &val
, len
))
545 memcpy((u8
*)addr
, &val
, len
);
548 regs
->epc
= epc
+ INSN_LEN(insn
);
553 int handle_misaligned_load(struct pt_regs
*regs
)
555 unsigned long epc
= regs
->epc
;
558 if (IS_ENABLED(CONFIG_RISCV_VECTOR_MISALIGNED
)) {
559 if (get_insn(regs
, epc
, &insn
))
562 if (insn_is_vector(insn
))
563 return handle_vector_misaligned_load(regs
);
566 if (IS_ENABLED(CONFIG_RISCV_SCALAR_MISALIGNED
))
567 return handle_scalar_misaligned_load(regs
);
572 int handle_misaligned_store(struct pt_regs
*regs
)
574 if (IS_ENABLED(CONFIG_RISCV_SCALAR_MISALIGNED
))
575 return handle_scalar_misaligned_store(regs
);
580 #ifdef CONFIG_RISCV_VECTOR_MISALIGNED
581 void check_vector_unaligned_access_emulated(struct work_struct
*work __always_unused
)
583 long *mas_ptr
= this_cpu_ptr(&vector_misaligned_access
);
584 unsigned long tmp_var
;
586 *mas_ptr
= RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN
;
588 kernel_vector_begin();
590 * In pre-13.0.0 versions of GCC, vector registers cannot appear in
591 * the clobber list. This inline asm clobbers v0, but since we do not
592 * currently build the kernel with V enabled, the v0 clobber arg is not
593 * needed (as the compiler will not emit vector code itself). If the kernel
594 * is changed to build with V enabled, the clobber arg will need to be
597 __asm__
__volatile__ (
600 ".option arch, +zve32x\n\t"
601 " vsetivli zero, 1, e16, m1, ta, ma\n\t" // Vectors of 16b
602 " vle16.v v0, (%[ptr])\n\t" // Load bytes
604 : : [ptr
] "r" ((u8
*)&tmp_var
+ 1));
608 bool check_vector_unaligned_access_emulated_all_cpus(void)
613 for_each_online_cpu(cpu
)
614 per_cpu(vector_misaligned_access
, cpu
) = RISCV_HWPROBE_MISALIGNED_VECTOR_UNSUPPORTED
;
618 schedule_on_each_cpu(check_vector_unaligned_access_emulated
);
620 for_each_online_cpu(cpu
)
621 if (per_cpu(vector_misaligned_access
, cpu
)
622 == RISCV_HWPROBE_MISALIGNED_VECTOR_UNKNOWN
)
628 bool check_vector_unaligned_access_emulated_all_cpus(void)
634 #ifdef CONFIG_RISCV_SCALAR_MISALIGNED
636 static bool unaligned_ctl __read_mostly
;
638 void check_unaligned_access_emulated(struct work_struct
*work __always_unused
)
640 int cpu
= smp_processor_id();
641 long *mas_ptr
= per_cpu_ptr(&misaligned_access_speed
, cpu
);
642 unsigned long tmp_var
, tmp_val
;
644 *mas_ptr
= RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN
;
646 __asm__
__volatile__ (
647 " "REG_L
" %[tmp], 1(%[ptr])\n"
648 : [tmp
] "=r" (tmp_val
) : [ptr
] "r" (&tmp_var
) : "memory");
651 * If unaligned_ctl is already set, this means that we detected that all
652 * CPUS uses emulated misaligned access at boot time. If that changed
653 * when hotplugging the new cpu, this is something we don't handle.
655 if (unlikely(unaligned_ctl
&& (*mas_ptr
!= RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED
))) {
656 pr_crit("CPU misaligned accesses non homogeneous (expected all emulated)\n");
662 bool check_unaligned_access_emulated_all_cpus(void)
667 * We can only support PR_UNALIGN controls if all CPUs have misaligned
668 * accesses emulated since tasks requesting such control can run on any
671 schedule_on_each_cpu(check_unaligned_access_emulated
);
673 for_each_online_cpu(cpu
)
674 if (per_cpu(misaligned_access_speed
, cpu
)
675 != RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED
)
678 unaligned_ctl
= true;
682 bool unaligned_ctl_available(void)
684 return unaligned_ctl
;
687 bool check_unaligned_access_emulated_all_cpus(void)