@@ -113,6 +113,7 @@ void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
void __sve_save_state(void *sve_pffr, u32 *fpsr, int save_ffr);
void __sve_restore_state(void *sve_pffr, u32 *fpsr, int restore_ffr);
+int __sve_get_vl(void);
u64 __guest_enter(struct kvm_vcpu *vcpu);
@@ -31,3 +31,8 @@ SYM_FUNC_START(__sve_save_state)
sve_save 0, x1, x2, 3
ret
SYM_FUNC_END(__sve_save_state)
+
+SYM_FUNC_START(__sve_get_vl)
+ _sve_rdvl 0, 1
+ ret
+SYM_FUNC_END(__sve_get_vl)
@@ -339,7 +339,7 @@ static inline void __hyp_sve_save_host(void)
sve_state->zcr_el1 = read_sysreg_el1(SYS_ZCR);
write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2);
- __sve_save_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_sve_max_vl),
+ __sve_save_state(sve_state->sve_regs + sve_ffr_offset(__sve_get_vl()),
&sve_state->fpsr,
true);
}
@@ -49,7 +49,7 @@ static void __hyp_sve_restore_host(void)
* supported by the system (or limited at EL3).
*/
write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL2);
- __sve_restore_state(sve_state->sve_regs + sve_ffr_offset(kvm_host_sve_max_vl),
+ __sve_restore_state(sve_state->sve_regs + sve_ffr_offset(__sve_get_vl()),
&sve_state->fpsr,
true);
write_sysreg_el1(sve_state->zcr_el1, SYS_ZCR);
When saving and restoring the SVE state for the host we configure the hardware for the maximum VL it supports, but when calculating offsets in memory we use the maximum usable VL for the host. Since these two values may not be the same this may result in data corruption in the case where the PE supports a VL larger than the maximum usable VL for the host. We can just read the current VL from the hardware with an instruction so use that instead of a saved value, we need to correct the value used to lay out the stored data and this makes it clear that the layout is consistent with the hardware configuration. Fixes: b5b9955617bc ("KVM: arm64: Eagerly restore host fpsimd/sve state in pKVM") Signed-off-by: Mark Brown <broonie@kernel.org> --- arch/arm64/include/asm/kvm_hyp.h | 1 + arch/arm64/kvm/hyp/fpsimd.S | 5 +++++ arch/arm64/kvm/hyp/include/hyp/switch.h | 2 +- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-)