diff options
author | Claudio Fontana | 2021-02-04 17:39:16 +0100 |
---|---|---|
committer | Richard Henderson | 2021-02-05 21:24:14 +0100 |
commit | 853bfef4e6d60244fd131ec55bbf1e7caa52599b (patch) | |
tree | 485978d56eb4630722bb9d5bd75042e3a6628218 /target/arm | |
parent | cpu: Move debug_excp_handler to tcg_ops (diff) | |
download | qemu-853bfef4e6d60244fd131ec55bbf1e7caa52599b.tar.gz qemu-853bfef4e6d60244fd131ec55bbf1e7caa52599b.tar.xz qemu-853bfef4e6d60244fd131ec55bbf1e7caa52599b.zip |
target/arm: do not use cc->do_interrupt for KVM directly
cc->do_interrupt is in theory a TCG callback used in accel/tcg only,
to prepare the emulated architecture to take an interrupt as defined
in the hardware specifications,
but in reality the _do_interrupt style of functions in targets are
also occasionally reused by KVM to prepare the architecture state in a
similar way where userspace code has identified that it needs to
deliver an exception to the guest.
In the case of ARM, that includes:
1) the vcpu thread got a SIGBUS indicating a memory error,
and we need to deliver a Synchronous External Abort to the guest to
let it know about the error.
2) the kernel told us about a debug exception (breakpoint, watchpoint)
but it is not for one of QEMU's own gdbstub breakpoints/watchpoints
so it must be a breakpoint the guest itself has set up, therefore
we need to deliver it to the guest.
So in order to reuse code, the same arm_do_interrupt function is used.
This is all fine, but we need to avoid calling it using the callback
registered in CPUClass, since that one is now TCG-only.
Fortunately this is easily solved by replacing calls to
CPUClass::do_interrupt() with explicit calls to arm_do_interrupt().
Signed-off-by: Claudio Fontana <cfontana@suse.de>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Cc: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20210204163931.7358-9-cfontana@suse.de>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/arm')
-rw-r--r-- | target/arm/helper.c | 4 | ||||
-rw-r--r-- | target/arm/kvm64.c | 6 |
2 files changed, 6 insertions, 4 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index 47e266d7e6..1a64bd748c 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -9969,6 +9969,10 @@ static void handle_semihosting(CPUState *cs) * Do any appropriate logging, handle PSCI calls, and then hand off * to the AArch64-entry or AArch32-entry function depending on the * target exception level's register width. + * + * Note: this is used for both TCG (as the do_interrupt tcg op), + * and KVM to re-inject guest debug exceptions, and to + * inject a Synchronous-External-Abort. */ void arm_cpu_do_interrupt(CPUState *cs) { diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 3c37fc4fb6..dff85f6db9 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -946,7 +946,6 @@ static void kvm_inject_arm_sea(CPUState *c) { ARMCPU *cpu = ARM_CPU(c); CPUARMState *env = &cpu->env; - CPUClass *cc = CPU_GET_CLASS(c); uint32_t esr; bool same_el; @@ -962,7 +961,7 @@ static void kvm_inject_arm_sea(CPUState *c) env->exception.syndrome = esr; - cc->do_interrupt(c); + arm_cpu_do_interrupt(c); } #define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ @@ -1493,7 +1492,6 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit) { int hsr_ec = syn_get_ec(debug_exit->hsr); ARMCPU *cpu = ARM_CPU(cs); - CPUClass *cc = CPU_GET_CLASS(cs); CPUARMState *env = &cpu->env; /* Ensure PC is synchronised */ @@ -1547,7 +1545,7 @@ bool kvm_arm_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit) env->exception.vaddress = debug_exit->far; env->exception.target_el = 1; qemu_mutex_lock_iothread(); - cc->do_interrupt(cs); + arm_cpu_do_interrupt(cs); qemu_mutex_unlock_iothread(); return false; |