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> 1112ca1401SAndre Przywara #include <linux/sizes.h> 127c0e8b0cSWill Deacon 1369ae77c5SAndre Przywara #define IRQCHIP_GIC 0 1469ae77c5SAndre Przywara 1569b9a17aSMarc Zyngier static int gic_fd = -1; 16bfb2c703SAndre Przywara static u64 gic_redists_base; 17bfb2c703SAndre Przywara static u64 gic_redists_size; 1812ca1401SAndre Przywara static u64 gic_msi_base; 1912ca1401SAndre Przywara static u64 gic_msi_size = 0; 20e59679d2SJean-Philippe Brucker static bool vgic_is_init = false; 21e59679d2SJean-Philippe Brucker 22e59679d2SJean-Philippe Brucker struct kvm_irqfd_line { 23e59679d2SJean-Philippe Brucker unsigned int gsi; 24e59679d2SJean-Philippe Brucker int trigger_fd; 25e59679d2SJean-Philippe Brucker int resample_fd; 26e59679d2SJean-Philippe Brucker struct list_head list; 27e59679d2SJean-Philippe Brucker }; 28e59679d2SJean-Philippe Brucker 29e59679d2SJean-Philippe Brucker static LIST_HEAD(irqfd_lines); 3069b9a17aSMarc Zyngier 3143d2781cSAndre Przywara int irqchip_parser(const struct option *opt, const char *arg, int unset) 3243d2781cSAndre Przywara { 3343d2781cSAndre Przywara enum irqchip_type *type = opt->value; 3443d2781cSAndre Przywara 3543d2781cSAndre Przywara if (!strcmp(arg, "gicv2")) { 3643d2781cSAndre Przywara *type = IRQCHIP_GICV2; 37f6108d72SJean-Philippe Brucker } else if (!strcmp(arg, "gicv2m")) { 38f6108d72SJean-Philippe Brucker *type = IRQCHIP_GICV2M; 3943d2781cSAndre Przywara } else if (!strcmp(arg, "gicv3")) { 4043d2781cSAndre Przywara *type = IRQCHIP_GICV3; 4176392d29SAndre Przywara } else if (!strcmp(arg, "gicv3-its")) { 4276392d29SAndre Przywara *type = IRQCHIP_GICV3_ITS; 4343d2781cSAndre Przywara } else { 4443d2781cSAndre Przywara pr_err("irqchip: unknown type \"%s\"\n", arg); 4543d2781cSAndre Przywara return -1; 4643d2781cSAndre Przywara } 4743d2781cSAndre Przywara 4843d2781cSAndre Przywara return 0; 4943d2781cSAndre Przywara } 5043d2781cSAndre Przywara 51e59679d2SJean-Philippe Brucker static int irq__setup_irqfd_lines(struct kvm *kvm) 52e59679d2SJean-Philippe Brucker { 53e59679d2SJean-Philippe Brucker int ret; 54e59679d2SJean-Philippe Brucker struct kvm_irqfd_line *line, *tmp; 55e59679d2SJean-Philippe Brucker 56e59679d2SJean-Philippe Brucker list_for_each_entry_safe(line, tmp, &irqfd_lines, list) { 57e59679d2SJean-Philippe Brucker ret = irq__common_add_irqfd(kvm, line->gsi, line->trigger_fd, 58e59679d2SJean-Philippe Brucker line->resample_fd); 59e59679d2SJean-Philippe Brucker if (ret < 0) { 60e59679d2SJean-Philippe Brucker pr_err("Failed to register IRQFD"); 61e59679d2SJean-Philippe Brucker return ret; 62e59679d2SJean-Philippe Brucker } 63e59679d2SJean-Philippe Brucker 64e59679d2SJean-Philippe Brucker list_del(&line->list); 65e59679d2SJean-Philippe Brucker free(line); 66e59679d2SJean-Philippe Brucker } 67e59679d2SJean-Philippe Brucker 68e59679d2SJean-Philippe Brucker return 0; 69e59679d2SJean-Philippe Brucker } 70e59679d2SJean-Philippe Brucker 7169ae77c5SAndre Przywara static int irq__routing_init(struct kvm *kvm) 7269ae77c5SAndre Przywara { 7369ae77c5SAndre Przywara int r; 7469ae77c5SAndre Przywara int irqlines = ALIGN(irq__get_nr_allocated_lines(), 32); 7569ae77c5SAndre Przywara 7669ae77c5SAndre Przywara /* 7769ae77c5SAndre Przywara * This describes the default routing that the kernel uses without 7869ae77c5SAndre Przywara * any routing explicitly set up via KVM_SET_GSI_ROUTING. So we 7969ae77c5SAndre Przywara * don't need to commit these setting right now. The first actual 8069ae77c5SAndre Przywara * user (MSI routing) will engage these mappings then. 8169ae77c5SAndre Przywara */ 8269ae77c5SAndre Przywara for (next_gsi = 0; next_gsi < irqlines; next_gsi++) { 8369ae77c5SAndre Przywara r = irq__allocate_routing_entry(); 8469ae77c5SAndre Przywara if (r) 8569ae77c5SAndre Przywara return r; 8669ae77c5SAndre Przywara 8769ae77c5SAndre Przywara irq_routing->entries[irq_routing->nr++] = 8869ae77c5SAndre Przywara (struct kvm_irq_routing_entry) { 8969ae77c5SAndre Przywara .gsi = next_gsi, 9069ae77c5SAndre Przywara .type = KVM_IRQ_ROUTING_IRQCHIP, 9169ae77c5SAndre Przywara .u.irqchip.irqchip = IRQCHIP_GIC, 9269ae77c5SAndre Przywara .u.irqchip.pin = next_gsi, 9369ae77c5SAndre Przywara }; 9469ae77c5SAndre Przywara } 9569ae77c5SAndre Przywara 9669ae77c5SAndre Przywara return 0; 9769ae77c5SAndre Przywara } 9869ae77c5SAndre Przywara 9912ca1401SAndre Przywara static int gic__create_its_frame(struct kvm *kvm, u64 its_frame_addr) 10012ca1401SAndre Przywara { 10112ca1401SAndre Przywara struct kvm_create_device its_device = { 10212ca1401SAndre Przywara .type = KVM_DEV_TYPE_ARM_VGIC_ITS, 10312ca1401SAndre Przywara .flags = 0, 10412ca1401SAndre Przywara }; 10512ca1401SAndre Przywara struct kvm_device_attr its_attr = { 10612ca1401SAndre Przywara .group = KVM_DEV_ARM_VGIC_GRP_ADDR, 10712ca1401SAndre Przywara .attr = KVM_VGIC_ITS_ADDR_TYPE, 10812ca1401SAndre Przywara .addr = (u64)(unsigned long)&its_frame_addr, 10912ca1401SAndre Przywara }; 11012ca1401SAndre Przywara struct kvm_device_attr its_init_attr = { 11112ca1401SAndre Przywara .group = KVM_DEV_ARM_VGIC_GRP_CTRL, 11212ca1401SAndre Przywara .attr = KVM_DEV_ARM_VGIC_CTRL_INIT, 11312ca1401SAndre Przywara }; 11412ca1401SAndre Przywara int err; 11512ca1401SAndre Przywara 11612ca1401SAndre Przywara err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &its_device); 11712ca1401SAndre Przywara if (err) { 11812ca1401SAndre Przywara fprintf(stderr, 11912ca1401SAndre Przywara "GICv3 ITS requested, but kernel does not support it.\n"); 12012ca1401SAndre Przywara fprintf(stderr, "Try --irqchip=gicv3 instead\n"); 12112ca1401SAndre Przywara return err; 12212ca1401SAndre Przywara } 12312ca1401SAndre Przywara 12412ca1401SAndre Przywara err = ioctl(its_device.fd, KVM_HAS_DEVICE_ATTR, &its_attr); 12512ca1401SAndre Przywara if (err) { 12612ca1401SAndre Przywara close(its_device.fd); 12712ca1401SAndre Przywara its_device.fd = -1; 12812ca1401SAndre Przywara return err; 12912ca1401SAndre Przywara } 13012ca1401SAndre Przywara 13112ca1401SAndre Przywara err = ioctl(its_device.fd, KVM_SET_DEVICE_ATTR, &its_attr); 13212ca1401SAndre Przywara if (err) 13312ca1401SAndre Przywara return err; 13412ca1401SAndre Przywara 13512ca1401SAndre Przywara return ioctl(its_device.fd, KVM_SET_DEVICE_ATTR, &its_init_attr); 13612ca1401SAndre Przywara } 13712ca1401SAndre Przywara 13812ca1401SAndre Przywara static int gic__create_msi_frame(struct kvm *kvm, enum irqchip_type type, 13912ca1401SAndre Przywara u64 msi_frame_addr) 14012ca1401SAndre Przywara { 14112ca1401SAndre Przywara switch (type) { 142f6108d72SJean-Philippe Brucker case IRQCHIP_GICV2M: 143f6108d72SJean-Philippe Brucker return gic__create_gicv2m_frame(kvm, msi_frame_addr); 14412ca1401SAndre Przywara case IRQCHIP_GICV3_ITS: 14512ca1401SAndre Przywara return gic__create_its_frame(kvm, msi_frame_addr); 14612ca1401SAndre Przywara default: /* No MSI frame needed */ 14712ca1401SAndre Przywara return 0; 14812ca1401SAndre Przywara } 14912ca1401SAndre Przywara } 15012ca1401SAndre Przywara 15102017c1dSAndre Przywara static int gic__create_device(struct kvm *kvm, enum irqchip_type type) 15269b9a17aSMarc Zyngier { 15369b9a17aSMarc Zyngier int err; 15469b9a17aSMarc Zyngier u64 cpu_if_addr = ARM_GIC_CPUI_BASE; 15569b9a17aSMarc Zyngier u64 dist_addr = ARM_GIC_DIST_BASE; 15669b9a17aSMarc Zyngier struct kvm_create_device gic_device = { 15702017c1dSAndre Przywara .flags = 0, 15869b9a17aSMarc Zyngier }; 15969b9a17aSMarc Zyngier struct kvm_device_attr cpu_if_attr = { 16069b9a17aSMarc Zyngier .group = KVM_DEV_ARM_VGIC_GRP_ADDR, 16169b9a17aSMarc Zyngier .attr = KVM_VGIC_V2_ADDR_TYPE_CPU, 16269b9a17aSMarc Zyngier .addr = (u64)(unsigned long)&cpu_if_addr, 16369b9a17aSMarc Zyngier }; 16469b9a17aSMarc Zyngier struct kvm_device_attr dist_attr = { 16569b9a17aSMarc Zyngier .group = KVM_DEV_ARM_VGIC_GRP_ADDR, 16669b9a17aSMarc Zyngier .addr = (u64)(unsigned long)&dist_addr, 16769b9a17aSMarc Zyngier }; 168bfb2c703SAndre Przywara struct kvm_device_attr redist_attr = { 169bfb2c703SAndre Przywara .group = KVM_DEV_ARM_VGIC_GRP_ADDR, 170bfb2c703SAndre Przywara .attr = KVM_VGIC_V3_ADDR_TYPE_REDIST, 171bfb2c703SAndre Przywara .addr = (u64)(unsigned long)&gic_redists_base, 172bfb2c703SAndre Przywara }; 17369b9a17aSMarc Zyngier 17402017c1dSAndre Przywara switch (type) { 175f6108d72SJean-Philippe Brucker case IRQCHIP_GICV2M: 17602017c1dSAndre Przywara case IRQCHIP_GICV2: 17702017c1dSAndre Przywara gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V2; 17802017c1dSAndre Przywara dist_attr.attr = KVM_VGIC_V2_ADDR_TYPE_DIST; 17902017c1dSAndre Przywara break; 180bfb2c703SAndre Przywara case IRQCHIP_GICV3: 18112ca1401SAndre Przywara case IRQCHIP_GICV3_ITS: 182bfb2c703SAndre Przywara gic_device.type = KVM_DEV_TYPE_ARM_VGIC_V3; 183bfb2c703SAndre Przywara dist_attr.attr = KVM_VGIC_V3_ADDR_TYPE_DIST; 184bfb2c703SAndre Przywara break; 185*c57e001aSAndre Przywara case IRQCHIP_AUTO: 186*c57e001aSAndre Przywara return -ENODEV; 18702017c1dSAndre Przywara } 18802017c1dSAndre Przywara 18969b9a17aSMarc Zyngier err = ioctl(kvm->vm_fd, KVM_CREATE_DEVICE, &gic_device); 19069b9a17aSMarc Zyngier if (err) 19169b9a17aSMarc Zyngier return err; 19269b9a17aSMarc Zyngier 19369b9a17aSMarc Zyngier gic_fd = gic_device.fd; 19469b9a17aSMarc Zyngier 19502017c1dSAndre Przywara switch (type) { 196f6108d72SJean-Philippe Brucker case IRQCHIP_GICV2M: 19702017c1dSAndre Przywara case IRQCHIP_GICV2: 19869b9a17aSMarc Zyngier err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &cpu_if_attr); 19902017c1dSAndre Przywara break; 20012ca1401SAndre Przywara case IRQCHIP_GICV3_ITS: 201bfb2c703SAndre Przywara case IRQCHIP_GICV3: 202bfb2c703SAndre Przywara err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &redist_attr); 203bfb2c703SAndre Przywara break; 204*c57e001aSAndre Przywara case IRQCHIP_AUTO: 205*c57e001aSAndre Przywara return -ENODEV; 20602017c1dSAndre Przywara } 20769b9a17aSMarc Zyngier if (err) 20869b9a17aSMarc Zyngier goto out_err; 20969b9a17aSMarc Zyngier 21069b9a17aSMarc Zyngier err = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &dist_attr); 21169b9a17aSMarc Zyngier if (err) 21269b9a17aSMarc Zyngier goto out_err; 21369b9a17aSMarc Zyngier 21412ca1401SAndre Przywara err = gic__create_msi_frame(kvm, type, gic_msi_base); 21512ca1401SAndre Przywara if (err) 21612ca1401SAndre Przywara goto out_err; 21712ca1401SAndre Przywara 21869b9a17aSMarc Zyngier return 0; 21969b9a17aSMarc Zyngier 22069b9a17aSMarc Zyngier out_err: 22169b9a17aSMarc Zyngier close(gic_fd); 22269b9a17aSMarc Zyngier gic_fd = -1; 22369b9a17aSMarc Zyngier return err; 22469b9a17aSMarc Zyngier } 22569b9a17aSMarc Zyngier 22669b9a17aSMarc Zyngier static int gic__create_irqchip(struct kvm *kvm) 2277c0e8b0cSWill Deacon { 2287c0e8b0cSWill Deacon int err; 229aa7a0e79SWill Deacon struct kvm_arm_device_addr gic_addr[] = { 2307c0e8b0cSWill Deacon [0] = { 231aa7a0e79SWill Deacon .id = KVM_VGIC_V2_ADDR_TYPE_DIST | 232aa7a0e79SWill Deacon (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT), 2337c0e8b0cSWill Deacon .addr = ARM_GIC_DIST_BASE, 2347c0e8b0cSWill Deacon }, 2357c0e8b0cSWill Deacon [1] = { 236aa7a0e79SWill Deacon .id = KVM_VGIC_V2_ADDR_TYPE_CPU | 237aa7a0e79SWill Deacon (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT), 2387c0e8b0cSWill Deacon .addr = ARM_GIC_CPUI_BASE, 2397c0e8b0cSWill Deacon } 2407c0e8b0cSWill Deacon }; 2417c0e8b0cSWill Deacon 2427c0e8b0cSWill Deacon err = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP); 2437c0e8b0cSWill Deacon if (err) 2447c0e8b0cSWill Deacon return err; 2457c0e8b0cSWill Deacon 246aa7a0e79SWill Deacon err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[0]); 2477c0e8b0cSWill Deacon if (err) 2487c0e8b0cSWill Deacon return err; 2497c0e8b0cSWill Deacon 250aa7a0e79SWill Deacon err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[1]); 2517c0e8b0cSWill Deacon return err; 2527c0e8b0cSWill Deacon } 2537c0e8b0cSWill Deacon 25402017c1dSAndre Przywara int gic__create(struct kvm *kvm, enum irqchip_type type) 25569b9a17aSMarc Zyngier { 256*c57e001aSAndre Przywara enum irqchip_type try; 25769b9a17aSMarc Zyngier int err; 25869b9a17aSMarc Zyngier 25902017c1dSAndre Przywara switch (type) { 260*c57e001aSAndre Przywara case IRQCHIP_AUTO: 261*c57e001aSAndre Przywara for (try = IRQCHIP_GICV3_ITS; try >= IRQCHIP_GICV2; try--) { 262*c57e001aSAndre Przywara err = gic__create(kvm, try); 263*c57e001aSAndre Przywara if (!err) 264*c57e001aSAndre Przywara break; 265*c57e001aSAndre Przywara } 266*c57e001aSAndre Przywara if (err) 267*c57e001aSAndre Przywara return err; 268*c57e001aSAndre Przywara 269*c57e001aSAndre Przywara kvm->cfg.arch.irqchip = try; 270*c57e001aSAndre Przywara return 0; 271f6108d72SJean-Philippe Brucker case IRQCHIP_GICV2M: 272f6108d72SJean-Philippe Brucker gic_msi_size = KVM_VGIC_V2M_SIZE; 273a43b08e8SAndre Przywara gic_msi_base = ARM_GIC_CPUI_BASE - gic_msi_size; 274f6108d72SJean-Philippe Brucker break; 27502017c1dSAndre Przywara case IRQCHIP_GICV2: 27602017c1dSAndre Przywara break; 27712ca1401SAndre Przywara case IRQCHIP_GICV3_ITS: 278a5d36dd1SAndre Przywara /* The 64K page with the doorbell is included. */ 279a5d36dd1SAndre Przywara gic_msi_size = KVM_VGIC_V3_ITS_SIZE; 28012ca1401SAndre Przywara /* fall through */ 281bfb2c703SAndre Przywara case IRQCHIP_GICV3: 282bfb2c703SAndre Przywara gic_redists_size = kvm->cfg.nrcpus * ARM_GIC_REDIST_SIZE; 283bfb2c703SAndre Przywara gic_redists_base = ARM_GIC_DIST_BASE - gic_redists_size; 28412ca1401SAndre Przywara gic_msi_base = gic_redists_base - gic_msi_size; 285bfb2c703SAndre Przywara break; 28602017c1dSAndre Przywara default: 28702017c1dSAndre Przywara return -ENODEV; 28802017c1dSAndre Przywara } 28902017c1dSAndre Przywara 29069b9a17aSMarc Zyngier /* Try the new way first, and fallback on legacy method otherwise */ 29102017c1dSAndre Przywara err = gic__create_device(kvm, type); 29202017c1dSAndre Przywara if (err && type == IRQCHIP_GICV2) 29369b9a17aSMarc Zyngier err = gic__create_irqchip(kvm); 29469b9a17aSMarc Zyngier 29569b9a17aSMarc Zyngier return err; 29669b9a17aSMarc Zyngier } 29769b9a17aSMarc Zyngier 298b5790302SAndre Przywara /* 299b5790302SAndre Przywara * Sets the number of used interrupts and finalizes the GIC init explicitly. 300b5790302SAndre Przywara */ 301bed2bd9eSMarc Zyngier static int gic__init_gic(struct kvm *kvm) 302bed2bd9eSMarc Zyngier { 303b5790302SAndre Przywara int ret; 304b5790302SAndre Przywara 305bed2bd9eSMarc Zyngier int lines = irq__get_nr_allocated_lines(); 306bed2bd9eSMarc Zyngier u32 nr_irqs = ALIGN(lines, 32) + GIC_SPI_IRQ_BASE; 307bed2bd9eSMarc Zyngier struct kvm_device_attr nr_irqs_attr = { 308bed2bd9eSMarc Zyngier .group = KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 309bed2bd9eSMarc Zyngier .addr = (u64)(unsigned long)&nr_irqs, 310bed2bd9eSMarc Zyngier }; 311b5790302SAndre Przywara struct kvm_device_attr vgic_init_attr = { 312b5790302SAndre Przywara .group = KVM_DEV_ARM_VGIC_GRP_CTRL, 313b5790302SAndre Przywara .attr = KVM_DEV_ARM_VGIC_CTRL_INIT, 314b5790302SAndre Przywara }; 315bed2bd9eSMarc Zyngier 316bed2bd9eSMarc Zyngier /* 317bed2bd9eSMarc Zyngier * If we didn't use the KVM_CREATE_DEVICE method, KVM will 318b5790302SAndre Przywara * give us some default number of interrupts. The GIC initialization 319b5790302SAndre Przywara * will be done automatically in this case. 320bed2bd9eSMarc Zyngier */ 321bed2bd9eSMarc Zyngier if (gic_fd < 0) 322bed2bd9eSMarc Zyngier return 0; 323bed2bd9eSMarc Zyngier 324b5790302SAndre Przywara if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, &nr_irqs_attr)) { 325b5790302SAndre Przywara ret = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &nr_irqs_attr); 326b5790302SAndre Przywara if (ret) 327b5790302SAndre Przywara return ret; 328b5790302SAndre Przywara } 329b5790302SAndre Przywara 33069ae77c5SAndre Przywara irq__routing_init(kvm); 33169ae77c5SAndre Przywara 332b5790302SAndre Przywara if (!ioctl(gic_fd, KVM_HAS_DEVICE_ATTR, &vgic_init_attr)) { 333b5790302SAndre Przywara ret = ioctl(gic_fd, KVM_SET_DEVICE_ATTR, &vgic_init_attr); 334b5790302SAndre Przywara if (ret) 335b5790302SAndre Przywara return ret; 336b5790302SAndre Przywara } 337bed2bd9eSMarc Zyngier 338714ab9e6SAndre Przywara kvm->msix_needs_devid = kvm__supports_vm_extension(kvm, 339714ab9e6SAndre Przywara KVM_CAP_MSI_DEVID); 340714ab9e6SAndre Przywara 341e59679d2SJean-Philippe Brucker vgic_is_init = true; 342e59679d2SJean-Philippe Brucker 343e59679d2SJean-Philippe Brucker return irq__setup_irqfd_lines(kvm); 344bed2bd9eSMarc Zyngier } 345bed2bd9eSMarc Zyngier late_init(gic__init_gic) 346bed2bd9eSMarc Zyngier 3470063d50cSAndre Przywara void gic__generate_fdt_nodes(void *fdt, enum irqchip_type type) 3487c0e8b0cSWill Deacon { 34914421de9SAndre Przywara const char *compatible, *msi_compatible = NULL; 35014421de9SAndre Przywara u64 msi_prop[2]; 3517c0e8b0cSWill Deacon u64 reg_prop[] = { 3527c0e8b0cSWill Deacon cpu_to_fdt64(ARM_GIC_DIST_BASE), cpu_to_fdt64(ARM_GIC_DIST_SIZE), 353bfb2c703SAndre Przywara 0, 0, /* to be filled */ 3547c0e8b0cSWill Deacon }; 3557c0e8b0cSWill Deacon 35602017c1dSAndre Przywara switch (type) { 357f6108d72SJean-Philippe Brucker case IRQCHIP_GICV2M: 358f6108d72SJean-Philippe Brucker msi_compatible = "arm,gic-v2m-frame"; 359f6108d72SJean-Philippe Brucker /* fall-through */ 36002017c1dSAndre Przywara case IRQCHIP_GICV2: 36102017c1dSAndre Przywara compatible = "arm,cortex-a15-gic"; 362bfb2c703SAndre Przywara reg_prop[2] = cpu_to_fdt64(ARM_GIC_CPUI_BASE); 363bfb2c703SAndre Przywara reg_prop[3] = cpu_to_fdt64(ARM_GIC_CPUI_SIZE); 364bfb2c703SAndre Przywara break; 36514421de9SAndre Przywara case IRQCHIP_GICV3_ITS: 36614421de9SAndre Przywara msi_compatible = "arm,gic-v3-its"; 36714421de9SAndre Przywara /* fall-through */ 368bfb2c703SAndre Przywara case IRQCHIP_GICV3: 369bfb2c703SAndre Przywara compatible = "arm,gic-v3"; 370bfb2c703SAndre Przywara reg_prop[2] = cpu_to_fdt64(gic_redists_base); 371bfb2c703SAndre Przywara reg_prop[3] = cpu_to_fdt64(gic_redists_size); 37202017c1dSAndre Przywara break; 37302017c1dSAndre Przywara default: 37402017c1dSAndre Przywara return; 37502017c1dSAndre Przywara } 37602017c1dSAndre Przywara 3777c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "intc")); 37802017c1dSAndre Przywara _FDT(fdt_property_string(fdt, "compatible", compatible)); 3797c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS)); 3807c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0)); 3817c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 3820063d50cSAndre Przywara _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_GIC)); 38314421de9SAndre Przywara _FDT(fdt_property_cell(fdt, "#address-cells", 2)); 38414421de9SAndre Przywara _FDT(fdt_property_cell(fdt, "#size-cells", 2)); 38514421de9SAndre Przywara 38614421de9SAndre Przywara if (msi_compatible) { 38714421de9SAndre Przywara _FDT(fdt_property(fdt, "ranges", NULL, 0)); 38814421de9SAndre Przywara 38914421de9SAndre Przywara _FDT(fdt_begin_node(fdt, "msic")); 39014421de9SAndre Przywara _FDT(fdt_property_string(fdt, "compatible", msi_compatible)); 39114421de9SAndre Przywara _FDT(fdt_property(fdt, "msi-controller", NULL, 0)); 39214421de9SAndre Przywara _FDT(fdt_property_cell(fdt, "phandle", PHANDLE_MSI)); 39314421de9SAndre Przywara msi_prop[0] = cpu_to_fdt64(gic_msi_base); 39414421de9SAndre Przywara msi_prop[1] = cpu_to_fdt64(gic_msi_size); 39514421de9SAndre Przywara _FDT(fdt_property(fdt, "reg", msi_prop, sizeof(msi_prop))); 39614421de9SAndre Przywara _FDT(fdt_end_node(fdt)); 39714421de9SAndre Przywara } 39814421de9SAndre Przywara 3997c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 4007c0e8b0cSWill Deacon } 4017c0e8b0cSWill Deacon 4027c0e8b0cSWill Deacon #define KVM_IRQCHIP_IRQ(x) (KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT) |\ 4037c0e8b0cSWill Deacon ((x) & KVM_ARM_IRQ_NUM_MASK) 4047c0e8b0cSWill Deacon 4057c0e8b0cSWill Deacon void kvm__irq_line(struct kvm *kvm, int irq, int level) 4067c0e8b0cSWill Deacon { 4077c0e8b0cSWill Deacon struct kvm_irq_level irq_level = { 4087c0e8b0cSWill Deacon .irq = KVM_IRQCHIP_IRQ(irq), 4097c0e8b0cSWill Deacon .level = !!level, 4107c0e8b0cSWill Deacon }; 4117c0e8b0cSWill Deacon 4127c0e8b0cSWill Deacon if (irq < GIC_SPI_IRQ_BASE || irq > GIC_MAX_IRQ) 4137c0e8b0cSWill Deacon pr_warning("Ignoring invalid GIC IRQ %d", irq); 4147c0e8b0cSWill Deacon else if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0) 4157c0e8b0cSWill Deacon pr_warning("Could not KVM_IRQ_LINE for irq %d", irq); 4167c0e8b0cSWill Deacon } 4177c0e8b0cSWill Deacon 4187c0e8b0cSWill Deacon void kvm__irq_trigger(struct kvm *kvm, int irq) 4197c0e8b0cSWill Deacon { 4207c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH); 4217c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW); 4227c0e8b0cSWill Deacon } 423e59679d2SJean-Philippe Brucker 424e59679d2SJean-Philippe Brucker int gic__add_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd, 425e59679d2SJean-Philippe Brucker int resample_fd) 426e59679d2SJean-Philippe Brucker { 427e59679d2SJean-Philippe Brucker struct kvm_irqfd_line *line; 428e59679d2SJean-Philippe Brucker 429e59679d2SJean-Philippe Brucker if (vgic_is_init) 430e59679d2SJean-Philippe Brucker return irq__common_add_irqfd(kvm, gsi, trigger_fd, resample_fd); 431e59679d2SJean-Philippe Brucker 432e59679d2SJean-Philippe Brucker /* Postpone the routing setup until we have a distributor */ 433e59679d2SJean-Philippe Brucker line = malloc(sizeof(*line)); 434e59679d2SJean-Philippe Brucker if (!line) 435e59679d2SJean-Philippe Brucker return -ENOMEM; 436e59679d2SJean-Philippe Brucker 437e59679d2SJean-Philippe Brucker *line = (struct kvm_irqfd_line) { 438e59679d2SJean-Philippe Brucker .gsi = gsi, 439e59679d2SJean-Philippe Brucker .trigger_fd = trigger_fd, 440e59679d2SJean-Philippe Brucker .resample_fd = resample_fd, 441e59679d2SJean-Philippe Brucker }; 442e59679d2SJean-Philippe Brucker list_add(&line->list, &irqfd_lines); 443e59679d2SJean-Philippe Brucker 444e59679d2SJean-Philippe Brucker return 0; 445e59679d2SJean-Philippe Brucker } 446e59679d2SJean-Philippe Brucker 447e59679d2SJean-Philippe Brucker void gic__del_irqfd(struct kvm *kvm, unsigned int gsi, int trigger_fd) 448e59679d2SJean-Philippe Brucker { 449e59679d2SJean-Philippe Brucker struct kvm_irqfd_line *line; 450e59679d2SJean-Philippe Brucker 451e59679d2SJean-Philippe Brucker if (vgic_is_init) { 452e59679d2SJean-Philippe Brucker irq__common_del_irqfd(kvm, gsi, trigger_fd); 453e59679d2SJean-Philippe Brucker return; 454e59679d2SJean-Philippe Brucker } 455e59679d2SJean-Philippe Brucker 456e59679d2SJean-Philippe Brucker list_for_each_entry(line, &irqfd_lines, list) { 457e59679d2SJean-Philippe Brucker if (line->gsi != gsi) 458e59679d2SJean-Philippe Brucker continue; 459e59679d2SJean-Philippe Brucker 460e59679d2SJean-Philippe Brucker list_del(&line->list); 461e59679d2SJean-Philippe Brucker free(line); 462e59679d2SJean-Philippe Brucker break; 463e59679d2SJean-Philippe Brucker } 464e59679d2SJean-Philippe Brucker } 465