1*7c0e8b0cSWill Deacon #include "kvm/fdt.h" 2*7c0e8b0cSWill Deacon #include "kvm/kvm.h" 3*7c0e8b0cSWill Deacon #include "kvm/virtio.h" 4*7c0e8b0cSWill Deacon 5*7c0e8b0cSWill Deacon #include "arm-common/gic.h" 6*7c0e8b0cSWill Deacon 7*7c0e8b0cSWill Deacon #include <linux/byteorder.h> 8*7c0e8b0cSWill Deacon #include <linux/kvm.h> 9*7c0e8b0cSWill Deacon 10*7c0e8b0cSWill Deacon static int irq_ids; 11*7c0e8b0cSWill Deacon 12*7c0e8b0cSWill Deacon int gic__alloc_irqnum(void) 13*7c0e8b0cSWill Deacon { 14*7c0e8b0cSWill Deacon int irq = GIC_SPI_IRQ_BASE + irq_ids++; 15*7c0e8b0cSWill Deacon 16*7c0e8b0cSWill Deacon if (irq > GIC_MAX_IRQ) 17*7c0e8b0cSWill Deacon die("GIC IRQ limit %d reached!", GIC_MAX_IRQ); 18*7c0e8b0cSWill Deacon 19*7c0e8b0cSWill Deacon return irq; 20*7c0e8b0cSWill Deacon } 21*7c0e8b0cSWill Deacon 22*7c0e8b0cSWill Deacon int gic__init_irqchip(struct kvm *kvm) 23*7c0e8b0cSWill Deacon { 24*7c0e8b0cSWill Deacon int err; 25*7c0e8b0cSWill Deacon struct kvm_device_address gic_addr[] = { 26*7c0e8b0cSWill Deacon [0] = { 27*7c0e8b0cSWill Deacon .id = (KVM_ARM_DEVICE_VGIC_V2 << KVM_DEVICE_ID_SHIFT) |\ 28*7c0e8b0cSWill Deacon KVM_VGIC_V2_ADDR_TYPE_DIST, 29*7c0e8b0cSWill Deacon .addr = ARM_GIC_DIST_BASE, 30*7c0e8b0cSWill Deacon }, 31*7c0e8b0cSWill Deacon [1] = { 32*7c0e8b0cSWill Deacon .id = (KVM_ARM_DEVICE_VGIC_V2 << KVM_DEVICE_ID_SHIFT) |\ 33*7c0e8b0cSWill Deacon KVM_VGIC_V2_ADDR_TYPE_CPU, 34*7c0e8b0cSWill Deacon .addr = ARM_GIC_CPUI_BASE, 35*7c0e8b0cSWill Deacon } 36*7c0e8b0cSWill Deacon }; 37*7c0e8b0cSWill Deacon 38*7c0e8b0cSWill Deacon if (kvm->nrcpus > GIC_MAX_CPUS) { 39*7c0e8b0cSWill Deacon pr_warning("%d CPUS greater than maximum of %d -- truncating\n", 40*7c0e8b0cSWill Deacon kvm->nrcpus, GIC_MAX_CPUS); 41*7c0e8b0cSWill Deacon kvm->nrcpus = GIC_MAX_CPUS; 42*7c0e8b0cSWill Deacon } 43*7c0e8b0cSWill Deacon 44*7c0e8b0cSWill Deacon err = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP); 45*7c0e8b0cSWill Deacon if (err) 46*7c0e8b0cSWill Deacon return err; 47*7c0e8b0cSWill Deacon 48*7c0e8b0cSWill Deacon err = ioctl(kvm->vm_fd, KVM_SET_DEVICE_ADDRESS, &gic_addr[0]); 49*7c0e8b0cSWill Deacon if (err) 50*7c0e8b0cSWill Deacon return err; 51*7c0e8b0cSWill Deacon 52*7c0e8b0cSWill Deacon err = ioctl(kvm->vm_fd, KVM_SET_DEVICE_ADDRESS, &gic_addr[1]); 53*7c0e8b0cSWill Deacon return err; 54*7c0e8b0cSWill Deacon } 55*7c0e8b0cSWill Deacon 56*7c0e8b0cSWill Deacon void gic__generate_fdt_nodes(void *fdt, u32 phandle) 57*7c0e8b0cSWill Deacon { 58*7c0e8b0cSWill Deacon u64 reg_prop[] = { 59*7c0e8b0cSWill Deacon cpu_to_fdt64(ARM_GIC_DIST_BASE), cpu_to_fdt64(ARM_GIC_DIST_SIZE), 60*7c0e8b0cSWill Deacon cpu_to_fdt64(ARM_GIC_CPUI_BASE), cpu_to_fdt64(ARM_GIC_CPUI_SIZE), 61*7c0e8b0cSWill Deacon }; 62*7c0e8b0cSWill Deacon 63*7c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "intc")); 64*7c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "compatible", "arm,cortex-a15-gic")); 65*7c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS)); 66*7c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0)); 67*7c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 68*7c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "phandle", phandle)); 69*7c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 70*7c0e8b0cSWill Deacon } 71*7c0e8b0cSWill Deacon 72*7c0e8b0cSWill Deacon #define KVM_IRQCHIP_IRQ(x) (KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT) |\ 73*7c0e8b0cSWill Deacon ((x) & KVM_ARM_IRQ_NUM_MASK) 74*7c0e8b0cSWill Deacon 75*7c0e8b0cSWill Deacon void kvm__irq_line(struct kvm *kvm, int irq, int level) 76*7c0e8b0cSWill Deacon { 77*7c0e8b0cSWill Deacon struct kvm_irq_level irq_level = { 78*7c0e8b0cSWill Deacon .irq = KVM_IRQCHIP_IRQ(irq), 79*7c0e8b0cSWill Deacon .level = !!level, 80*7c0e8b0cSWill Deacon }; 81*7c0e8b0cSWill Deacon 82*7c0e8b0cSWill Deacon if (irq < GIC_SPI_IRQ_BASE || irq > GIC_MAX_IRQ) 83*7c0e8b0cSWill Deacon pr_warning("Ignoring invalid GIC IRQ %d", irq); 84*7c0e8b0cSWill Deacon else if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0) 85*7c0e8b0cSWill Deacon pr_warning("Could not KVM_IRQ_LINE for irq %d", irq); 86*7c0e8b0cSWill Deacon } 87*7c0e8b0cSWill Deacon 88*7c0e8b0cSWill Deacon void kvm__irq_trigger(struct kvm *kvm, int irq) 89*7c0e8b0cSWill Deacon { 90*7c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH); 91*7c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW); 92*7c0e8b0cSWill Deacon } 93