Skip to content

Commit 3643b33

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/nv-resx-fixes-6.14 into kvmarm-master/next
* kvm-arm64/nv-resx-fixes-6.14: : . : Fixes for NV sysreg accessors. From the cover letter: : : "Joey recently reported that some rather basic tests were failing on : NV, and managed to track it down to critical register fields (such as : HCR_EL2.E2H) not having their expect value. : : Further investigation has outlined a couple of critical issues: : : - Evaluating HCR_EL2.E2H must always be done with a sanitising : accessor, no ifs, no buts. Given that KVM assumes a fixed value for : this bit, we cannot leave it to the guest to mess with. : : - Resetting the sysreg file must result in the RESx bits taking : effect. Otherwise, we may end-up making the wrong decision (see : above), and we definitely expose invalid values to the guest. Note : that because we compute the RESx masks very late in the VM setup, we : need to apply these masks at that particular point as well. : [...]" : . KVM: arm64: nv: Apply RESx settings to sysreg reset values KVM: arm64: nv: Always evaluate HCR_EL2 using sanitising accessors Signed-off-by: Marc Zyngier <[email protected]> # Conflicts: # arch/arm64/kvm/nested.c
2 parents 946904e + 36f998d commit 3643b33

File tree

5 files changed

+29
-27
lines changed

5 files changed

+29
-27
lines changed

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -184,29 +184,30 @@ static inline bool vcpu_is_el2(const struct kvm_vcpu *vcpu)
184184
return vcpu_is_el2_ctxt(&vcpu->arch.ctxt);
185185
}
186186

187-
static inline bool __vcpu_el2_e2h_is_set(const struct kvm_cpu_context *ctxt)
187+
static inline bool vcpu_el2_e2h_is_set(const struct kvm_vcpu *vcpu)
188188
{
189189
return (!cpus_have_final_cap(ARM64_HAS_HCR_NV1) ||
190-
(ctxt_sys_reg(ctxt, HCR_EL2) & HCR_E2H));
190+
(__vcpu_sys_reg(vcpu, HCR_EL2) & HCR_E2H));
191191
}
192192

193-
static inline bool vcpu_el2_e2h_is_set(const struct kvm_vcpu *vcpu)
193+
static inline bool vcpu_el2_tge_is_set(const struct kvm_vcpu *vcpu)
194194
{
195-
return __vcpu_el2_e2h_is_set(&vcpu->arch.ctxt);
195+
return ctxt_sys_reg(&vcpu->arch.ctxt, HCR_EL2) & HCR_TGE;
196196
}
197197

198-
static inline bool __vcpu_el2_tge_is_set(const struct kvm_cpu_context *ctxt)
198+
static inline bool is_hyp_ctxt(const struct kvm_vcpu *vcpu)
199199
{
200-
return ctxt_sys_reg(ctxt, HCR_EL2) & HCR_TGE;
201-
}
200+
bool e2h, tge;
201+
u64 hcr;
202202

203-
static inline bool vcpu_el2_tge_is_set(const struct kvm_vcpu *vcpu)
204-
{
205-
return __vcpu_el2_tge_is_set(&vcpu->arch.ctxt);
206-
}
203+
if (!vcpu_has_nv(vcpu))
204+
return false;
205+
206+
hcr = __vcpu_sys_reg(vcpu, HCR_EL2);
207+
208+
e2h = (hcr & HCR_E2H);
209+
tge = (hcr & HCR_TGE);
207210

208-
static inline bool __is_hyp_ctxt(const struct kvm_cpu_context *ctxt)
209-
{
210211
/*
211212
* We are in a hypervisor context if the vcpu mode is EL2 or
212213
* E2H and TGE bits are set. The latter means we are in the user space
@@ -215,14 +216,7 @@ static inline bool __is_hyp_ctxt(const struct kvm_cpu_context *ctxt)
215216
* Note that the HCR_EL2.{E2H,TGE}={0,1} isn't really handled in the
216217
* rest of the KVM code, and will result in a misbehaving guest.
217218
*/
218-
return vcpu_is_el2_ctxt(ctxt) ||
219-
(__vcpu_el2_e2h_is_set(ctxt) && __vcpu_el2_tge_is_set(ctxt)) ||
220-
__vcpu_el2_tge_is_set(ctxt);
221-
}
222-
223-
static inline bool is_hyp_ctxt(const struct kvm_vcpu *vcpu)
224-
{
225-
return vcpu_has_nv(vcpu) && __is_hyp_ctxt(&vcpu->arch.ctxt);
219+
return vcpu_is_el2(vcpu) || (e2h && tge) || tge;
226220
}
227221

