Skip to content

Commit 3013c33

Browse files
committed
Merge tag 'riscv-for-linus-6.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux
Pull RISC-V fixes from Palmer Dabbelt: - The compressed half-word misaligned access instructions (c.lhu, c.lh, and c.sh) from the Zcb extension are now properly emulated - A series of fixes to properly emulate permissions while handling userspace misaligned accesses - A pair of fixes for PR_GET_TAGGED_ADDR_CTRL to avoid accessing the envcfg CSR on systems that don't support that CSR, and to report those failures up to userspace - The .rela.dyn section is no longer stripped from vmlinux, as it is necessary to relocate the kernel under some conditions (including kexec) * tag 'riscv-for-linus-6.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux: riscv: Disallow PR_GET_TAGGED_ADDR_CTRL without Supm scripts: Do not strip .rela.dyn section riscv: Fix kernel crash due to PR_SET_TAGGED_ADDR_CTRL riscv: misaligned: use get_user() instead of __get_user() riscv: misaligned: enable IRQs while handling misaligned accesses riscv: misaligned: factorize trap handling riscv: misaligned: Add handling for ZCB instructions
2 parents cc9f062 + 01534f3 commit 3013c33

File tree

4 files changed

+62
-29
lines changed

4 files changed

+62
-29
lines changed

arch/riscv/kernel/process.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,9 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
275275
unsigned long pmm;
276276
u8 pmlen;
277277

278+
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM))
279+
return -EINVAL;
280+
278281
if (is_compat_thread(ti))
279282
return -EINVAL;
280283

@@ -330,6 +333,9 @@ long get_tagged_addr_ctrl(struct task_struct *task)
330333
struct thread_info *ti = task_thread_info(task);
331334
long ret = 0;
332335

336+
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM))
337+
return -EINVAL;
338+
333339
if (is_compat_thread(ti))
334340
return -EINVAL;
335341

arch/riscv/kernel/traps.c

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -198,47 +198,57 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re
198198
DO_ERROR_INFO(do_trap_load_fault,
199199
SIGSEGV, SEGV_ACCERR, "load access fault");
200200

201-
asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs)
201+
enum misaligned_access_type {
202+
MISALIGNED_STORE,
203+
MISALIGNED_LOAD,
204+
};
205+
static const struct {
206+
const char *type_str;
207+
int (*handler)(struct pt_regs *regs);
208+
} misaligned_handler[] = {
209+
[MISALIGNED_STORE] = {
210+
.type_str = "Oops - store (or AMO) address misaligned",
211+
.handler = handle_misaligned_store,
212+
},
213+
[MISALIGNED_LOAD] = {
214+
.type_str = "Oops - load address misaligned",
215+
.handler = handle_misaligned_load,
216+
},
217+
};
218+
219+
static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type)
202220
{
221+
irqentry_state_t state;
222+
203223
if (user_mode(regs)) {
204224
irqentry_enter_from_user_mode(regs);
225+
local_irq_enable();
226+
} else {
227+
state = irqentry_nmi_enter(regs);
228+
}
205229

206-
if (handle_misaligned_load(regs))
207-
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
208-
"Oops - load address misaligned");
230+
if (misaligned_handler[type].handler(regs))
231+
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
232+
misaligned_handler[type].type_str);
209233

234+
if (user_mode(regs)) {
235+
local_irq_disable();
210236
irqentry_exit_to_user_mode(regs);
211237
} else {
212-
irqentry_state_t state = irqentry_nmi_enter(regs);
213-
214-
if (handle_misaligned_load(regs))
215-
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
216-
"Oops - load address misaligned");
217-
218238
irqentry_nmi_exit(regs, state);
219239
}
220240
}
221241

222-
asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs)
242+
asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs)
223243
{
224-
if (user_mode(regs)) {
225-
irqentry_enter_from_user_mode(regs);
226-
227-
if (handle_misaligned_store(regs))
228-
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
229-
"Oops - store (or AMO) address misaligned");
230-
231-
irqentry_exit_to_user_mode(regs);
232-
} else {
233-
irqentry_state_t state = irqentry_nmi_enter(regs);
234-
235-
if (handle_misaligned_store(regs))
236-
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
237-
"Oops - store (or AMO) address misaligned");
244+
do_trap_misaligned(regs, MISALIGNED_LOAD);
245+
}
238246

239-
irqentry_nmi_exit(regs, state);
240-
}
247+
asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs)
248+
{
249+
do_trap_misaligned(regs, MISALIGNED_STORE);
241250
}
251+
242252
DO_ERROR_INFO(do_trap_store_fault,
243253
SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault");
244254
DO_ERROR_INFO(do_trap_ecall_s,

arch/riscv/kernel/traps_misaligned.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@
8888
#define INSN_MATCH_C_FSWSP 0xe002
8989
#define INSN_MASK_C_FSWSP 0xe003
9090

91+
#define INSN_MATCH_C_LHU 0x8400
92+
#define INSN_MASK_C_LHU 0xfc43
93+
#define INSN_MATCH_C_LH 0x8440
94+
#define INSN_MASK_C_LH 0xfc43
95+
#define INSN_MATCH_C_SH 0x8c00
96+
#define INSN_MASK_C_SH 0xfc43
97+
9198
#define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4)
9299

93100
#if defined(CONFIG_64BIT)
@@ -268,7 +275,7 @@ static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset,
268275
int __ret; \
269276
\
270277
if (user_mode(regs)) { \
271-
__ret = __get_user(insn, (type __user *) insn_addr); \
278+
__ret = get_user(insn, (type __user *) insn_addr); \
272279
} else { \
273280
insn = *(type *)insn_addr; \
274281
__ret = 0; \
@@ -431,6 +438,13 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
431438
fp = 1;
432439
len = 4;
433440
#endif
441+
} else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) {
442+
len = 2;
443+
insn = RVC_RS2S(insn) << SH_RD;
444+
} else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) {
445+
len = 2;
446+
shift = 8 * (sizeof(ulong) - len);
447+
insn = RVC_RS2S(insn) << SH_RD;
434448
} else {
435449
regs->epc = epc;
436450
return -1;
@@ -530,6 +544,9 @@ static int handle_scalar_misaligned_store(struct pt_regs *regs)
530544
len = 4;
531545
val.data_ulong = GET_F32_RS2C(insn, regs);
532546
#endif
547+
} else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) {
548+
len = 2;
549+
val.data_ulong = GET_RS2S(insn, regs);
533550
} else {
534551
regs->epc = epc;
535552
return -1;

scripts/Makefile.vmlinux

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ ifdef CONFIG_ARCH_VMLINUX_NEEDS_RELOCS
1313
vmlinux-final := vmlinux.unstripped
1414

1515
quiet_cmd_strip_relocs = RSTRIP $@
16-
cmd_strip_relocs = $(OBJCOPY) --remove-section='.rel*' $< $@
16+
cmd_strip_relocs = $(OBJCOPY) --remove-section='.rel*' --remove-section=!'.rel*.dyn' $< $@
1717

1818
vmlinux: $(vmlinux-final) FORCE
1919
$(call if_changed,strip_relocs)

0 commit comments

Comments
 (0)