From c2f3786ab0d58b5eb08b3d3fe28f7eb85c40027f Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Mon, 16 Sep 2024 10:27:17 +0000 Subject: [PATCH] arm64: Save all integer registers in exception handlers. * This is needed in order to support syscalls and other exceptions that need to be able to inspect/modify userspace register contents. Change-Id: I8a638c0c40dd44ed882adad0591ae3bf5493a6b9 Reviewed-on: https://review.haiku-os.org/c/haiku/+/8329 Haiku-Format: Haiku-format Bot Reviewed-by: waddlesplash Tested-by: Commit checker robot --- headers/private/kernel/arch/arm64/arch_cpu.h | 4 ++-- src/system/kernel/arch/arm64/arch_asm.S | 16 ++++++++++------ src/system/kernel/arch/arm64/asm_offsets.cpp | 5 +++++ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/headers/private/kernel/arch/arm64/arch_cpu.h b/headers/private/kernel/arch/arm64/arch_cpu.h index 088a729854..cfbc3b5416 100644 --- a/headers/private/kernel/arch/arm64/arch_cpu.h +++ b/headers/private/kernel/arch/arm64/arch_cpu.h @@ -132,10 +132,10 @@ struct iframe { // return info uint64 elr; uint64 spsr; - uint64 x[20]; + uint64 x[29]; + uint64 fp; uint64 lr; uint64 sp; - uint64 fp; // exception info uint64 esr; diff --git a/src/system/kernel/arch/arm64/arch_asm.S b/src/system/kernel/arch/arm64/arch_asm.S index fe3b73955a..74ff183951 100644 --- a/src/system/kernel/arch/arm64/arch_asm.S +++ b/src/system/kernel/arch/arm64/arch_asm.S @@ -40,11 +40,11 @@ sub sp, sp, \xt stp x16, x17, [x19, #(IFRAME_x + 16 * 8)] mov x0, sp // original x19 that we swapped with sp stp x18, x0, [x19, #(IFRAME_x + 18 * 8)] - - // x20-x28 won't be clobbered - // thus we don't really need to store these - - str x29, [x19, #(IFRAME_fp)] + stp x20, x21, [x19, #(IFRAME_x + 20 * 8)] + stp x22, x23, [x19, #(IFRAME_x + 22 * 8)] + stp x24, x25, [x19, #(IFRAME_x + 24 * 8)] + stp x26, x27, [x19, #(IFRAME_x + 26 * 8)] + stp x28, fp, [x19, #(IFRAME_x + 28 * 8)] str x30, [x19, #(IFRAME_lr)] .if \el == 0 @@ -84,7 +84,11 @@ sub sp, sp, \xt ldp x14, x15, [x19, #(IFRAME_x + 14 * 8)] ldp x16, x17, [x19, #(IFRAME_x + 16 * 8)] // x18 and x19 will be restored later - ldr x29, [x19, #(IFRAME_fp)] + ldp x20, x21, [x19, #(IFRAME_x + 20 * 8)] + ldp x22, x23, [x19, #(IFRAME_x + 22 * 8)] + ldp x24, x25, [x19, #(IFRAME_x + 24 * 8)] + ldp x26, x27, [x19, #(IFRAME_x + 26 * 8)] + ldp x28, fp, [x19, #(IFRAME_x + 28 * 8)] ldr x30, [x19, #(IFRAME_lr)] // disable interrupts before restoring ELR/SPSR/sp diff --git a/src/system/kernel/arch/arm64/asm_offsets.cpp b/src/system/kernel/arch/arm64/asm_offsets.cpp index 9493980390..00247fb953 100644 --- a/src/system/kernel/arch/arm64/asm_offsets.cpp +++ b/src/system/kernel/arch/arm64/asm_offsets.cpp @@ -44,3 +44,8 @@ dummy() DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler); DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer); } + + +// fp must be located at x[29] so that we can load/store +// x[28] and fp with a single LDP/STP instruction. +STATIC_ASSERT(offsetof(iframe, fp) == offsetof(iframe, x) + 29 * 8);