Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+62 -29
+6
arch/riscv/kernel/process.c
··· 275 275 unsigned long pmm; 276 276 u8 pmlen; 277 277 278 + if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) 279 + return -EINVAL; 280 + 278 281 if (is_compat_thread(ti)) 279 282 return -EINVAL; 280 283 ··· 332 329 { 333 330 struct thread_info *ti = task_thread_info(task); 334 331 long ret = 0; 332 + 333 + if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM)) 334 + return -EINVAL; 335 335 336 336 if (is_compat_thread(ti)) 337 337 return -EINVAL;
+37 -27
arch/riscv/kernel/traps.c
··· 198 198 DO_ERROR_INFO(do_trap_load_fault, 199 199 SIGSEGV, SEGV_ACCERR, "load access fault"); 200 200 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) 202 220 { 221 + irqentry_state_t state; 222 + 203 223 if (user_mode(regs)) { 204 224 irqentry_enter_from_user_mode(regs); 225 + local_irq_enable(); 226 + } else { 227 + state = irqentry_nmi_enter(regs); 228 + } 205 229 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); 209 233 234 + if (user_mode(regs)) { 235 + local_irq_disable(); 210 236 irqentry_exit_to_user_mode(regs); 211 237 } 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 - 218 238 irqentry_nmi_exit(regs, state); 219 239 } 240 + } 241 + 242 + asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs) 243 + { 244 + do_trap_misaligned(regs, MISALIGNED_LOAD); 220 245 } 221 246 222 247 asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs) 223 248 { 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"); 238 - 239 - irqentry_nmi_exit(regs, state); 240 - } 249 + do_trap_misaligned(regs, MISALIGNED_STORE); 241 250 } 251 + 242 252 DO_ERROR_INFO(do_trap_store_fault, 243 253 SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault"); 244 254 DO_ERROR_INFO(do_trap_ecall_s,
+18 -1
arch/riscv/kernel/traps_misaligned.c
··· 88 88 #define INSN_MATCH_C_FSWSP 0xe002 89 89 #define INSN_MASK_C_FSWSP 0xe003 90 90 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 + 91 98 #define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4) 92 99 93 100 #if defined(CONFIG_64BIT) ··· 275 268 int __ret; \ 276 269 \ 277 270 if (user_mode(regs)) { \ 278 - __ret = __get_user(insn, (type __user *) insn_addr); \ 271 + __ret = get_user(insn, (type __user *) insn_addr); \ 279 272 } else { \ 280 273 insn = *(type *)insn_addr; \ 281 274 __ret = 0; \ ··· 438 431 fp = 1; 439 432 len = 4; 440 433 #endif 434 + } else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) { 435 + len = 2; 436 + insn = RVC_RS2S(insn) << SH_RD; 437 + } else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) { 438 + len = 2; 439 + shift = 8 * (sizeof(ulong) - len); 440 + insn = RVC_RS2S(insn) << SH_RD; 441 441 } else { 442 442 regs->epc = epc; 443 443 return -1; ··· 544 530 len = 4; 545 531 val.data_ulong = GET_F32_RS2C(insn, regs); 546 532 #endif 533 + } else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) { 534 + len = 2; 535 + val.data_ulong = GET_RS2S(insn, regs); 547 536 } else { 548 537 regs->epc = epc; 549 538 return -1;
+1 -1
scripts/Makefile.vmlinux
··· 13 13 vmlinux-final := vmlinux.unstripped 14 14 15 15 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' $< $@ 17 17 18 18 vmlinux: $(vmlinux-final) FORCE 19 19 $(call if_changed,strip_relocs)