17c0e8b0cSWill Deacon #include "kvm/fdt.h" 27c0e8b0cSWill Deacon #include "kvm/kvm.h" 37c0e8b0cSWill Deacon #include "kvm/virtio.h" 47c0e8b0cSWill Deacon 57c0e8b0cSWill Deacon #include "arm-common/gic.h" 67c0e8b0cSWill Deacon 77c0e8b0cSWill Deacon #include <linux/byteorder.h> 87c0e8b0cSWill Deacon #include <linux/kvm.h> 97c0e8b0cSWill Deacon 107c0e8b0cSWill Deacon static int irq_ids; 117c0e8b0cSWill Deacon 127c0e8b0cSWill Deacon int gic__alloc_irqnum(void) 137c0e8b0cSWill Deacon { 147c0e8b0cSWill Deacon int irq = GIC_SPI_IRQ_BASE + irq_ids++; 157c0e8b0cSWill Deacon 167c0e8b0cSWill Deacon if (irq > GIC_MAX_IRQ) 177c0e8b0cSWill Deacon die("GIC IRQ limit %d reached!", GIC_MAX_IRQ); 187c0e8b0cSWill Deacon 197c0e8b0cSWill Deacon return irq; 207c0e8b0cSWill Deacon } 217c0e8b0cSWill Deacon 227c0e8b0cSWill Deacon int gic__init_irqchip(struct kvm *kvm) 237c0e8b0cSWill Deacon { 247c0e8b0cSWill Deacon int err; 25*aa7a0e79SWill Deacon struct kvm_arm_device_addr gic_addr[] = { 267c0e8b0cSWill Deacon [0] = { 27*aa7a0e79SWill Deacon .id = KVM_VGIC_V2_ADDR_TYPE_DIST | 28*aa7a0e79SWill Deacon (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT), 297c0e8b0cSWill Deacon .addr = ARM_GIC_DIST_BASE, 307c0e8b0cSWill Deacon }, 317c0e8b0cSWill Deacon [1] = { 32*aa7a0e79SWill Deacon .id = KVM_VGIC_V2_ADDR_TYPE_CPU | 33*aa7a0e79SWill Deacon (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT), 347c0e8b0cSWill Deacon .addr = ARM_GIC_CPUI_BASE, 357c0e8b0cSWill Deacon } 367c0e8b0cSWill Deacon }; 377c0e8b0cSWill Deacon 387c0e8b0cSWill Deacon if (kvm->nrcpus > GIC_MAX_CPUS) { 397c0e8b0cSWill Deacon pr_warning("%d CPUS greater than maximum of %d -- truncating\n", 407c0e8b0cSWill Deacon kvm->nrcpus, GIC_MAX_CPUS); 417c0e8b0cSWill Deacon kvm->nrcpus = GIC_MAX_CPUS; 427c0e8b0cSWill Deacon } 437c0e8b0cSWill Deacon 447c0e8b0cSWill Deacon err = ioctl(kvm->vm_fd, KVM_CREATE_IRQCHIP); 457c0e8b0cSWill Deacon if (err) 467c0e8b0cSWill Deacon return err; 477c0e8b0cSWill Deacon 48*aa7a0e79SWill Deacon err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[0]); 497c0e8b0cSWill Deacon if (err) 507c0e8b0cSWill Deacon return err; 517c0e8b0cSWill Deacon 52*aa7a0e79SWill Deacon err = ioctl(kvm->vm_fd, KVM_ARM_SET_DEVICE_ADDR, &gic_addr[1]); 537c0e8b0cSWill Deacon return err; 547c0e8b0cSWill Deacon } 557c0e8b0cSWill Deacon 567c0e8b0cSWill Deacon void gic__generate_fdt_nodes(void *fdt, u32 phandle) 577c0e8b0cSWill Deacon { 587c0e8b0cSWill Deacon u64 reg_prop[] = { 597c0e8b0cSWill Deacon cpu_to_fdt64(ARM_GIC_DIST_BASE), cpu_to_fdt64(ARM_GIC_DIST_SIZE), 607c0e8b0cSWill Deacon cpu_to_fdt64(ARM_GIC_CPUI_BASE), cpu_to_fdt64(ARM_GIC_CPUI_SIZE), 617c0e8b0cSWill Deacon }; 627c0e8b0cSWill Deacon 637c0e8b0cSWill Deacon _FDT(fdt_begin_node(fdt, "intc")); 647c0e8b0cSWill Deacon _FDT(fdt_property_string(fdt, "compatible", "arm,cortex-a15-gic")); 657c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS)); 667c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "interrupt-controller", NULL, 0)); 677c0e8b0cSWill Deacon _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 687c0e8b0cSWill Deacon _FDT(fdt_property_cell(fdt, "phandle", phandle)); 697c0e8b0cSWill Deacon _FDT(fdt_end_node(fdt)); 707c0e8b0cSWill Deacon } 717c0e8b0cSWill Deacon 727c0e8b0cSWill Deacon #define KVM_IRQCHIP_IRQ(x) (KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT) |\ 737c0e8b0cSWill Deacon ((x) & KVM_ARM_IRQ_NUM_MASK) 747c0e8b0cSWill Deacon 757c0e8b0cSWill Deacon void kvm__irq_line(struct kvm *kvm, int irq, int level) 767c0e8b0cSWill Deacon { 777c0e8b0cSWill Deacon struct kvm_irq_level irq_level = { 787c0e8b0cSWill Deacon .irq = KVM_IRQCHIP_IRQ(irq), 797c0e8b0cSWill Deacon .level = !!level, 807c0e8b0cSWill Deacon }; 817c0e8b0cSWill Deacon 827c0e8b0cSWill Deacon if (irq < GIC_SPI_IRQ_BASE || irq > GIC_MAX_IRQ) 837c0e8b0cSWill Deacon pr_warning("Ignoring invalid GIC IRQ %d", irq); 847c0e8b0cSWill Deacon else if (ioctl(kvm->vm_fd, KVM_IRQ_LINE, &irq_level) < 0) 857c0e8b0cSWill Deacon pr_warning("Could not KVM_IRQ_LINE for irq %d", irq); 867c0e8b0cSWill Deacon } 877c0e8b0cSWill Deacon 887c0e8b0cSWill Deacon void kvm__irq_trigger(struct kvm *kvm, int irq) 897c0e8b0cSWill Deacon { 907c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_HIGH); 917c0e8b0cSWill Deacon kvm__irq_line(kvm, irq, VIRTIO_IRQ_LOW); 927c0e8b0cSWill Deacon } 93