Separate the CPU interface, redistributor and distributor address setup from GIC device creation. Keep the per-GIC address handling in small helpers. Use the irqchip enum order to omit the GICv2 PPI CPU mask for GICv3 and later generations. Suggested-by: Vladimir Murzin Signed-off-by: Sascha Bischoff --- arm64/gic.c | 94 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 32 deletions(-) diff --git a/arm64/gic.c b/arm64/gic.c index f8371f50..57f3fa02 100644 --- a/arm64/gic.c +++ b/arm64/gic.c @@ -142,52 +142,90 @@ out_close: return err; } -static int gic__create_msi_frame(struct kvm *kvm, enum irqchip_type type, - u64 msi_frame_addr) +static int gic__create_msi_frame(struct kvm *kvm, enum irqchip_type type) { switch (type) { case IRQCHIP_GICV2M: - return gic__create_gicv2m_frame(kvm, msi_frame_addr); + return gic__create_gicv2m_frame(kvm, gic_msi_base); case IRQCHIP_GICV3_ITS: - return gic__create_its_frame(kvm, msi_frame_addr); + return gic__create_its_frame(kvm, gic_msi_base); default: /* No MSI frame needed */ return 0; } } -static int gic__create_device(struct kvm *kvm, enum irqchip_type type) +static int gic__set_cpu_if(enum irqchip_type type) { - int err; u64 cpu_if_addr = ARM_GIC_CPUI_BASE; - u64 dist_addr = ARM_GIC_DIST_BASE; - struct kvm_create_device gic_device = { - .flags = 0, - }; struct kvm_device_attr cpu_if_attr = { .group = KVM_DEV_ARM_VGIC_GRP_ADDR, .attr = KVM_VGIC_V2_ADDR_TYPE_CPU, .addr = (u64)(unsigned long)&cpu_if_addr, }; - struct kvm_device_attr dist_attr = { - .group = KVM_DEV_ARM_VGIC_GRP_ADDR, - .addr = (u64)(unsigned long)&dist_addr, - }; + + switch (type) { + case IRQCHIP_GICV2M: + case IRQCHIP_GICV2: + return ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &cpu_if_attr); + default: /* No CPU interface needed */ + return 0; + } +} + +static int gic__set_redist(enum irqchip_type type) +{ struct kvm_device_attr redist_attr = { .group = KVM_DEV_ARM_VGIC_GRP_ADDR, .attr = KVM_VGIC_V3_ADDR_TYPE_REDIST, .addr = (u64)(unsigned long)&gic_redists_base, }; + switch (type) { + case IRQCHIP_GICV3: + case IRQCHIP_GICV3_ITS: + return ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &redist_attr); + default: /* No redistributor needed */ + return 0; + } +} + +static int gic__set_dist(enum irqchip_type type) +{ + u64 dist_addr = ARM_GIC_DIST_BASE; + struct kvm_device_attr dist_attr = { + .group = KVM_DEV_ARM_VGIC_GRP_ADDR, + .addr = (u64)(unsigned long)&dist_addr, + }; + + switch (type) { + case IRQCHIP_GICV2M: + case IRQCHIP_GICV2: + dist_attr.attr = KVM_VGIC_V2_ADDR_TYPE_DIST; + return ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &dist_attr); + case IRQCHIP_GICV3: + case IRQCHIP_GICV3_ITS: + dist_attr.attr = KVM_VGIC_V3_ADDR_TYPE_DIST; + return ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &dist_attr); + default: /* No distributor needed */ + return 0; + } +} + +static int gic__create_device(struct kvm *kvm, enum irqchip_type type) +{ + int err; + struct kvm_create_device gic_device = { + .flags = 0, + }; + switch (type) { case IRQCHIP_GICV2M: case IRQCHIP_GICV2: gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V2; - dist_attr.attr = KVM_VGIC_V2_ADDR_TYPE_DIST; break; case IRQCHIP_GICV3: case IRQCHIP_GICV3_ITS: gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V3; - dist_attr.attr = KVM_VGIC_V3_ADDR_TYPE_DIST; break; case IRQCHIP_AUTO: return -ENODEV; @@ -199,26 +237,19 @@ static int gic__create_device(struct kvm *kvm, enum irqchip_type type) gic_fd = gic_device.fd; - switch (type) { - case IRQCHIP_GICV2M: - case IRQCHIP_GICV2: - err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &cpu_if_attr); - break; - case IRQCHIP_GICV3_ITS: - case IRQCHIP_GICV3: - err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &redist_attr); - break; - case IRQCHIP_AUTO: - return -ENODEV; - } + err = gic__set_cpu_if(type); + if (err) + goto out_err; + + err = gic__set_redist(type); if (err) goto out_err; - err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &dist_attr); + err = gic__set_dist(type); if (err) goto out_err; - err = gic__create_msi_frame(kvm, type, gic_msi_base); + err = gic__create_msi_frame(kvm, type); if (err) goto out_err; @@ -439,8 +470,7 @@ void gic__generate_fdt_nodes(void *fdt, struct kvm *kvm) u32 gic__get_fdt_irq_cpumask(struct kvm *kvm) { /* Only for GICv2 */ - if (kvm->cfg.arch.irqchip == IRQCHIP_GICV3 || - kvm->cfg.arch.irqchip == IRQCHIP_GICV3_ITS) + if (kvm->cfg.arch.irqchip >= IRQCHIP_GICV3) return 0; if (kvm->nrcpus > 8) -- 2.34.1