Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

KVM: arm64: GICv3: Force exit to sync ICH_HCR_EL2.En

FEAT_NV2 is pretty terrible for anything that tries to enforce immediate
effects, and writing to ICH_HCR_EL2 in the hope to disable a maintenance
interrupt is vain. This only hits memory, and the guest hasn't cleared
anything -- the MI will fire.

For example, running the vgic_irq test under NV results in about 800
maintenance interrupts being actually handled by the L1 guest,
when none were expected.

As a cheap workaround, read back ICH_MISR_EL2 after writing 0 to
ICH_HCR_EL2. This is very cheap on real HW, and causes a trap to
the host in NV, giving it the opportunity to retire the pending MI.
With this, the above test runs to completion without any MI being
actually handled.

Yes, this is really poor...

Tested-by: Fuad Tabba <tabba@google.com>
Reviewed-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Tested-by: Mark Brown <broonie@kernel.org>
Link: https://msgid.link/20251120172540.2267180-37-maz@kernel.org
Signed-off-by: Oliver Upton <oupton@kernel.org>

authored by

Marc Zyngier and committed by
Oliver Upton
78ffc284 6dd333c8

+11 -2
+7
arch/arm64/kvm/hyp/vgic-v3-sr.c
··· 244 244 } 245 245 246 246 write_gicreg(0, ICH_HCR_EL2); 247 + 248 + /* 249 + * Hack alert: On NV, this results in a trap so that the above write 250 + * actually takes effect... No synchronisation is necessary, as we 251 + * only care about the effects when this traps. 252 + */ 253 + read_gicreg(ICH_MISR_EL2); 247 254 } 248 255 249 256 void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if)
+4 -2
arch/arm64/kvm/vgic/vgic-v3-nested.c
··· 94 94 * 95 95 * - because most of the ICH_*_EL2 registers live in the VNCR page, the 96 96 * quality of emulation is poor: L1 can setup the vgic so that an MI would 97 - * immediately fire, and not observe anything until the next exit. Trying 98 - * to read ICH_MISR_EL2 would do the trick, for example. 97 + * immediately fire, and not observe anything until the next exit. 98 + * Similarly, a pending MI is not immediately disabled by clearing 99 + * ICH_HCR_EL2.En. Trying to read ICH_MISR_EL2 would do the trick, for 100 + * example. 99 101 * 100 102 * System register emulation: 101 103 *