Skip to content

Commit

Permalink
KVM: arm64: Fix CPU interface MMIO compatibility detection
Browse files Browse the repository at this point in the history
In order to detect whether a GICv3 CPU interface is MMIO capable,
we switch ICC_SRE_EL1.SRE to 0 and check whether it sticks.

However, this is only possible if *ALL* of the HCR_EL2 interrupt
overrides are set, and the CPU is perfectly allowed to ignore
the write to ICC_SRE_EL1 otherwise. This leads KVM to pretend
that a whole bunch of ARMv8.0 CPUs aren't MMIO-capable, and
breaks VMs that should work correctly otherwise.

Fix this by setting IMO/FMO/IMO before touching ICC_SRE_EL1,
and clear them afterwards. This allows us to reliably detect
the CPU interface capabilities.

Tested-by: Shameerali Kolothum Thodi <[email protected]>
Fixes: 9739f6e ("KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibility")
Signed-off-by: Marc Zyngier <[email protected]>
  • Loading branch information
Marc Zyngier committed Mar 24, 2021
1 parent a354a64 commit af22df9
Showing 1 changed file with 9 additions and 0 deletions.
9 changes: 9 additions & 0 deletions arch/arm64/kvm/hyp/vgic-v3-sr.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,13 +429,22 @@ u64 __vgic_v3_get_gic_config(void)
if (has_vhe())
flags = local_daif_save();

/*
* Table 11-2 "Permitted ICC_SRE_ELx.SRE settings" indicates
* that to be able to set ICC_SRE_EL1.SRE to 0, all the
* interrupt overrides must be set. You've got to love this.
*/
sysreg_clear_set(hcr_el2, 0, HCR_AMO | HCR_FMO | HCR_IMO);
isb();
write_gicreg(0, ICC_SRE_EL1);
isb();

val = read_gicreg(ICC_SRE_EL1);

write_gicreg(sre, ICC_SRE_EL1);
isb();
sysreg_clear_set(hcr_el2, HCR_AMO | HCR_FMO | HCR_IMO, 0);
isb();

if (has_vhe())
local_daif_restore(flags);
Expand Down

0 comments on commit af22df9

Please sign in to comment.