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: Handle in-LR deactivation when possible

Even when we have either an LR overflow or SPIs in flight, it is
extremely likely that the interrupt being deactivated is still in
the LRs, and that going all the way back to the the generic trap
handling code is a waste of time.

Instead, try and deactivate in place when possible, and only if
this fails, perform a full exit.

Tested-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-33-maz@kernel.org
Signed-off-by: Oliver Upton <oupton@kernel.org>

authored by

Marc Zyngier and committed by
Oliver Upton
ca3c34da 1c3b3cad

+28 -10
+28 -10
arch/arm64/kvm/hyp/vgic-v3-sr.c
··· 792 792 write_gicreg(hcr, ICH_HCR_EL2); 793 793 } 794 794 795 - static void __vgic_v3_write_dir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) 795 + static int ___vgic_v3_write_dir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) 796 796 { 797 797 u32 vid = vcpu_get_reg(vcpu, rt); 798 798 u64 lr_val; ··· 800 800 801 801 /* EOImode == 0, nothing to be done here */ 802 802 if (!(vmcr & ICH_VMCR_EOIM_MASK)) 803 - return; 803 + return 1; 804 804 805 805 /* No deactivate to be performed on an LPI */ 806 806 if (vid >= VGIC_MIN_LPI) 807 - return; 807 + return 1; 808 808 809 809 lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val); 810 - if (lr == -1) { 811 - __vgic_v3_bump_eoicount(); 812 - return; 810 + if (lr != -1) { 811 + __vgic_v3_clear_active_lr(lr, lr_val); 812 + return 1; 813 813 } 814 814 815 - __vgic_v3_clear_active_lr(lr, lr_val); 815 + return 0; 816 + } 817 + 818 + static void __vgic_v3_write_dir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) 819 + { 820 + if (!___vgic_v3_write_dir(vcpu, vmcr, rt)) 821 + __vgic_v3_bump_eoicount(); 816 822 } 817 823 818 824 static void __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt) ··· 1253 1247 case SYS_ICC_DIR_EL1: 1254 1248 if (unlikely(is_read)) 1255 1249 return 0; 1256 - /* Full exit if required to handle overflow deactivation... */ 1257 - if (vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr & ICH_HCR_EL2_TDIR) 1258 - return 0; 1250 + /* 1251 + * Full exit if required to handle overflow deactivation, 1252 + * unless we can emulate it in the LRs (likely the majority 1253 + * of the cases). 1254 + */ 1255 + if (vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr & ICH_HCR_EL2_TDIR) { 1256 + int ret; 1257 + 1258 + ret = ___vgic_v3_write_dir(vcpu, __vgic_v3_read_vmcr(), 1259 + kvm_vcpu_sys_get_rt(vcpu)); 1260 + if (ret) 1261 + __kvm_skip_instr(vcpu); 1262 + 1263 + return ret; 1264 + } 1259 1265 fn = __vgic_v3_write_dir; 1260 1266 break; 1261 1267 case SYS_ICC_RPR_EL1: