Skip to content

Commit 303084a

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: Filter out HCR_EL2 bits when running in hypervisor context
Most HCR_EL2 bits are not supposed to affect EL2 at all, but only the guest. However, we gladly merge these bits with the host's HCR_EL2 configuration, irrespective of entering L1 or L2. This leads to some funky behaviour, such as L1 trying to inject a virtual SError for L2, and getting a taste of its own medecine. Not quite what the architecture anticipated. In the end, the only bits that matter are those we have defined as invariants, either because we've made them RESx (E2H, HCD...), or that we actively refuse to merge because the mess with KVM's own logic. Use the sanitisation infrastructure to get the RES1 bits, and let things rip in a safer way. Fixes: 04ab519 ("KVM: arm64: nv: Configure HCR_EL2 for FEAT_NV2") Signed-off-by: Marc Zyngier <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Oliver Upton <[email protected]>
1 parent c6e35df commit 303084a

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

arch/arm64/kvm/hyp/vhe/switch.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ DEFINE_PER_CPU(unsigned long, kvm_hyp_vector);
4848

4949
static u64 __compute_hcr(struct kvm_vcpu *vcpu)
5050
{
51-
u64 guest_hcr = __vcpu_sys_reg(vcpu, HCR_EL2);
52-
u64 hcr = vcpu->arch.hcr_el2;
51+
u64 guest_hcr, hcr = vcpu->arch.hcr_el2;
5352

5453
if (!vcpu_has_nv(vcpu))
5554
return hcr;
@@ -68,10 +67,21 @@ static u64 __compute_hcr(struct kvm_vcpu *vcpu)
6867
if (!vcpu_el2_e2h_is_set(vcpu))
6968
hcr |= HCR_NV1;
7069

70+
/*
71+
* Nothing in HCR_EL2 should impact running in hypervisor
72+
* context, apart from bits we have defined as RESx (E2H,
73+
* HCD and co), or that cannot be set directly (the EXCLUDE
74+
* bits). Given that we OR the guest's view with the host's,
75+
* we can use the 0 value as the starting point, and only
76+
* use the config-driven RES1 bits.
77+
*/
78+
guest_hcr = kvm_vcpu_apply_reg_masks(vcpu, HCR_EL2, 0);
79+
7180
write_sysreg_s(vcpu->arch.ctxt.vncr_array, SYS_VNCR_EL2);
7281
} else {
7382
host_data_clear_flag(VCPU_IN_HYP_CONTEXT);
7483

84+
guest_hcr = __vcpu_sys_reg(vcpu, HCR_EL2);
7585
if (guest_hcr & HCR_NV) {
7686
u64 va = __fix_to_virt(vncr_fixmap(smp_processor_id()));
7787

0 commit comments

Comments
 (0)