Skip to content

Commit 0924729

Browse files
author
Marc Zyngier
committed
KVM: arm64: vgic-v3: Reduce common group trapping to ICV_DIR_EL1 when possible
On systems that advertise ICH_VTR_EL2.SEIS, we trap all GICv3 sysreg accesses from the guest. From a performance perspective, this is OK as long as the guest doesn't hammer the GICv3 CPU interface. In most cases, this is fine, unless the guest actively uses priorities and switches PMR_EL1 very often. Which is exactly what happens when a Linux guest runs with irqchip.gicv3_pseudo_nmi=1. In these condition, the performance plumets as we hit PMR each time we mask/unmask interrupts. Not good. There is however an opportunity for improvement. Careful reading of the architecture specification indicates that the only GICv3 sysreg belonging to the common group (which contains the SGI registers, PMR, DIR, CTLR and RPR) that is allowed to generate a SError is DIR. Everything else is safe. It is thus possible to substitute the trapping of all the common group with just that of DIR if it supported by the implementation. Yes, that's yet another optional bit of the architecture. So let's just do that, as it leads to some impressive result on the M1: Without this change: bash-5.1# /host/home/maz/hackbench 100 process 1000 Running with 100*40 (== 4000) tasks. Time: 56.596 With this change: bash-5.1# /host/home/maz/hackbench 100 process 1000 Running with 100*40 (== 4000) tasks. Time: 8.649 which is a pretty convincing result. Signed-off-by: Marc Zyngier <[email protected]> Reviewed-by: Alexandru Elisei <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent df652bc commit 0924729

File tree

2 files changed

+14
-4
lines changed

2 files changed

+14
-4
lines changed

arch/arm64/include/asm/sysreg.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,7 @@
11521152
#define ICH_HCR_TC (1 << 10)
11531153
#define ICH_HCR_TALL0 (1 << 11)
11541154
#define ICH_HCR_TALL1 (1 << 12)
1155+
#define ICH_HCR_TDIR (1 << 14)
11551156
#define ICH_HCR_EOIcount_SHIFT 27
11561157
#define ICH_HCR_EOIcount_MASK (0x1f << ICH_HCR_EOIcount_SHIFT)
11571158

@@ -1184,6 +1185,8 @@
11841185
#define ICH_VTR_SEIS_MASK (1 << ICH_VTR_SEIS_SHIFT)
11851186
#define ICH_VTR_A3V_SHIFT 21
11861187
#define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT)
1188+
#define ICH_VTR_TDS_SHIFT 19
1189+
#define ICH_VTR_TDS_MASK (1 << ICH_VTR_TDS_SHIFT)
11871190

11881191
#define ARM64_FEATURE_FIELD_BITS 4
11891192

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

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
static bool group0_trap;
1616
static bool group1_trap;
1717
static bool common_trap;
18+
static bool dir_trap;
1819
static bool gicv4_enable;
1920

2021
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
@@ -296,6 +297,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
296297
vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
297298
if (common_trap)
298299
vgic_v3->vgic_hcr |= ICH_HCR_TC;
300+
if (dir_trap)
301+
vgic_v3->vgic_hcr |= ICH_HCR_TDIR;
299302
}
300303

301304
int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq)
@@ -676,14 +679,18 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
676679

677680
group0_trap = true;
678681
group1_trap = true;
679-
common_trap = true;
682+
if (ich_vtr_el2 & ICH_VTR_TDS_MASK)
683+
dir_trap = true;
684+
else
685+
common_trap = true;
680686
}
681687

682-
if (group0_trap || group1_trap || common_trap) {
683-
kvm_info("GICv3 sysreg trapping enabled ([%s%s%s], reduced performance)\n",
688+
if (group0_trap || group1_trap || common_trap | dir_trap) {
689+
kvm_info("GICv3 sysreg trapping enabled ([%s%s%s%s], reduced performance)\n",
684690
group0_trap ? "G0" : "",
685691
group1_trap ? "G1" : "",
686-
common_trap ? "C" : "");
692+
common_trap ? "C" : "",
693+
dir_trap ? "D" : "");
687694
static_branch_enable(&vgic_v3_cpuif_trap);
688695
}
689696

0 commit comments

Comments
 (0)