Merge tag 'riscv-fixes-6.15-rc6' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/alexghiti/linux into fixes
riscv fixes for 6.15-rc6 - A fix to handle compressed halfword load/store instructions misaligned accesses - A fix to allow user memory access while handling a misaligned access - 2 fixes to return an error if the pointer masking extension is not implemented on the platform but userspace still tries to access it, which caused oops on some early platforms - A fix to prevent the stripping of .rela.dyn so that a vmlinux loaded by kexec can successfully boot * tag 'riscv-fixes-6.15-rc6' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/alexghiti/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
This commit is contained in:
@@ -275,6 +275,9 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
|
||||
unsigned long pmm;
|
||||
u8 pmlen;
|
||||
|
||||
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM))
|
||||
return -EINVAL;
|
||||
|
||||
if (is_compat_thread(ti))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -330,6 +333,9 @@ long get_tagged_addr_ctrl(struct task_struct *task)
|
||||
struct thread_info *ti = task_thread_info(task);
|
||||
long ret = 0;
|
||||
|
||||
if (!riscv_has_extension_unlikely(RISCV_ISA_EXT_SUPM))
|
||||
return -EINVAL;
|
||||
|
||||
if (is_compat_thread(ti))
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
+37
-27
@@ -198,47 +198,57 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re
|
||||
DO_ERROR_INFO(do_trap_load_fault,
|
||||
SIGSEGV, SEGV_ACCERR, "load access fault");
|
||||
|
||||
asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs)
|
||||
enum misaligned_access_type {
|
||||
MISALIGNED_STORE,
|
||||
MISALIGNED_LOAD,
|
||||
};
|
||||
static const struct {
|
||||
const char *type_str;
|
||||
int (*handler)(struct pt_regs *regs);
|
||||
} misaligned_handler[] = {
|
||||
[MISALIGNED_STORE] = {
|
||||
.type_str = "Oops - store (or AMO) address misaligned",
|
||||
.handler = handle_misaligned_store,
|
||||
},
|
||||
[MISALIGNED_LOAD] = {
|
||||
.type_str = "Oops - load address misaligned",
|
||||
.handler = handle_misaligned_load,
|
||||
},
|
||||
};
|
||||
|
||||
static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type)
|
||||
{
|
||||
irqentry_state_t state;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
irqentry_enter_from_user_mode(regs);
|
||||
local_irq_enable();
|
||||
} else {
|
||||
state = irqentry_nmi_enter(regs);
|
||||
}
|
||||
|
||||
if (handle_misaligned_load(regs))
|
||||
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
|
||||
"Oops - load address misaligned");
|
||||
if (misaligned_handler[type].handler(regs))
|
||||
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
|
||||
misaligned_handler[type].type_str);
|
||||
|
||||
if (user_mode(regs)) {
|
||||
local_irq_disable();
|
||||
irqentry_exit_to_user_mode(regs);
|
||||
} else {
|
||||
irqentry_state_t state = irqentry_nmi_enter(regs);
|
||||
|
||||
if (handle_misaligned_load(regs))
|
||||
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
|
||||
"Oops - load address misaligned");
|
||||
|
||||
irqentry_nmi_exit(regs, state);
|
||||
}
|
||||
}
|
||||
|
||||
asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs)
|
||||
{
|
||||
do_trap_misaligned(regs, MISALIGNED_LOAD);
|
||||
}
|
||||
|
||||
asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs)
|
||||
{
|
||||
if (user_mode(regs)) {
|
||||
irqentry_enter_from_user_mode(regs);
|
||||
|
||||
if (handle_misaligned_store(regs))
|
||||
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
|
||||
"Oops - store (or AMO) address misaligned");
|
||||
|
||||
irqentry_exit_to_user_mode(regs);
|
||||
} else {
|
||||
irqentry_state_t state = irqentry_nmi_enter(regs);
|
||||
|
||||
if (handle_misaligned_store(regs))
|
||||
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
|
||||
"Oops - store (or AMO) address misaligned");
|
||||
|
||||
irqentry_nmi_exit(regs, state);
|
||||
}
|
||||
do_trap_misaligned(regs, MISALIGNED_STORE);
|
||||
}
|
||||
|
||||
DO_ERROR_INFO(do_trap_store_fault,
|
||||
SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault");
|
||||
DO_ERROR_INFO(do_trap_ecall_s,
|
||||
|
||||
@@ -88,6 +88,13 @@
|
||||
#define INSN_MATCH_C_FSWSP 0xe002
|
||||
#define INSN_MASK_C_FSWSP 0xe003
|
||||
|
||||
#define INSN_MATCH_C_LHU 0x8400
|
||||
#define INSN_MASK_C_LHU 0xfc43
|
||||
#define INSN_MATCH_C_LH 0x8440
|
||||
#define INSN_MASK_C_LH 0xfc43
|
||||
#define INSN_MATCH_C_SH 0x8c00
|
||||
#define INSN_MASK_C_SH 0xfc43
|
||||
|
||||
#define INSN_LEN(insn) ((((insn) & 0x3) < 0x3) ? 2 : 4)
|
||||
|
||||
#if defined(CONFIG_64BIT)
|
||||
@@ -268,7 +275,7 @@ static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset,
|
||||
int __ret; \
|
||||
\
|
||||
if (user_mode(regs)) { \
|
||||
__ret = __get_user(insn, (type __user *) insn_addr); \
|
||||
__ret = get_user(insn, (type __user *) insn_addr); \
|
||||
} else { \
|
||||
insn = *(type *)insn_addr; \
|
||||
__ret = 0; \
|
||||
@@ -431,6 +438,13 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
|
||||
fp = 1;
|
||||
len = 4;
|
||||
#endif
|
||||
} else if ((insn & INSN_MASK_C_LHU) == INSN_MATCH_C_LHU) {
|
||||
len = 2;
|
||||
insn = RVC_RS2S(insn) << SH_RD;
|
||||
} else if ((insn & INSN_MASK_C_LH) == INSN_MATCH_C_LH) {
|
||||
len = 2;
|
||||
shift = 8 * (sizeof(ulong) - len);
|
||||
insn = RVC_RS2S(insn) << SH_RD;
|
||||
} else {
|
||||
regs->epc = epc;
|
||||
return -1;
|
||||
@@ -530,6 +544,9 @@ static int handle_scalar_misaligned_store(struct pt_regs *regs)
|
||||
len = 4;
|
||||
val.data_ulong = GET_F32_RS2C(insn, regs);
|
||||
#endif
|
||||
} else if ((insn & INSN_MASK_C_SH) == INSN_MATCH_C_SH) {
|
||||
len = 2;
|
||||
val.data_ulong = GET_RS2S(insn, regs);
|
||||
} else {
|
||||
regs->epc = epc;
|
||||
return -1;
|
||||
|
||||
@@ -13,7 +13,7 @@ ifdef CONFIG_ARCH_VMLINUX_NEEDS_RELOCS
|
||||
vmlinux-final := vmlinux.unstripped
|
||||
|
||||
quiet_cmd_strip_relocs = RSTRIP $@
|
||||
cmd_strip_relocs = $(OBJCOPY) --remove-section='.rel*' $< $@
|
||||
cmd_strip_relocs = $(OBJCOPY) --remove-section='.rel*' --remove-section=!'.rel*.dyn' $< $@
|
||||
|
||||
vmlinux: $(vmlinux-final) FORCE
|
||||
$(call if_changed,strip_relocs)
|
||||
|
||||
Reference in New Issue
Block a user