--- /dev/null
+From 1c71dbc8a179d99dd9bb7e7fc1888db613cf85de Mon Sep 17 00:00:00 2001
+From: James Morse <james.morse@arm.com>
+Date: Thu, 27 Jan 2022 12:20:50 +0000
+Subject: KVM: arm64: Avoid consuming a stale esr value when SError occur
+
+From: James Morse <james.morse@arm.com>
+
+commit 1c71dbc8a179d99dd9bb7e7fc1888db613cf85de upstream.
+
+When any exception other than an IRQ occurs, the CPU updates the ESR_EL2
+register with the exception syndrome. An SError may also become pending,
+and will be synchronised by KVM. KVM notes the exception type, and whether
+an SError was synchronised in exit_code.
+
+When an exception other than an IRQ occurs, fixup_guest_exit() updates
+vcpu->arch.fault.esr_el2 from the hardware register. When an SError was
+synchronised, the vcpu esr value is used to determine if the exception
+was due to an HVC. If so, ELR_EL2 is moved back one instruction. This
+is so that KVM can process the SError first, and re-execute the HVC if
+the guest survives the SError.
+
+But if an IRQ synchronises an SError, the vcpu's esr value is stale.
+If the previous non-IRQ exception was an HVC, KVM will corrupt ELR_EL2,
+causing an unrelated guest instruction to be executed twice.
+
+Check ARM_EXCEPTION_CODE() before messing with ELR_EL2, IRQs don't
+update this register so don't need to check.
+
+Fixes: defe21f49bc9 ("KVM: arm64: Move PC rollback on SError to HYP")
+Cc: stable@vger.kernel.org
+Reported-by: Steven Price <steven.price@arm.com>
+Signed-off-by: James Morse <james.morse@arm.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20220127122052.1584324-3-james.morse@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/hyp/include/hyp/switch.h | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/arm64/kvm/hyp/include/hyp/switch.h
++++ b/arch/arm64/kvm/hyp/include/hyp/switch.h
+@@ -425,7 +425,8 @@ static inline bool fixup_guest_exit(stru
+ if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
+ vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
+
+- if (ARM_SERROR_PENDING(*exit_code)) {
++ if (ARM_SERROR_PENDING(*exit_code) &&
++ ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ) {
+ u8 esr_ec = kvm_vcpu_trap_get_class(vcpu);
+
+ /*
--- /dev/null
+From 1229630af88620f6e3a621a1ebd1ca14d9340df7 Mon Sep 17 00:00:00 2001
+From: James Morse <james.morse@arm.com>
+Date: Thu, 27 Jan 2022 12:20:51 +0000
+Subject: KVM: arm64: Stop handle_exit() from handling HVC twice when an SError occurs
+
+From: James Morse <james.morse@arm.com>
+
+commit 1229630af88620f6e3a621a1ebd1ca14d9340df7 upstream.
+
+Prior to commit defe21f49bc9 ("KVM: arm64: Move PC rollback on SError to
+HYP"), when an SError is synchronised due to another exception, KVM
+handles the SError first. If the guest survives, the instruction that
+triggered the original exception is re-exectued to handle the first
+exception. HVC is treated as a special case as the instruction wouldn't
+normally be re-exectued, as its not a trap.
+
+Commit defe21f49bc9 didn't preserve the behaviour of the 'return 1'
+that skips the rest of handle_exit().
+
+Since commit defe21f49bc9, KVM will try to handle the SError and the
+original exception at the same time. When the exception was an HVC,
+fixup_guest_exit() has already rolled back ELR_EL2, meaning if the
+guest has virtual SError masked, it will execute and handle the HVC
+twice.
+
+Restore the original behaviour.
+
+Fixes: defe21f49bc9 ("KVM: arm64: Move PC rollback on SError to HYP")
+Cc: stable@vger.kernel.org
+Signed-off-by: James Morse <james.morse@arm.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Link: https://lore.kernel.org/r/20220127122052.1584324-4-james.morse@arm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/arm64/kvm/handle_exit.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/arch/arm64/kvm/handle_exit.c
++++ b/arch/arm64/kvm/handle_exit.c
+@@ -226,6 +226,14 @@ int handle_exit(struct kvm_vcpu *vcpu, i
+ {
+ struct kvm_run *run = vcpu->run;
+
++ if (ARM_SERROR_PENDING(exception_index)) {
++ /*
++ * The SError is handled by handle_exit_early(). If the guest
++ * survives it will re-execute the original instruction.
++ */
++ return 1;
++ }
++
+ exception_index = ARM_EXCEPTION_CODE(exception_index);
+
+ switch (exception_index) {