Skip to content

Commit d9476fd

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/gic-v5-nv into kvmarm-master/next
* kvm-arm64/gic-v5-nv: : . : Add NV support to GICv5 in GICv3 emulation mode, ensuring that the v3 : guest support is identical to that of a pure v3 platform. : : Patches courtesy of Sascha Bischoff (20250828105925.3865158-1-sascha.bischoff@arm.com) : . irqchip/gic-v5: Drop has_gcie_v3_compat from gic_kvm_info KVM: arm64: Use ARM64_HAS_GICV5_LEGACY for GICv5 probing arm64: cpucaps: Add GICv5 Legacy vCPU interface (GCIE_LEGACY) capability KVM: arm64: Enable nested for GICv5 host with FEAT_GCIE_LEGACY KVM: arm64: Don't access ICC_SRE_EL2 if GICv3 doesn't support v2 compatibility Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents 8cba6c8 + 5c5db9e commit d9476fd

10 files changed

Lines changed: 41 additions & 28 deletions

File tree

arch/arm64/kernel/cpufeature.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,15 @@ test_has_mpam_hcr(const struct arm64_cpu_capabilities *entry, int scope)
25392539
return idr & MPAMIDR_EL1_HAS_HCR;
25402540
}
25412541

2542+
static bool
2543+
test_has_gicv5_legacy(const struct arm64_cpu_capabilities *entry, int scope)
2544+
{
2545+
if (!this_cpu_has_cap(ARM64_HAS_GICV5_CPUIF))
2546+
return false;
2547+
2548+
return !!(read_sysreg_s(SYS_ICC_IDR0_EL1) & ICC_IDR0_EL1_GCIE_LEGACY);
2549+
}
2550+
25422551
static const struct arm64_cpu_capabilities arm64_features[] = {
25432552
{
25442553
.capability = ARM64_ALWAYS_BOOT,
@@ -3156,6 +3165,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
31563165
.matches = has_cpuid_feature,
31573166
ARM64_CPUID_FIELDS(ID_AA64PFR2_EL1, GCIE, IMP)
31583167
},
3168+
{
3169+
.desc = "GICv5 Legacy vCPU interface",
3170+
.type = ARM64_CPUCAP_EARLY_LOCAL_CPU_FEATURE,
3171+
.capability = ARM64_HAS_GICV5_LEGACY,
3172+
.matches = test_has_gicv5_legacy,
3173+
},
31593174
{},
31603175
};
31613176

arch/arm64/kernel/image-vars.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors);
105105
KVM_NVHE_ALIAS(vgic_v2_cpuif_trap);
106106
KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
107107

108+
/* Static key indicating whether GICv3 has GICv2 compatibility */
109+
KVM_NVHE_ALIAS(vgic_v3_has_v2_compat);
110+
108111
/* Static key which is set if CNTVOFF_EL2 is unusable */
109112
KVM_NVHE_ALIAS(broken_cntvoff_key);
110113

arch/arm64/kvm/arm.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2321,8 +2321,9 @@ static int __init init_subsystems(void)
23212321
}
23222322

23232323
if (kvm_mode == KVM_MODE_NV &&
2324-
!(vgic_present && kvm_vgic_global_state.type == VGIC_V3)) {
2325-
kvm_err("NV support requires GICv3, giving up\n");
2324+
!(vgic_present && (kvm_vgic_global_state.type == VGIC_V3 ||
2325+
kvm_vgic_global_state.has_gcie_v3_compat))) {
2326+
kvm_err("NV support requires GICv3 or GICv5 with legacy support, giving up\n");
23262327
err = -EINVAL;
23272328
goto out;
23282329
}

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

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -295,12 +295,8 @@ void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if)
295295
}
296296
}
297297

