Skip to content

Commit 89896cc

Browse files
Marc Zyngieroupton
authored andcommitted
KVM: arm64: nv: Fold GICv3 host trapping requirements into guest setup
Popular HW that is able to use NV also has a broken vgic implementation that requires trapping. On such HW, propagate the host trap bits into the guest's shadow ICH_HCR_EL2 register, making sure we don't allow an L2 guest to bring the system down. This involves a bit of tweaking so that the emulation code correctly poicks up the shadow state as needed, and to only partially sync ICH_HCR_EL2 back with the guest state to capture EOIcount. Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20250225172930.1850838-15-maz@kernel.org Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 7682c02 commit 89896cc

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

arch/arm64/kvm/vgic/vgic-v3-nested.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,19 @@ static void vgic_v3_create_shadow_state(struct kvm_vcpu *vcpu,
296296
struct vgic_v3_cpu_if *s_cpu_if)
297297
{
298298
struct vgic_v3_cpu_if *host_if = &vcpu->arch.vgic_cpu.vgic_v3;
299+
u64 val = 0;
299300
int i;
300301

301-
s_cpu_if->vgic_hcr = __vcpu_sys_reg(vcpu, ICH_HCR_EL2);
302+
/*
303+
* If we're on a system with a broken vgic that requires
304+
* trapping, propagate the trapping requirements.
305+
*
306+
* Ah, the smell of rotten fruits...
307+
*/
308+
if (static_branch_unlikely(&vgic_v3_cpuif_trap))
309+
val = host_if->vgic_hcr & (ICH_HCR_EL2_TALL0 | ICH_HCR_EL2_TALL1 |
310+
ICH_HCR_EL2_TC | ICH_HCR_EL2_TDIR);
311+
s_cpu_if->vgic_hcr = __vcpu_sys_reg(vcpu, ICH_HCR_EL2) | val;
302312
s_cpu_if->vgic_vmcr = __vcpu_sys_reg(vcpu, ICH_VMCR_EL2);
303313
s_cpu_if->vgic_sre = host_if->vgic_sre;
304314

@@ -335,6 +345,7 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu)
335345
{
336346
struct shadow_if *shadow_if = get_shadow_if();
337347
struct vgic_v3_cpu_if *s_cpu_if = &shadow_if->cpuif;
348+
u64 val;
338349
int i;
339350

340351
__vgic_v3_save_vmcr_aprs(s_cpu_if);
@@ -345,7 +356,10 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu)
345356
* Translate the shadow state HW fields back to the virtual ones
346357
* before copying the shadow struct back to the nested one.
347358
*/
348-
__vcpu_sys_reg(vcpu, ICH_HCR_EL2) = s_cpu_if->vgic_hcr;
359+
val = __vcpu_sys_reg(vcpu, ICH_HCR_EL2);
360+
val &= ~ICH_HCR_EL2_EOIcount_MASK;
361+
val |= (s_cpu_if->vgic_hcr & ICH_HCR_EL2_EOIcount_MASK);
362+
__vcpu_sys_reg(vcpu, ICH_HCR_EL2) = val;
349363
__vcpu_sys_reg(vcpu, ICH_VMCR_EL2) = s_cpu_if->vgic_vmcr;
350364

351365
for (i = 0; i < 4; i++) {
@@ -354,7 +368,7 @@ void vgic_v3_put_nested(struct kvm_vcpu *vcpu)
354368
}
355369

356370
for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) {
357-
u64 val = __vcpu_sys_reg(vcpu, ICH_LRN(i));
371+
val = __vcpu_sys_reg(vcpu, ICH_LRN(i));
358372

359373
val &= ~ICH_LR_STATE;
360374
val |= s_cpu_if->vgic_lr[i] & ICH_LR_STATE;

0 commit comments

Comments
 (0)