/* Send an MSI-X message */ void msix_notify(PCIDevice *dev, unsigned vector) { uint8_t *table_entry = dev->msix_table_page + vector * MSIX_ENTRY_SIZE; uint64_t address; uint32_t data; if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) return; if (msix_is_masked(dev, vector)) { msix_set_pending(dev, vector); return; } #ifdef KVM_CAP_IRQCHIP if (kvm_enabled() && qemu_kvm_irqchip_in_kernel()) { kvm_set_irq(dev->msix_irq_entries[vector].gsi, 1, NULL); return; } #endif address = pci_get_long(table_entry + MSIX_MSG_UPPER_ADDR); address = (address << 32) | pci_get_long(table_entry + MSIX_MSG_ADDR); data = pci_get_long(table_entry + MSIX_MSG_DATA); stl_phys(address, data); }
static void kvm_arm_gic_set_irq(void *opaque, int irq, int level) { /* Meaning of the 'irq' parameter: * [0..N-1] : external interrupts * [N..N+31] : PPI (internal) interrupts for CPU 0 * [N+32..N+63] : PPI (internal interrupts for CPU 1 * ... * Convert this to the kernel's desired encoding, which * has separate fields in the irq number for type, * CPU number and interrupt number. */ GICState *s = (GICState *)opaque; int kvm_irq, irqtype, cpu; if (irq < (s->num_irq - GIC_INTERNAL)) { /* External interrupt. The kernel numbers these like the GIC * hardware, with external interrupt IDs starting after the * internal ones. */ irqtype = KVM_ARM_IRQ_TYPE_SPI; cpu = 0; irq += GIC_INTERNAL; } else { /* Internal interrupt: decode into (cpu, interrupt id) */ irqtype = KVM_ARM_IRQ_TYPE_PPI; irq -= (s->num_irq - GIC_INTERNAL); cpu = irq / GIC_INTERNAL; irq %= GIC_INTERNAL; } kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT) | (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq; kvm_set_irq(kvm_state, kvm_irq, !!level); }
static void kvm_pic_set_irq(void *opaque, int irq, int level) { int delivered; delivered = kvm_set_irq(kvm_state, irq, level); apic_report_irq_delivered(delivered); }
int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, bool line_status) { if (!irqchip_in_kernel(kvm)) return -ENXIO; irq_event->status = kvm_set_irq(kvm, KVM_USERSPACE_IRQ_SOURCE_ID, irq_event->irq, irq_event->level, line_status); return 0; }
static void kvm_arm_pic_cpu_handler(void *opaque, int irq, int level) { #ifdef CONFIG_KVM ARMCPU *cpu = opaque; CPUState *cs = CPU(cpu); int kvm_irq = KVM_ARM_IRQ_TYPE_CPU << KVM_ARM_IRQ_TYPE_SHIFT; switch (irq) { case ARM_PIC_CPU_IRQ: kvm_irq |= KVM_ARM_IRQ_CPU_IRQ; break; case ARM_PIC_CPU_FIQ: kvm_irq |= KVM_ARM_IRQ_CPU_FIQ; break; default: hw_error("kvm_arm_pic_cpu_handler: Bad interrupt line %d\n", irq); } kvm_irq |= cs->cpu_index << KVM_ARM_IRQ_VCPU_SHIFT; kvm_set_irq(kvm_state, kvm_irq, level ? 1 : 0); #endif }
/* Send an MSI-X message */ void msix_notify(PCIDevice *dev, unsigned vector) { uint8_t *table_entry = dev->msix_table_page + vector * PCI_MSIX_ENTRY_SIZE; uint64_t address; uint32_t data; if (vector >= dev->msix_entries_nr || !dev->msix_entry_used[vector]) return; if (msix_is_masked(dev, vector)) { msix_set_pending(dev, vector); return; } if (kvm_enabled() && kvm_irqchip_in_kernel()) { kvm_set_irq(dev->msix_irq_entries[vector].gsi, 1, NULL); return; } address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR); data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA); stl_le_phys(address, data); }
static void kvm_openpic_set_irq(void *opaque, int n_IRQ, int level) { kvm_set_irq(kvm_state, n_IRQ, level); }