diff options
Diffstat (limited to 'target/arm/kvm.c')
-rw-r--r-- | target/arm/kvm.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 3a46f54..8bb7318 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -749,6 +749,29 @@ int kvm_get_vcpu_events(ARMCPU *cpu) void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run) { + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + if (unlikely(env->ext_dabt_raised)) { + /* + * Verifying that the ext DABT has been properly injected, + * otherwise risking indefinitely re-running the faulting instruction + * Covering a very narrow case for kernels 5.5..5.5.4 + * when injected abort was misconfigured to be + * an IMPLEMENTATION DEFINED exception (for 32-bit EL1) + */ + if (!arm_feature(env, ARM_FEATURE_AARCH64) && + unlikely(!kvm_arm_verify_ext_dabt_pending(cs))) { + + error_report("Data abort exception with no valid ISS generated by " + "guest memory access. KVM unable to emulate faulting " + "instruction. Failed to inject an external data abort " + "into the guest."); + abort(); + } + /* Clear the status */ + env->ext_dabt_raised = 0; + } } MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run) @@ -833,6 +856,8 @@ void kvm_arm_vm_state_change(void *opaque, int running, RunState state) static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss, uint64_t fault_ipa) { + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; /* * Request KVM to inject the external data abort into the guest */ @@ -847,7 +872,10 @@ static int kvm_arm_handle_dabt_nisv(CPUState *cs, uint64_t esr_iss, */ events.exception.ext_dabt_pending = 1; /* KVM_CAP_ARM_INJECT_EXT_DABT implies KVM_CAP_VCPU_EVENTS */ - return kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events); + if (!kvm_vcpu_ioctl(cs, KVM_SET_VCPU_EVENTS, &events)) { + env->ext_dabt_raised = 1; + return 0; + } } else { error_report("Data abort exception triggered by guest memory access " "at physical address: 0x" TARGET_FMT_lx, |