228222
static inline bool vcpu_is_host_el0(const struct kvm_vcpu *vcpu)

arch/arm64/include/asm/kvm_nested.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ static inline bool kvm_supported_tlbi_s1e2_op(struct kvm_vcpu *vpcu, u32 instr)
187187
return true;
188188
}
189189

190-
int kvm_init_nv_sysregs(struct kvm *kvm);
190+
int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu);
191191

192192
#ifdef CONFIG_ARM64_PTR_AUTH
193193
bool kvm_auth_eretax(struct kvm_vcpu *vcpu, u64 *elr);

arch/arm64/kvm/hyp/vhe/sysreg-sr.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ void __vcpu_load_switch_sysregs(struct kvm_vcpu *vcpu)
216216
__sysreg32_restore_state(vcpu);
217217
__sysreg_restore_user_state(guest_ctxt);
218218

219-
if (unlikely(__is_hyp_ctxt(guest_ctxt))) {
219+
if (unlikely(is_hyp_ctxt(vcpu))) {
220220
__sysreg_restore_vel2_state(vcpu);
221221
} else {
222222
if (vcpu_has_nv(vcpu)) {
@@ -260,7 +260,7 @@ void __vcpu_put_switch_sysregs(struct kvm_vcpu *vcpu)
260260

261261
host_ctxt = host_data_ptr(host_ctxt);
262262

263-
if (unlikely(__is_hyp_ctxt(guest_ctxt)))
263+
if (unlikely(is_hyp_ctxt(vcpu)))
264264
__sysreg_save_vel2_state(vcpu);
265265
else
266266
__sysreg_save_el1_state(guest_ctxt);

arch/arm64/kvm/nested.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -963,14 +963,15 @@ static __always_inline void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0,
963963
kvm->arch.sysreg_masks->mask[i].res1 = res1;
964964
}
965965

966-
int kvm_init_nv_sysregs(struct kvm *kvm)
966+
int kvm_init_nv_sysregs(struct kvm_vcpu *vcpu)
967967
{
968+
struct kvm *kvm = vcpu->kvm;
968969
u64 res0, res1;
969970

970971
lockdep_assert_held(&kvm->arch.config_lock);
971972

972973
if (kvm->arch.sysreg_masks)
973-
return 0;
974+
goto out;
974975

975976
kvm->arch.sysreg_masks = kzalloc(sizeof(*(kvm->arch.sysreg_masks)),
976977
GFP_KERNEL_ACCOUNT);
@@ -1286,6 +1287,10 @@ int kvm_init_nv_sysregs(struct kvm *kvm)
12861287
res0 |= GENMASK(11, 8);
12871288
set_sysreg_masks(kvm, CNTHCTL_EL2, res0, res1);
12881289

1290+
out:
1291+
for (enum vcpu_sysreg sr = __SANITISED_REG_START__; sr < NR_SYS_REGS; sr++)
1292+
(void)__vcpu_sys_reg(vcpu, sr);
1293+
12891294
return 0;
12901295
}
12911296

arch/arm64/kvm/sys_regs.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4450,6 +4450,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
44504450
reset_vcpu_ftr_id_reg(vcpu, r);
44514451
else
44524452
r->reset(vcpu, r);
4453+
4454+
if (r->reg >= __SANITISED_REG_START__ && r->reg < NR_SYS_REGS)
4455+
(void)__vcpu_sys_reg(vcpu, r->reg);
44534456
}
44544457

44554458
set_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags);
@@ -5053,7 +5056,7 @@ int kvm_finalize_sys_regs(struct kvm_vcpu *vcpu)
50535056
}
50545057

50555058
if (vcpu_has_nv(vcpu)) {
5056-
int ret = kvm_init_nv_sysregs(kvm);
5059+
int ret = kvm_init_nv_sysregs(vcpu);
50575060
if (ret)
50585061
return ret;
50595062
}

0 commit comments

Comments
 (0)