QEMU interrupt system use GPIO to implement interrupt system. We can understand it by a simple model:
Device.[GPIO_OUT] ->[GPIO_IN].GIC.[GPIO_OUT]->[GPIO_IN].core
GPIO_IN IRQ is created by qdev_init_gpio_in()
GPIO_OUT IRQ is initialized by sysbus_init_irq()->qdev_init_gpio_out_named(). Attention, GPIO_OUT IRQ is not created. Actually it is just a IRQ pointer, and the IRQ pointer will point to the GPIO_IN IRQ which connected. sysbus_connect_irq() connects GPIO_OUT and GPIO_IN IRQ.
Here let's take vexpress-a9 as the example.
ARM core:
ARM core has irq,fiq,virq,vfiq for GPIO_IN IRQ. they are created at:
arm_cpu_initfn()->qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4);
GIC:
GIC has 96 GPIO_IN IRQs and 4 GPIO_OUT IRQs, and they are created at:
arm_gic_realize()->gic_init_irqs_and_mmio()
void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
const MemoryRegionOps *ops,
const MemoryRegionOps *virt_ops)
{
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
int i = s->num_irq - GIC_INTERNAL;
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
* GPIO array layout is thus:
* [0..N-1] SPIs
* [N..N+31] PPIs for CPU 0
* [N+32..N+63] PPIs for CPU 1
* ...
*/
i += (GIC_INTERNAL * s->num_cpu);
qdev_init_gpio_in(DEVICE(s), handler, i); // GPIO_IN IRQs