Skip to content

Commit 1dd498e

Browse files
James MorseMarc Zyngier
authored andcommitted
KVM: arm64: Workaround Cortex-A510's single-step and PAC trap errata
Cortex-A510's erratum #2077057 causes SPSR_EL2 to be corrupted when single-stepping authenticated ERET instructions. A single step is expected, but a pointer authentication trap is taken instead. The erratum causes SPSR_EL1 to be copied to SPSR_EL2, which could allow EL1 to cause a return to EL2 with a guest controlled ELR_EL2. Because the conditions require an ERET into active-not-pending state, this is only a problem for the EL2 when EL2 is stepping EL1. In this case the previous SPSR_EL2 value is preserved in struct kvm_vcpu, and can be restored. Cc: stable@vger.kernel.org # 53960fa: arm64: Add Cortex-A510 CPU part definition Cc: stable@vger.kernel.org Signed-off-by: James Morse <james.morse@arm.com> [maz: fixup cpucaps ordering] Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20220127122052.1584324-5-james.morse@arm.com
1 parent 1229630 commit 1dd498e

File tree

5 files changed

+48
-3
lines changed

5 files changed

+48
-3
lines changed

Documentation/arm64/silicon-errata.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ stable kernels.
100100
+----------------+-----------------+-----------------+-----------------------------+
101101
| ARM | Cortex-A510 | #2051678 | ARM64_ERRATUM_2051678 |
102102
+----------------+-----------------+-----------------+-----------------------------+
103+
| ARM | Cortex-A510 | #2077057 | ARM64_ERRATUM_2077057 |
104+
+----------------+-----------------+-----------------+-----------------------------+
103105
| ARM | Cortex-A710 | #2119858 | ARM64_ERRATUM_2119858 |
104106
+----------------+-----------------+-----------------+-----------------------------+
105107
| ARM | Cortex-A710 | #2054223 | ARM64_ERRATUM_2054223 |

arch/arm64/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,22 @@ config ARM64_ERRATUM_2051678
680680

681681
If unsure, say Y.
682682

683+
config ARM64_ERRATUM_2077057
684+
bool "Cortex-A510: 2077057: workaround software-step corrupting SPSR_EL2"
685+
help
686+
This option adds the workaround for ARM Cortex-A510 erratum 2077057.
687+
Affected Cortex-A510 may corrupt SPSR_EL2 when the a step exception is
688+
expected, but a Pointer Authentication trap is taken instead. The
689+
erratum causes SPSR_EL1 to be copied to SPSR_EL2, which could allow
690+
EL1 to cause a return to EL2 with a guest controlled ELR_EL2.
691+
692+
This can only happen when EL2 is stepping EL1.
693+
694+
When these conditions occur, the SPSR_EL2 value is unchanged from the
695+
previous guest entry, and can be restored from the in-memory copy.
696+
697+
If unsure, say Y.
698+
683699
config ARM64_ERRATUM_2119858
684700
bool "Cortex-A710/X2: 2119858: workaround TRBE overwriting trace data in FILL mode"
685701
default y

arch/arm64/kernel/cpu_errata.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
600600
CAP_MIDR_RANGE_LIST(trbe_write_out_of_range_cpus),
601601
},
602602
#endif
603+
#ifdef CONFIG_ARM64_ERRATUM_2077057
604+
{
605+
.desc = "ARM erratum 2077057",
606+
.capability = ARM64_WORKAROUND_2077057,
607+
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
608+
ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A510, 0, 0, 2),
609+
},
610+
#endif
603611
#ifdef CONFIG_ARM64_ERRATUM_2064142
604612
{
605613
.desc = "ARM erratum 2064142",

arch/arm64/kvm/hyp/include/hyp/switch.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,24 @@ static inline bool kvm_hyp_handle_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
402402
return false;
403403
}
404404

405+
static inline void synchronize_vcpu_pstate(struct kvm_vcpu *vcpu, u64 *exit_code)
406+
{
407+
/*
408+
* Check for the conditions of Cortex-A510's #2077057. When these occur
409+
* SPSR_EL2 can't be trusted, but isn't needed either as it is
410+
* unchanged from the value in vcpu_gp_regs(vcpu)->pstate.
411+
* Are we single-stepping the guest, and took a PAC exception from the
412+
* active-not-pending state?
413+
*/
414+
if (cpus_have_final_cap(ARM64_WORKAROUND_2077057) &&
415+
vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP &&
416+
*vcpu_cpsr(vcpu) & DBG_SPSR_SS &&
417+
ESR_ELx_EC(read_sysreg_el2(SYS_ESR)) == ESR_ELx_EC_PAC)
418+
write_sysreg_el2(*vcpu_cpsr(vcpu), SYS_SPSR);
419+
420+
vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR);
421+
}
422+
405423
/*
406424
* Return true when we were able to fixup the guest exit and should return to
407425
* the guest, false when we should restore the host state and return to the
@@ -413,7 +431,7 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
413431
* Save PSTATE early so that we can evaluate the vcpu mode
414432
* early on.
415433
*/
416-
vcpu->arch.ctxt.regs.pstate = read_sysreg_el2(SYS_SPSR);
434+
synchronize_vcpu_pstate(vcpu, exit_code);
417435

418436
/*
419437
* Check whether we want to repaint the state one way or

arch/arm64/tools/cpucaps

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ WORKAROUND_1418040
5555
WORKAROUND_1463225
5656
WORKAROUND_1508412
5757
WORKAROUND_1542419
58-
WORKAROUND_2064142
59-
WORKAROUND_2038923
6058
WORKAROUND_1902691
59+
WORKAROUND_2038923
60+
WORKAROUND_2064142
61+
WORKAROUND_2077057
6162
WORKAROUND_TRBE_OVERWRITE_FILL_MODE
6263
WORKAROUND_TSB_FLUSH_FAILURE
6364
WORKAROUND_TRBE_WRITE_OUT_OF_RANGE

0 commit comments

Comments
 (0)