From 2ecbbcc7cabdc0147e54ffa90c90efcc33afadd8 Mon Sep 17 00:00:00 2001 From: Zachary Leaf Date: Fri, 24 Feb 2023 08:35:08 +0000 Subject: [PATCH] arm64: extend ESR/SPSR registers to 64b For the Exception Syndrome Register, ESR_ELx, the upper 32b were previously unused, but now may contain additional exception info as of Armv8.7 (FEAT_LS64). Extend ESR from u32->u64 in exception handling code to support this. In addition, also extend Saved Program Status Register SPSR_ELx in the same way to allow for future extensions. Reviewed by: andrew Sponsored by: Arm Ltd Differential Revision: https://reviews.freebsd.org/D38983 --- sys/arm64/arm64/db_trace.c | 6 +++--- sys/arm64/arm64/exception.S | 2 +- sys/arm64/arm64/exec_machdep.c | 2 +- sys/arm64/arm64/trap.c | 18 +++++++++--------- sys/arm64/include/frame.h | 5 +++-- sys/arm64/include/reg.h | 2 +- sys/arm64/include/ucontext.h | 3 +-- 7 files changed, 19 insertions(+), 19 deletions(-) diff --git a/sys/arm64/arm64/db_trace.c b/sys/arm64/arm64/db_trace.c index 2b47ae2a89c7..6abdd6c5ca7a 100644 --- a/sys/arm64/arm64/db_trace.c +++ b/sys/arm64/arm64/db_trace.c @@ -102,18 +102,18 @@ db_stack_trace_cmd(struct thread *td, struct unwind_state *frame) switch (frame_type) { case FRAME_SYNC: - db_printf("--- exception, esr %#x\n", + db_printf("--- exception, esr %#lx\n", tf->tf_esr); break; case FRAME_IRQ: db_printf("--- interrupt\n"); break; case FRAME_SERROR: - db_printf("--- system error, esr %#x\n", + db_printf("--- system error, esr %#lx\n", tf->tf_esr); break; case FRAME_UNHANDLED: - db_printf("--- unhandled exception, esr %#x\n", + db_printf("--- unhandled exception, esr %#lx\n", tf->tf_esr); break; default: diff --git a/sys/arm64/arm64/exception.S b/sys/arm64/arm64/exception.S index fd55e1f39b58..e23a7868b56f 100644 --- a/sys/arm64/arm64/exception.S +++ b/sys/arm64/arm64/exception.S @@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$"); mrs x12, esr_el1 stp x18, lr, [sp, #(TF_SP - TF_X)]! str x10, [sp, #(TF_ELR)] - stp w11, w12, [sp, #(TF_SPSR)] + stp x11, x12, [sp, #(TF_SPSR)] mrs x18, tpidr_el1 .endm diff --git a/sys/arm64/arm64/exec_machdep.c b/sys/arm64/arm64/exec_machdep.c index 27ee2f80858d..7ead30a05663 100644 --- a/sys/arm64/arm64/exec_machdep.c +++ b/sys/arm64/arm64/exec_machdep.c @@ -457,7 +457,7 @@ int set_mcontext(struct thread *td, mcontext_t *mcp) { struct trapframe *tf = td->td_frame; - uint32_t spsr; + uint64_t spsr; spsr = mcp->mc_gpregs.gp_spsr; if ((spsr & PSR_M_MASK) != PSR_M_EL0t || diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index 1b33d7aa60c4..50f6e9de874b 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -212,7 +212,7 @@ align_abort(struct thread *td, struct trapframe *frame, uint64_t esr, if (!lower) { print_registers(frame); print_gp_register("far", far); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); panic("Misaligned access from kernel space!"); } @@ -329,7 +329,7 @@ data_abort(struct thread *td, struct trapframe *frame, uint64_t esr, WARN_GIANTOK, NULL, "Kernel page fault") != 0) { print_registers(frame); print_gp_register("far", far); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); panic("data abort in critical section or under mutex"); } @@ -370,7 +370,7 @@ data_abort(struct thread *td, struct trapframe *frame, uint64_t esr, printf("Fatal data abort:\n"); print_registers(frame); print_gp_register("far", far); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); #ifdef KDB if (debugger_on_trap) { @@ -429,7 +429,7 @@ print_registers(struct trapframe *frame) printf(" sp: %16lx\n", frame->tf_sp); print_gp_register(" lr", frame->tf_lr); print_gp_register("elr", frame->tf_elr); - printf("spsr: %8x\n", frame->tf_spsr); + printf("spsr: %16lx\n", frame->tf_spsr); } #ifdef VFP @@ -496,7 +496,7 @@ do_el1h_sync(struct thread *td, struct trapframe *frame) #endif { print_registers(frame); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); panic("VFP exception in the kernel"); } break; @@ -510,7 +510,7 @@ do_el1h_sync(struct thread *td, struct trapframe *frame) } else { print_registers(frame); print_gp_register("far", far); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); panic("Unhandled EL1 %s abort: %x", exception == EXCP_INSN_ABORT ? "instruction" : "data", dfsc); @@ -624,7 +624,7 @@ do_el0_sync(struct thread *td, struct trapframe *frame, uint64_t far) else { print_registers(frame); print_gp_register("far", far); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); panic("Unhandled EL0 %s abort: %x", exception == EXCP_INSN_ABORT_L ? "instruction" : "data", dfsc); @@ -716,7 +716,7 @@ do_serror(struct trapframe *frame) print_registers(frame); print_gp_register("far", far); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); panic("Unhandled System Error"); } @@ -730,6 +730,6 @@ unhandled_exception(struct trapframe *frame) print_registers(frame); print_gp_register("far", far); - printf(" esr: %.8lx\n", esr); + printf(" esr: %.16lx\n", esr); panic("Unhandled exception"); } diff --git a/sys/arm64/include/frame.h b/sys/arm64/include/frame.h index 0a8b53ebb01e..91ed6dbce920 100644 --- a/sys/arm64/include/frame.h +++ b/sys/arm64/include/frame.h @@ -45,8 +45,9 @@ struct trapframe { uint64_t tf_sp; uint64_t tf_lr; uint64_t tf_elr; - uint32_t tf_spsr; - uint32_t tf_esr; + uint64_t tf_spsr; + uint64_t tf_esr; + uint64_t pad; /* struct must be 16B aligned */ uint64_t tf_x[30]; }; diff --git a/sys/arm64/include/reg.h b/sys/arm64/include/reg.h index 44b2e2b21b72..4e8ca4f4e834 100644 --- a/sys/arm64/include/reg.h +++ b/sys/arm64/include/reg.h @@ -40,7 +40,7 @@ struct reg { __uint64_t lr; __uint64_t sp; __uint64_t elr; - __uint32_t spsr; + __uint64_t spsr; }; struct reg32 { diff --git a/sys/arm64/include/ucontext.h b/sys/arm64/include/ucontext.h index a81fdf9ad724..edb4cf8e63e3 100644 --- a/sys/arm64/include/ucontext.h +++ b/sys/arm64/include/ucontext.h @@ -38,8 +38,7 @@ struct gpregs { __register_t gp_lr; __register_t gp_sp; __register_t gp_elr; - __uint32_t gp_spsr; - int gp_pad; + __uint64_t gp_spsr; }; struct fpregs {