From aea90dc7dac7be871a3375d34bea8df92beeb744 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Sat, 30 Sep 2023 15:29:02 +0200 Subject: [PATCH] hw: fix vmm_arm test on arm_v8a Fixes #4975 regression --- .../arm_64/cpu/vcpu_state_virtualization.h | 7 +- .../src/core/spec/arm_v8/exception_vector.s | 15 +- .../src/core/spec/arm_v8/kernel/thread.cc | 10 +- .../arm_v8/virtualization/exception_vector.s | 184 +++++++++--------- .../base/include/spec/arm_64/cpu/cpu_state.h | 21 +- repos/os/src/monitor/spec/arm_64/gdb_arch.cc | 6 +- 6 files changed, 124 insertions(+), 119 deletions(-) diff --git a/repos/base-hw/include/spec/arm_64/cpu/vcpu_state_virtualization.h b/repos/base-hw/include/spec/arm_64/cpu/vcpu_state_virtualization.h index 37322faa44..b23baa94fa 100644 --- a/repos/base-hw/include/spec/arm_64/cpu/vcpu_state_virtualization.h +++ b/repos/base-hw/include/spec/arm_64/cpu/vcpu_state_virtualization.h @@ -38,15 +38,14 @@ struct Genode::Vcpu_state : Genode::Cpu_state Genode::uint64_t exception_type { 0 }; Genode::uint64_t esr_el2 { 0 }; - /** Fpu registers **/ - Genode::uint128_t q[32] { 0 }; + /** Fpu registers - q must start at 16-byte aligned offset **/ Genode::uint32_t fpcr { 0 }; Genode::uint32_t fpsr { 0 }; + Genode::uint128_t q[32] { 0 }; Genode::uint64_t elr_el1 { 0 }; Genode::uint64_t sp_el1 { 0 }; - Genode::uint32_t spsr_el1 { 0 }; - Genode::uint32_t esr_el1 { 0 }; + Genode::uint64_t spsr_el1 { 0 }; Genode::uint64_t sctlr_el1 { 0 }; Genode::uint64_t actlr_el1 { 0 }; diff --git a/repos/base-hw/src/core/spec/arm_v8/exception_vector.s b/repos/base-hw/src/core/spec/arm_v8/exception_vector.s index 5940201840..510e4252da 100644 --- a/repos/base-hw/src/core/spec/arm_v8/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm_v8/exception_vector.s @@ -34,13 +34,14 @@ stp x29, x30, [x0], #16 mrs x1, sp_el0 mrs x2, elr_el1 - mrs x3, spsr_el1 - mrs x4, mdscr_el1 - adr x5, . - and x5, x5, #0xf80 + mrs x3, esr_el1 + mrs x4, spsr_el1 + mrs x5, mdscr_el1 + adr x6, . + and x6, x6, #0xf80 stp x1, x2, [x0], #16 - stp xzr, x3, [x0], #16 /* ec will be updated later if needed */ - stp x4, x5, [x0], #16 + stp x3, x4, [x0], #16 + stp x5, x6, [x0], #16 b _kernel_entry .balign 128 .endr @@ -93,7 +94,7 @@ _kernel_entry: mov sp, x1 /* reset stack */ str x0, [sp, #-16] /* store cpu state pointer */ add x1, x0, #8*31 - ldp x2, x3, [x1], #16+8 /* load sp, ip, skip ec */ + ldp x2, x3, [x1], #16+8 /* load sp, ip, skip esr_el1 */ ldp x4, x5, [x1], #16+8 /* load pstate, mdscr_el1, skip exception_type */ msr sp_el0, x2 msr elr_el1, x3 diff --git a/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc b/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc index 4a5b6d43c8..f4445005e9 100644 --- a/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/arm_v8/kernel/thread.cc @@ -40,14 +40,13 @@ void Thread::exception(Cpu & cpu) case Cpu::SYNC_LEVEL_EL0: [[fallthrough]]; case Cpu::SYNC_LEVEL_EL1: { - Cpu::Esr::access_t esr = Cpu::Esr_el1::read(); - switch (Cpu::Esr::Ec::get(esr)) { + switch (Cpu::Esr::Ec::get(regs->esr_el1)) { case Cpu::Esr::Ec::SVC: _call(); return; case Cpu::Esr::Ec::INST_ABORT_SAME_LEVEL: [[fallthrough]]; case Cpu::Esr::Ec::DATA_ABORT_SAME_LEVEL: - Genode::raw("Fault in kernel/core ESR=", Genode::Hex(esr)); + Genode::raw("Fault in kernel/core ESR=", Genode::Hex(regs->esr_el1)); [[fallthrough]]; case Cpu::Esr::Ec::INST_ABORT_LOW_LEVEL: [[fallthrough]]; case Cpu::Esr::Ec::DATA_ABORT_LOW_LEVEL: @@ -55,12 +54,11 @@ void Thread::exception(Cpu & cpu) return; case Cpu::Esr::Ec::SOFTWARE_STEP_LOW_LEVEL: [[fallthrough]]; case Cpu::Esr::Ec::BRK: - regs->ec = Cpu::Esr::Ec::get(esr); _exception(); return; default: - Genode::raw("Unknown cpu exception EC=", Cpu::Esr::Ec::get(esr), - " ISS=", Cpu::Esr::Iss::get(esr), + Genode::raw("Unknown cpu exception EC=", Cpu::Esr::Ec::get(regs->esr_el1), + " ISS=", Cpu::Esr::Iss::get(regs->esr_el1), " ip=", (void*)regs->ip); }; diff --git a/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s b/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s index 1ea7342792..7d74b1dfae 100644 --- a/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s +++ b/repos/base-hw/src/core/spec/arm_v8/virtualization/exception_vector.s @@ -53,15 +53,19 @@ _to_vm: add x0, x0, #31*8 /* skip x0...x30, loaded later */ - ldr x1, [x0], #1*8 /* sp */ - ldp x2, x3, [x0], #2*8 /* ip, pstate */ + ldp x1, x2, [x0], #2*8 /* sp, ip */ + ldp x3, x4, [x0], #2*8 /* esr_el1, pstate */ msr sp_el0, x1 msr elr_el2, x2 - msr spsr_el2, x3 + msr esr_el1, x3 + msr spsr_el2, x4 add x0, x0, #2*8 /* skip exception_type and esr_el2 */ /** FPU register **/ + ldp w1, w2, [x0], #2*4 + msr fpcr, x1 + msr fpsr, x2 ldp q0, q1, [x0], #2*16 ldp q2, q3, [x0], #2*16 ldp q4, q5, [x0], #2*16 @@ -78,45 +82,40 @@ _to_vm: ldp q26, q27, [x0], #2*16 ldp q28, q29, [x0], #2*16 ldp q30, q31, [x0], #2*16 - ldp w1, w2, [x0], #2*4 - msr fpcr, x1 - msr fpsr, x2 /** system register **/ ldp x1, x2, [x0], #2*8 /* elr_el1, sp_el1 */ - ldp w3, w4, [x0], #2*4 /* spsr_el1, esr_el1 */ - ldp x5, x6, [x0], #2*8 /* sctlr_el1, actlr_el1 */ - ldr x7, [x0], #8 /* vbar_el1 */ - ldp w8, w9, [x0], #2*4 /* cpacr_el1, afsr0_el1 */ - ldp w10, w11, [x0], #2*4 /* afsr1_el1, contextidr_el1 */ - ldp x12, x13, [x0], #2*8 /* ttbr0_el1, ttbr1_el1 */ - ldp x14, x15, [x0], #2*8 /* tcr_el1, mair_el1 */ - ldp x16, x17, [x0], #2*8 /* amair_el1, far_el1 */ - ldp x18, x19, [x0], #2*8 /* par_el1, tpidrro_el0 */ - ldp x20, x21, [x0], #2*8 /* tpidr_el0, tpidr_el1 */ - ldr x22, [x0], #3*8 /* vmpidr_el2 */ + ldp x3, x4, [x0], #2*8 /* spsr_el1, sctlr_el1 */ + ldp x5, x6, [x0], #2*8 /* actlr_el1, vbar_el1 */ + ldp w7, w8, [x0], #2*4 /* cpacr_el1, afsr0_el1 */ + ldp w9, w10, [x0], #2*4 /* afsr1_el1, contextidr_el1 */ + ldp x11, x12, [x0], #2*8 /* ttbr0_el1, ttbr1_el1 */ + ldp x13, x14, [x0], #2*8 /* tcr_el1, mair_el1 */ + ldp x15, x16, [x0], #2*8 /* amair_el1, far_el1 */ + ldp x17, x18, [x0], #2*8 /* par_el1, tpidrro_el0 */ + ldp x19, x20, [x0], #2*8 /* tpidr_el0, tpidr_el1 */ + ldr x21, [x0], #3*8 /* vmpidr_el2 */ msr elr_el1, x1 msr sp_el1, x2 msr spsr_el1, x3 - msr esr_el1, x4 - msr sctlr_el1, x5 - msr actlr_el1, x6 - msr vbar_el1, x7 - msr cpacr_el1, x8 - msr afsr0_el1, x9 - msr afsr1_el1, x10 - msr contextidr_el1, x11 - msr ttbr0_el1, x12 - msr ttbr1_el1, x13 - msr tcr_el1, x14 - msr mair_el1, x15 - msr amair_el1, x16 - msr far_el1, x17 - msr par_el1, x18 - msr tpidrro_el0, x19 - msr tpidr_el0, x20 - msr tpidr_el1, x21 - msr vmpidr_el2, x22 + msr sctlr_el1, x4 + msr actlr_el1, x5 + msr vbar_el1, x6 + msr cpacr_el1, x7 + msr afsr0_el1, x8 + msr afsr1_el1, x9 + msr contextidr_el1, x10 + msr ttbr0_el1, x11 + msr ttbr1_el1, x12 + msr tcr_el1, x13 + msr mair_el1, x14 + msr amair_el1, x15 + msr far_el1, x16 + msr par_el1, x17 + msr tpidrro_el0, x18 + msr tpidr_el0, x19 + msr tpidr_el1, x20 + msr vmpidr_el2, x21 /********************** @@ -224,16 +223,20 @@ _from_vm: stp x28, x29, [x0], #2*8 str x30, [x0], #1*8 - /** save sp, ip, pstate and exception reason **/ + /** save sp, ip, esr_el1, pstate and exception reason **/ mrs x2, sp_el0 mrs x3, elr_el2 - mrs x4, spsr_el2 - mrs x5, esr_el2 - stp x2, x3, [x0], #2*8 - stp x4, x1, [x0], #2*8 - str x5, [x0], #1*8 + mrs x4, esr_el1 + mrs x5, spsr_el2 + mrs x6, esr_el2 + stp x2, x3, [x0], #2*8 /* sp, ip */ + stp x4, x5, [x0], #2*8 /* esr_el1, pstate */ + stp x1, x6, [x0], #2*8 /* exception_type, esr_el2 */ /** fpu registers **/ + mrs x1, fpcr + mrs x2, fpsr + stp w1, w2, [x0], #2*4 stp q0, q1, [x0], #32 stp q2, q3, [x0], #32 stp q4, q5, [x0], #32 @@ -251,56 +254,51 @@ _from_vm: stp q28, q29, [x0], #32 stp q30, q31, [x0], #32 - mrs x1, fpcr - mrs x2, fpsr mrs x3, elr_el1 mrs x4, sp_el1 mrs x5, spsr_el1 - mrs x6, esr_el1 - mrs x7, sctlr_el1 - mrs x8, actlr_el1 - mrs x9, vbar_el1 - mrs x10, cpacr_el1 - mrs x11, afsr0_el1 - mrs x12, afsr1_el1 - mrs x13, contextidr_el1 - mrs x14, ttbr0_el1 - mrs x15, ttbr1_el1 - mrs x16, tcr_el1 - mrs x17, mair_el1 - mrs x18, amair_el1 - mrs x19, far_el1 - mrs x20, par_el1 - mrs x21, tpidrro_el0 - mrs x22, tpidr_el0 - mrs x23, tpidr_el1 - mrs x24, far_el2 - mrs x25, hpfar_el2 - stp w1, w2, [x0], #2*4 + mrs x6, sctlr_el1 + mrs x7, actlr_el1 + mrs x8, vbar_el1 + mrs x9, cpacr_el1 + mrs x10, afsr0_el1 + mrs x11, afsr1_el1 + mrs x12, contextidr_el1 + mrs x13, ttbr0_el1 + mrs x14, ttbr1_el1 + mrs x15, tcr_el1 + mrs x16, mair_el1 + mrs x17, amair_el1 + mrs x18, far_el1 + mrs x19, par_el1 + mrs x20, tpidrro_el0 + mrs x21, tpidr_el0 + mrs x22, tpidr_el1 + mrs x23, far_el2 + mrs x24, hpfar_el2 stp x3, x4, [x0], #2*8 - stp w5, w6, [x0], #2*4 + stp x5, x6, [x0], #2*8 stp x7, x8, [x0], #2*8 - str x9, [x0], #1*8 - stp w10, w11, [x0], #2*4 - stp w12, w13, [x0], #2*4 - stp x14, x15, [x0], #2*8 - stp x16, x17, [x0], #2*8 - stp x18, x19, [x0], #2*8 - stp x20, x21, [x0], #2*8 - stp x22, x23, [x0], #3*8 - stp x24, x25, [x0], #2*8 + stp w9, w10, [x0], #2*4 + stp w11, w12, [x0], #2*4 + stp x13, x14, [x0], #2*8 + stp x15, x16, [x0], #2*8 + stp x17, x18, [x0], #2*8 + stp x19, x20, [x0], #2*8 + stp x21, x22, [x0], #3*8 + stp x23, x24, [x0], #2*8 /********************** ** save timer state ** **********************/ - mrs x26, cntvoff_el2 - mrs x27, cntv_cval_el0 - mrs x28, cntv_ctl_el0 - mrs x29, cntkctl_el1 - stp x26, x27, [x0], #2*8 - stp w28, w29, [x0] + mrs x25, cntvoff_el2 + mrs x26, cntv_cval_el0 + mrs x27, cntv_ctl_el0 + mrs x28, cntkctl_el1 + stp x25, x26, [x0], #2*8 + stp w27, w28, [x0] mov x0, #0b111 msr cnthctl_el2, x0 @@ -332,17 +330,19 @@ _from_vm: ** Load host context ** ***********************/ - add x30, x30, #32*8 /* skip general-purpose regs, sp */ - ldp x0, x1, [x30] /* host state ip, and pstate */ - add x30, x30, #34*16 /* skip fpu regs etc. */ - ldp w2, w3, [x30], #4*4 /* fpcr and fpsr */ - ldr x4, [x30], #2*8 /* sp_el1 */ - ldp x5, x6, [x30], #2*8 /* sctlr_el1, actlr_el1 */ - ldr x7, [x30], #1*8 /* vbar_el1 */ - ldr w8, [x30], #4*4 /* cpacr_el1 */ - ldp x9, x10, [x30], #2*8 /* ttbr0_el1, ttbr1_el1 */ - ldp x11, x12, [x30], #2*8 /* tcr_el1, mair_el1 */ - ldr x13, [x30] /* amair_el1 */ + add x30, x30, #32*8 /* skip general-purpose regs, sp */ + ldr x0, [x30], #2*8 /* host state ip, skip esr_el1 */ + ldr x1, [x30], #3*8 /* host state pstate, + skip exception_type and esr_el2 */ + ldp w2, w3, [x30], #2*4 /* fpcr and fpsr */ + add x30, x30, #32*16+8 /* skip remaining fpu regs and elr_el1 */ + ldr x4, [x30], #2*8 /* sp_el1 */ + ldp x5, x6, [x30], #2*8 /* sctlr_el1, actlr_el1 */ + ldr x7, [x30], #1*8 /* vbar_el1 */ + ldr w8, [x30], #4*4 /* cpacr_el1 */ + ldp x9, x10, [x30], #2*8 /* ttbr0_el1, ttbr1_el1 */ + ldp x11, x12, [x30], #2*8 /* tcr_el1, mair_el1 */ + ldr x13, [x30] /* amair_el1 */ msr elr_el2, x0 msr spsr_el2, x1 diff --git a/repos/base/include/spec/arm_64/cpu/cpu_state.h b/repos/base/include/spec/arm_64/cpu/cpu_state.h index 5942ba8b12..8318ce1b0e 100644 --- a/repos/base/include/spec/arm_64/cpu/cpu_state.h +++ b/repos/base/include/spec/arm_64/cpu/cpu_state.h @@ -16,21 +16,28 @@ /* Genode includes */ #include +#include namespace Genode { struct Cpu_state; } struct Genode::Cpu_state { - enum Cpu_exception { - SOFTWARE_STEP = 0x32, - BREAKPOINT = 0x3c, + struct Esr : Genode::Register<64> + { + struct Ec : Bitfield<26, 6> + { + enum Exception { + SOFTWARE_STEP = 0b110010, + BREAKPOINT = 0b111100, + }; + }; }; - addr_t r[31] { 0 }; /* general purpose register 0...30 */ - addr_t sp { 0 }; /* stack pointer */ - addr_t ip { 0 }; /* instruction pointer */ - addr_t ec { 0 }; /* exception class */ + addr_t r[31] { 0 }; /* general purpose register 0...30 */ + addr_t sp { 0 }; /* stack pointer */ + addr_t ip { 0 }; /* instruction pointer */ + addr_t esr_el1 { 0 }; /* exception syndrome */ }; #endif /* _INCLUDE__SPEC__ARM_64__CPU__CPU_STATE_H_ */ diff --git a/repos/os/src/monitor/spec/arm_64/gdb_arch.cc b/repos/os/src/monitor/spec/arm_64/gdb_arch.cc index 5f381305ac..b9e294e0f2 100644 --- a/repos/os/src/monitor/spec/arm_64/gdb_arch.cc +++ b/repos/os/src/monitor/spec/arm_64/gdb_arch.cc @@ -72,11 +72,11 @@ void Monitor::Monitored_thread::_handle_exception() _original_first_instruction); stop_reply_signal = Stop_reply_signal::STOP; } else { - switch(thread_state.ec) { - case Cpu_state::Cpu_exception::SOFTWARE_STEP: + switch(Cpu_state::Esr::Ec::get(thread_state.esr_el1)) { + case Cpu_state::Esr::Ec::SOFTWARE_STEP: stop_reply_signal = Stop_reply_signal::TRAP; break; - case Cpu_state::Cpu_exception::BREAKPOINT: + case Cpu_state::Esr::Ec::BREAKPOINT: stop_reply_signal = Stop_reply_signal::TRAP; break; default: