Commit fd94de9f authored by Clément Léger's avatar Clément Léger Committed by Alexandre Ghiti
Browse files

riscv: misaligned: factorize trap handling



Since both load/store and user/kernel should use almost the same path and
that we are going to add some code around that, factorize it.

Signed-off-by: default avatarClément Léger <cleger@rivosinc.com>
Reviewed-by: default avatarAlexandre Ghiti <alexghiti@rivosinc.com>
Link: https://lore.kernel.org/r/20250422162324.956065-2-cleger@rivosinc.com


Signed-off-by: default avatarAlexandre Ghiti <alexghiti@rivosinc.com>
parent eb16b372
Loading
Loading
Loading
Loading
+36 −30
Original line number Diff line number Diff line
@@ -198,47 +198,53 @@ 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)
{
	if (user_mode(regs)) {
	irqentry_state_t state;

	if (user_mode(regs))
		irqentry_enter_from_user_mode(regs);
	else
		state = irqentry_nmi_enter(regs);

		if (handle_misaligned_load(regs))
	if (misaligned_handler[type].handler(regs))
		do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
			      "Oops - load address misaligned");
			      misaligned_handler[type].type_str);

	if (user_mode(regs))
		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");

	else
		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,