298-
/*
299-
* GICv5 BET0 FEAT_GCIE_LEGACY doesn't include ICC_SRE_EL2. This is due
300-
* to be relaxed in a future spec release, at which point this in
301-
* condition can be dropped.
302-
*/
303-
if (!cpus_have_final_cap(ARM64_HAS_GICV5_CPUIF)) {
298+
/* Only disable SRE if the host implements the GICv2 interface */
299+
if (static_branch_unlikely(&vgic_v3_has_v2_compat)) {
304300
/*
305301
* Prevent the guest from touching the ICC_SRE_EL1 system
306302
* register. Note that this may not have any effect, as
@@ -329,19 +325,16 @@ void __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if)
329325
cpu_if->vgic_vmcr = read_gicreg(ICH_VMCR_EL2);
330326
}
331327

332-
/*
333-
* Can be dropped in the future when GICv5 spec is relaxed. See comment
334-
* above.
335-
*/
336-
if (!cpus_have_final_cap(ARM64_HAS_GICV5_CPUIF)) {
328+
/* Only restore SRE if the host implements the GICv2 interface */
329+
if (static_branch_unlikely(&vgic_v3_has_v2_compat)) {
337330
val = read_gicreg(ICC_SRE_EL2);
338331
write_gicreg(val | ICC_SRE_EL2_ENABLE, ICC_SRE_EL2);
339-
}
340332

341-
if (!cpu_if->vgic_sre) {
342-
/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
343-
isb();
344-
write_gicreg(1, ICC_SRE_EL1);
333+
if (!cpu_if->vgic_sre) {
334+
/* Make sure ENABLE is set at EL2 before setting SRE at EL1 */
335+
isb();
336+
write_gicreg(1, ICC_SRE_EL1);
337+
}
345338
}
346339

347340
/*

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@ int vgic_v3_map_resources(struct kvm *kvm)
588588
}
589589

590590
DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
591+
DEFINE_STATIC_KEY_FALSE(vgic_v3_has_v2_compat);
591592

592593
static int __init early_group0_trap_cfg(char *buf)
593594
{
@@ -697,6 +698,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
697698
if (kvm_vgic_global_state.vcpu_base == 0)
698699
kvm_info("disabling GICv2 emulation\n");
699700

701+
/*
702+
* Flip the static branch if the HW supports v2, even if we're
703+
* not using it (such as in protected mode).
704+
*/
705+
if (has_v2)
706+
static_branch_enable(&vgic_v3_has_v2_compat);
707+
700708
if (cpus_have_final_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
701709
group0_trap = true;
702710
group1_trap = true;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ int vgic_v5_probe(const struct gic_kvm_info *info)
1515
u64 ich_vtr_el2;
1616
int ret;
1717

18-
if (!info->has_gcie_v3_compat)
18+
if (!cpus_have_final_cap(ARM64_HAS_GICV5_LEGACY))
1919
return -ENODEV;
2020

2121
kvm_vgic_global_state.type = VGIC_V5;

arch/arm64/tools/cpucaps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ HAS_GENERIC_AUTH_ARCH_QARMA5
3737
HAS_GENERIC_AUTH_IMP_DEF
3838
HAS_GICV3_CPUIF
3939
HAS_GICV5_CPUIF
40+
HAS_GICV5_LEGACY
4041
HAS_GIC_PRIO_MASKING
4142
HAS_GIC_PRIO_RELAXED_SYNC
4243
HAS_HCR_NV1

drivers/irqchip/irq-gic-v5.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,16 +1062,9 @@ static void gicv5_set_cpuif_idbits(void)
10621062
#ifdef CONFIG_KVM
10631063
static struct gic_kvm_info gic_v5_kvm_info __initdata;
10641064

1065-
static bool __init gicv5_cpuif_has_gcie_legacy(void)
1066-
{
1067-
u64 idr0 = read_sysreg_s(SYS_ICC_IDR0_EL1);
1068-
return !!FIELD_GET(ICC_IDR0_EL1_GCIE_LEGACY, idr0);
1069-
}
1070-
10711065
static void __init gic_of_setup_kvm_info(struct device_node *node)
10721066
{
10731067
gic_v5_kvm_info.type = GIC_V5;
1074-
gic_v5_kvm_info.has_gcie_v3_compat = gicv5_cpuif_has_gcie_legacy();
10751068

10761069
/* GIC Virtual CPU interface maintenance interrupt */
10771070
gic_v5_kvm_info.no_maint_irq_mask = false;

include/kvm/arm_vgic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ struct vgic_cpu {
375375

376376
extern struct static_key_false vgic_v2_cpuif_trap;
377377
extern struct static_key_false vgic_v3_cpuif_trap;
378+
extern struct static_key_false vgic_v3_has_v2_compat;
378379

379380
int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev_addr);
380381
void kvm_vgic_early_init(struct kvm *kvm);

include/linux/irqchip/arm-vgic-info.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ struct gic_kvm_info {
3636
bool has_v4_1;
3737
/* Deactivation impared, subpar stuff */
3838
bool no_hw_deactivation;
39-
/* v3 compat support (GICv5 hosts, only) */
40-
bool has_gcie_v3_compat;
4139
};
4240

4341
#ifdef CONFIG_KVM

0 commit comments

Comments
 (0)