17c0e8b0cSWill Deacon #include "kvm/fdt.h" 2bed2bd9eSMarc Zyngier #include "kvm/irq.h" 37c0e8b0cSWill Deacon #include "kvm/kvm.h" 47c0e8b0cSWill Deacon #include "kvm/virtio.h" 57c0e8b0cSWill Deacon 67c0e8b0cSWill Deacon #include "arm-common/gic.h" 77c0e8b0cSWill Deacon 87c0e8b0cSWill Deacon #include <linux/byteorder.h> 9bed2bd9eSMarc Zyngier #include <linux/kernel.h> 107c0e8b0cSWill Deacon #include <linux/kvm.h> 117c0e8b0cSWill Deacon 12bfb2c703SAndre Przywara /* Those names are not defined for ARM (yet) */ 13bfb2c703SAndre Przywara #ifndef KVM_VGIC_V3_ADDR_TYPE_DIST 14bfb2c703SAndre Przywara #define KVM_VGIC_V3_ADDR_TYPE_DIST 2 15bfb2c703SAndre Przywara #endif 16bfb2c703SAndre Przywara 17bfb2c703SAndre Przywara #ifndef KVM_VGIC_V3_ADDR_TYPE_REDIST 18bfb2c703SAndre Przywara #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3 19bfb2c703SAndre Przywara #endif 20bfb2c703SAndre Przywara 2169b9a17aSMarc Zyngier static int gic_fd = -1; 22bfb2c703SAndre Przywara static u64 gic_redists_base; 23bfb2c703SAndre Przywara static u64 gic_redists_size; 2469b9a17aSMarc Zyngier 25*43d2781cSAndre Przywara int irqchip_parser(const struct option *opt, const char *arg, int unset) 26*43d2781cSAndre Przywara { 27*43d2781cSAndre Przywara enum irqchip_type *type = opt->value; 28*43d2781cSAndre Przywara 29*43d2781cSAndre Przywara if (!strcmp(arg, "gicv2")) { 30*43d2781cSAndre Przywara *type = IRQCHIP_GICV2; 31*43d2781cSAndre Przywara } else if (!strcmp(arg, "gicv3")) { 32*43d2781cSAndre Przywara *type = IRQCHIP_GICV3; 33*43d2781cSAndre Przywara } else { 34*43d2781cSAndre Przywara pr_err("irqchip: unknown type \"%s\"\n", arg); 35*43d2781cSAndre Przywara return -1; 36*43d2781cSAndre Przywara } 37*43d2781cSAndre Przywara 38*43d2781cSAndre Przywara return 0; 39*43d2781cSAndre Przywara } 40*43d2781cSAndre Przywara 4102017c1dSAndre Przywara static int gic__create_device(struct kvm *kvm, enum irqchip_type type) 4269b9a17aSMarc Zyngier { 4369b9a17aSMarc Zyngier int err; 4469b9a17aSMarc Zyngier u64 cpu_if_addr = ARM_GIC_CPUI_BASE; 4569b9a17aSMarc Zyngier u64 dist_addr = ARM_GIC_DIST_BASE; 4669b9a17aSMarc Zyngier struct kvm_create_device gic_device = { 4702017c1dSAndre Przywara .flags = 0, 4869b9a17aSMarc Zyngier }; 4969b9a17aSMarc Zyngier struct kvm_device_attr cpu_if_attr = { 5069b9a17aSMarc Zyngier .group = KVM_DEV_ARM_VGIC_GRP_ADDR, 5169b9a17aSMarc Zyngier .attr = KVM_VGIC_V2_ADDR_TYPE_CPU, 5269b9a17aSMarc Zyngier .addr = (u64)(unsigned long)&cpu_if_addr, 5369b9a17aSMarc Zyngier }; 5469b9a17aSMarc Zyngier struct kvm_device_attr dist_attr = { 5569b9a17aSMarc Zyngier .group = KVM_DEV_ARM_VGIC_GRP_ADDR, 5669b9a17aSMarc Zyngier .addr = (u64)(unsigned long)&dist_addr, 5769b9a17aSMarc Zyngier }; 58bfb2c703SAndre Przywara struct kvm_device_attr redist_attr = { 59bfb2c703SAndre Przywara .group = KVM_DEV_ARM_VGIC_GRP_ADDR, 60bfb2c703SAndre Przywara .attr = KVM_VGIC_V3_ADDR_TYPE_REDIST, 61bfb2c703SAndre Przywara .addr = (u64)(unsigned long)&gic_redists_base, 62bfb2c703SAndre Przywara }; 6369b9a17aSMarc Zyngier 6402017c1dSAndre Przywara switch (type) { 6502017c1dSAndre Przywara case IRQCHIP_GICV2: 6602017c1dSAndre Przywara gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V2; 6702017c1dSAndre Przywara dist_attr.attr = KVM_VGIC_V2_ADDR_TYPE_DIST; 6802017c1dSAndre Przywara break; 69bfb2c703SAndre Przywara case IRQCHIP_GICV3: 70bfb2c703SAndre Przywara gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V3; 71bfb2c703SAndre Przywara dist_attr.attr = KVM_VGIC_V3_ADDR_TYPE_DIST; 72bfb2c703SAndre Przywara break; 7302017c1dSAndre Przywara } 7402017c1dSAndre Przywara 7569b9a17aSMarc Zyngier err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &gic_device); 7669b9a17aSMarc Zyngier if (err) 7769b9a17aSMarc Zyngier return err; 7869b9a17aSMarc Zyngier 7969b9a17aSMarc Zyngier gic_fd = gic_device.fd; 8069b9a17aSMarc Zyngier 8102017c1dSAndre Przywara switch (type) { 8202017c1dSAndre Przywara case IRQCHIP_GICV2: 8369b9a17aSMarc Zyngier err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &cpu_if_attr); 8402017c1dSAndre Przywara break; 85bfb2c703SAndre Przywara case IRQCHIP_GICV3: 86bfb2c703SAndre Przywara err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &redist_attr); 87bfb2c703SAndre Przywara break; 8802017c1dSAndre Przywara } 8969b9a17aSMarc Zyngier if (err) 9069b9a17aSMarc Zyngier goto out_err; 9169b9a17aSMarc Zyngier 9269b9a17aSMarc Zyngier err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &dist_attr); 9369b9a17aSMarc Zyngier if (err) 9469b9a17aSMarc Zyngier goto out_err; 9569b9a17aSMarc Zyngier 9669b9a17aSMarc Zyngier return 0; 9769b9a17aSMarc Zyngier 9869b9a17aSMarc Zyngier out_err: 9969b9a17aSMarc Zyngier close(gic_fd); 10069b9a17aSMarc Zyngier gic_fd = -1; 10169b9a17aSMarc Zyngier return err; 10269b9a17aSMarc Zyngier } 10369b9a17aSMarc Zyngier 10469b9a17aSMarc Zyngier static int gic__create_irqchip(struct kvm *kvm) 1057c0e8b0cSWill Deacon { 1067c0e8b0cSWill Deacon int err; 107aa7a0e79SWill Deacon struct kvm_arm_device_addr gic_addr[] = { 1087c0e8b0cSWill Deacon [0] = { 109aa7a0e79SWill Deacon .id = KVM_VGIC_V2_ADDR_TYPE_DIST | 110aa7a0e79SWill Deacon (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT), 1117c0e8b0cSWill Deacon .addr = ARM_GIC_DIST_BASE, 1127c0e8b0cSWill Deacon }, 1137c0e8b0cSWill Deacon [1] = { 114aa7a0e79SWill Deacon .id = KVM_VGIC_V2_ADDR_TYPE_CPU | 115aa7a0e79SWill Deacon (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT), 1167c0e8b0cSWill Deacon .addr = ARM_GIC_CPUI_BASE, 1177c0e8b0cSWill Deacon } 1187c0e8b0cSWill Deacon }; 1197c0e8b0cSWill Deacon 1207c0e8b0cSWill Deacon err = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP); 1217c0e8b0cSWill Deacon if (err) 1227c0e8b0cSWill Deacon return err; 1237c0e8b0cSWill Deacon 124aa7a0e79SWill Deacon err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[0]); 1257c0e8b0cSWill Deacon if (err) 1267c0e8b0cSWill Deacon return err; 1277c0e8b0cSWill Deacon 128aa7a0e79SWill Deacon err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[1]); 1297c0e8b0cSWill Deacon return err; 1307c0e8b0cSWill Deacon } 1317c0e8b0cSWill Deacon 13202017c1dSAndre Przywara int gic__create(struct kvm *kvm, enum irqchip_type type) 13369b9a17aSMarc Zyngier { 13469b9a17aSMarc Zyngier int err; 13569b9a17aSMarc Zyngier 13602017c1dSAndre Przywara switch (type) { 13702017c1dSAndre Przywara case IRQCHIP_GICV2: 13802017c1dSAndre Przywara break; 139bfb2c703SAndre Przywara case IRQCHIP_GICV3: 140bfb2c703SAndre Przywara gic_redists_size = kvm->cfg.nrcpus * ARM_GIC_REDIST_SIZE; 141bfb2c703SAndre Przywara gic_redists_base = ARM_GIC_DIST_BASE - gic_redists_size; 142bfb2c703SAndre Przywara break; 14302017c1dSAndre Przywara default: 14402017c1dSAndre Przywara return -ENODEV; 14502017c1dSAndre Przywara } 14602017c1dSAndre Przywara 14769b9a17aSMarc Zyngier /* Try the new way first, and fallback on legacy method otherwise */ 14802017c1dSAndre Przywara err = gic__create_device(kvm, type); 14902017c1dSAndre Przywara if (err && type == IRQCHIP_GICV2) 15069b9a17aSMarc Zyngier err = gic__create_irqchip(kvm); 15169b9a17aSMarc Zyngier 15269b9a17aSMarc Zyngier return err; 15369b9a17aSMarc Zyngier } 15469b9a17aSMarc Zyngier 155b5790302SAndre Przywara /* 156b5790302SAndre Przywara * Sets the number of used interrupts and finalizes the GIC init explicitly. 157b5790302SAndre Przywara */ 158bed2bd9eSMarc Zyngier static int gic__init_gic(struct kvm *kvm) 159bed2bd9eSMarc Zyngier { 160b5790302SAndre Przywara int ret; 161b5790302SAndre Przywara 162bed2bd9eSMarc Zyngier int lines = irq__get_nr_allocated_lines(); 163bed2bd9eSMarc Zyngier u32 nr_irqs = ALIGN(lines, 32) + GIC_SPI_IRQ_BASE; 164bed2bd9eSMarc Zyngier struct kvm_device_attr nr_irqs_attr = { 165bed2bd9eSMarc Zyngier .group = KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 166bed2bd9eSMarc Zyngier .addr = (u64)(unsigned long)&nr_irqs, 167bed2bd9eSMarc Zyngier }; 168b5790302SAndre Przywara struct kvm_device_attr vgic_init_attr = { 169b5790302SAndre Przywara .group = KVM_DEV_ARM_VGIC_GRP_CTRL, 170b5790302SAndre Przywara .attr = KVM_DEV_ARM_VGIC_CTRL_INIT, 171b5790302SAndre Przywara }; 172bed2bd9eSMarc Zyngier 173bed2bd9eSMarc Zyngier /* 174bed2bd9eSMarc Zyngier * If we didn't use the KVM_CREATE_DEVICE method, KVM will 175b5790302SAndre Przywara * give us some default number of interrupts. The GIC initialization 176b5790302SAndre Przywara * will be done automatically in this case. 177bed2bd9eSMarc Zyngier */ 178bed2bd9eSMarc Zyngier if (gic_fd < 0) 179bed2bd9eSMarc Zyngier return 0; 180bed2bd9eSMarc Zyngier 181b5790302SAndre Przywara if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, &nr_irqs_attr)) { 182b5790302SAndre Przywara ret = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &nr_irqs_attr); 183b5790302SAndre Przywara if (ret) 184b5790302SAndre Przywara return ret; 185b5790302SAndre Przywara } 186b5790302SAndre Przywara 187b5790302SAndre Przywara if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, &vgic_init_attr)) { 188b5790302SAndre Przywara ret = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &vgic_init_attr); 189b5790302SAndre Przywara if (ret) 190b5790302SAndre Przywara return ret; 191b5790302SAndre Przywara } 192bed2bd9eSMarc Zyngier 193bed2bd9eSMarc Zyngier return 0; 194bed2bd9eSMarc Zyngier } 195bed2bd9eSMarc Zyngier late_init(gic__init_gic) 196bed2bd9eSMarc Zyngier 19702017c1dSAndre Przywara void gic__generate_fdt_nodes(void *fdt, u32 phandle, enum irqchip_type type) 1987c0e8b0cSWill Deacon { 19902017c1dSAndre Przywara const char *compatible; 2007c0e8b0cSWill Deacon u64 reg_prop[] = { 2017c0e8b0cSWill Deacon cpu_to_fdt64(ARM_GIC_DIST_BASE), cpu_to_fdt64(ARM_GIC_DIST_SIZE), 202bfb2c703SAndre Przywara 0, 0, /* to be filled */ 2037c0e8b0cSWill Deacon }; 2047c0e8b0cSWill Deacon 20502017c1dSAndre Przywara switch (type) { 20602017c1dSAndre Przywara case IRQCHIP_GICV2: 20702017c1dSAndre Przywara compatible = "arm,cortex-a15-gic"; 208bfb2c703SAndre Przywara reg_prop[2] = cpu_to_fdt64(ARM_GIC_CPUI_BASE); 209bfb2c703SAndre Przywara reg_prop[3] = cpu_to_fdt64(ARM_GIC_CPUI_SIZE); 210bfb2c703SAndre Przywara break; 211bfb2c703SAndre Przywara case IRQCHIP_GICV3: 212bfb2c703SAndre Przywara compatible = "arm,gic-v3"; 213bfb2c703SAndre Przywara reg_prop[2] = cpu_to_fdt64(gic_redists_base); 214bfb2c703SAndre Przywara reg_prop[3] = cpu_to_fdt64(gic_redists_size); 21502017c1dSAndre Przywara break; 21602017c1dSAndre Przywara default: 21702017c1dSAndre Przywara return; 21802017c1dSAndre Przywara } 21902017c1dSAndre Przywara 2207c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "intc")); 22102017c1dSAndre Przywara _FDT(fdt_property_string(fdt, "compatible", compatible)); 2227c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS)); 2237c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0)); 2247c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 2257c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "phandle", phandle)); 2267c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 2277c0e8b0cSWill Deacon } 2287c0e8b0cSWill Deacon 2297c0e8b0cSWill Deacon #define KVM_IRQCHIP_IRQ(x) (KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT) |\ 2307c0e8b0cSWill Deacon ((x) & KVM_ARM_IRQ_NUM_MASK) 2317c0e8b0cSWill Deacon 2327c0e8b0cSWill Deacon void kvm__irq_line(struct kvm *kvm, int irq, int level) 2337c0e8b0cSWill Deacon { 2347c0e8b0cSWill Deacon struct kvm_irq_level irq_level = { 2357c0e8b0cSWill Deacon .irq = KVM_IRQCHIP_IRQ(irq), 2367c0e8b0cSWill Deacon .level = !!level, 2377c0e8b0cSWill Deacon }; 2387c0e8b0cSWill Deacon 2397c0e8b0cSWill Deacon if (irq < GIC_SPI_IRQ_BASE || irq > GIC_MAX_IRQ) 2407c0e8b0cSWill Deacon pr_warning("Ignoring invalid GIC IRQ %d", irq); 2417c0e8b0cSWill Deacon else if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0) 2427c0e8b0cSWill Deacon pr_warning("Could not KVM_IRQ_LINE for irq %d", irq); 2437c0e8b0cSWill Deacon } 2447c0e8b0cSWill Deacon 2457c0e8b0cSWill Deacon void kvm__irq_trigger(struct kvm *kvm, int irq) 2467c0e8b0cSWill Deacon { 2477c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH); 2487c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW); 2497c0e8b0cSWill Deacon } 250