Skip to content

Commit c139b6d

Browse files
author
Marc Zyngier
committed
KVM: arm64: nv: Always evaluate HCR_EL2 using sanitising accessors
A lot of the NV code depends on HCR_EL2.{E2H,TGE}, and we assume in places that at least HCR_EL2.E2H is invariant for a given guest. However, we make a point in *not* using the sanitising accessor that would enforce this, and are at the mercy of the guest doing stupid things. Clearly, that's not good. Rework the HCR_EL2 accessors to use __vcpu_sys_reg() instead, guaranteeing that the RESx settings get applied, specially when HCR_EL2.E2H is evaluated. This results in fewer accessors overall. Huge thanks to Joey who spent a long time tracking this bug down. Reported-by: Joey Gouly <[email protected]> Tested-by: Joey Gouly <[email protected]> Reviewed-by: Joey Gouly <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent 40384c8 commit c139b6d

File tree

2 files changed

+17
-23
lines changed

2 files changed

+17
-23
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/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);

0 commit comments

Comments
 (0)