]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: arm64: Don't retire MMIO instruction w/ pending (emulated) SError
authorOliver Upton <oliver.upton@linux.dev>
Tue, 8 Jul 2025 17:25:28 +0000 (10:25 -0700)
committerOliver Upton <oliver.upton@linux.dev>
Tue, 8 Jul 2025 18:36:36 +0000 (11:36 -0700)
KVM might have an emulated SError queued for the guest if userspace
returned an abort for MMIO. Better yet, it could actually be a
*synchronous* exception in disguise if SCTLR2_ELx.EASE is set.

Don't advance PC if KVM owes an emulated SError, just like the handling
of emulated SEA injection.

Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250708172532.1699409-24-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/mmio.c

index 573a6ade2f4e9bca0dcf915fa5608dee2b81f6d3..54f9358c9e0e8f681469f903d7a1b0ae0af53897 100644 (file)
@@ -72,7 +72,7 @@ unsigned long kvm_mmio_read_buf(const void *buf, unsigned int len)
        return data;
 }
 
-static bool kvm_pending_sync_exception(struct kvm_vcpu *vcpu)
+static bool kvm_pending_external_abort(struct kvm_vcpu *vcpu)
 {
        if (!vcpu_get_flag(vcpu, PENDING_EXCEPTION))
                return false;
@@ -90,6 +90,8 @@ static bool kvm_pending_sync_exception(struct kvm_vcpu *vcpu)
                switch (vcpu_get_flag(vcpu, EXCEPT_MASK)) {
                case unpack_vcpu_flag(EXCEPT_AA64_EL1_SYNC):
                case unpack_vcpu_flag(EXCEPT_AA64_EL2_SYNC):
+               case unpack_vcpu_flag(EXCEPT_AA64_EL1_SERR):
+               case unpack_vcpu_flag(EXCEPT_AA64_EL2_SERR):
                        return true;
                default:
                        return false;
@@ -113,7 +115,7 @@ int kvm_handle_mmio_return(struct kvm_vcpu *vcpu)
         * Detect if the MMIO return was already handled or if userspace aborted
         * the MMIO access.
         */
-       if (unlikely(!vcpu->mmio_needed || kvm_pending_sync_exception(vcpu)))
+       if (unlikely(!vcpu->mmio_needed || kvm_pending_external_abort(vcpu)))
                return 1;
 
        vcpu->mmio_needed = 0;