Skip to content

Commit c6e35df

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: Check for SYSREGS_ON_CPU before accessing the CPU state
Mark Brown reports that since we commit to making exceptions visible without the vcpu being loaded, the external abort selftest fails. Upon investigation, it turns out that the code that makes registers affected by an exception visible to the guest is completely broken on VHE, as we don't check whether the system registers are loaded on the CPU at this point. We managed to get away with this so far, but that's obviously as bad as it gets, Add the required checksm and document the absolute need to check for the SYSREGS_ON_CPU flag before calling into any of the __vcpu_write_sys_reg_to_cpu()__vcpu_read_sys_reg_from_cpu() helpers. Reported-by: Mark Brown <broonie@kernel.org> Signed-off-by: Marc Zyngier <maz@kernel.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/18535df8-e647-4643-af9a-bb780af03a70@sirena.org.uk Link: https://lore.kernel.org/r/20250720102229.179114-1-maz@kernel.org Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent efa1368 commit c6e35df

File tree

2 files changed

+8
-2
lines changed

2 files changed

+8
-2
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,8 @@ static inline bool __vcpu_read_sys_reg_from_cpu(int reg, u64 *val)
11691169
* System registers listed in the switch are not saved on every
11701170
* exit from the guest but are only saved on vcpu_put.
11711171
*
1172+
* SYSREGS_ON_CPU *MUST* be checked before using this helper.
1173+
*
11721174
* Note that MPIDR_EL1 for the guest is set by KVM via VMPIDR_EL2 but
11731175
* should never be listed below, because the guest cannot modify its
11741176
* own MPIDR_EL1 and MPIDR_EL1 is accessed for VCPU A from VCPU B's
@@ -1221,6 +1223,8 @@ static inline bool __vcpu_write_sys_reg_to_cpu(u64 val, int reg)
12211223
* System registers listed in the switch are not restored on every
12221224
* entry to the guest but are only restored on vcpu_load.
12231225
*
1226+
* SYSREGS_ON_CPU *MUST* be checked before using this helper.
1227+
*
12241228
* Note that MPIDR_EL1 for the guest is set by KVM via VMPIDR_EL2 but
12251229
* should never be listed below, because the MPIDR should only be set
12261230
* once, before running the VCPU, and never changed later.

arch/arm64/kvm/hyp/exception.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ static inline u64 __vcpu_read_sys_reg(const struct kvm_vcpu *vcpu, int reg)
2626

2727
if (unlikely(vcpu_has_nv(vcpu)))
2828
return vcpu_read_sys_reg(vcpu, reg);
29-
else if (__vcpu_read_sys_reg_from_cpu(reg, &val))
29+
else if (vcpu_get_flag(vcpu, SYSREGS_ON_CPU) &&
30+
__vcpu_read_sys_reg_from_cpu(reg, &val))
3031
return val;
3132

3233
return __vcpu_sys_reg(vcpu, reg);
@@ -36,7 +37,8 @@ static inline void __vcpu_write_sys_reg(struct kvm_vcpu *vcpu, u64 val, int reg)
3637
{
3738
if (unlikely(vcpu_has_nv(vcpu)))
3839
vcpu_write_sys_reg(vcpu, val, reg);
39-
else if (!__vcpu_write_sys_reg_to_cpu(val, reg))
40+
else if (!vcpu_get_flag(vcpu, SYSREGS_ON_CPU) ||
41+
!__vcpu_write_sys_reg_to_cpu(val, reg))
4042
__vcpu_assign_sys_reg(vcpu, reg, val);
4143
}
4244

0 commit comments

Comments
 (0)