1c383fe9cSSasha Levin #include "kvm/irq.h"
25f0a22b7SSasha Levin #include "kvm/kvm.h"
35f0a22b7SSasha Levin #include "kvm/util.h"
4c383fe9cSSasha Levin
5c383fe9cSSasha Levin #include <linux/types.h>
6c383fe9cSSasha Levin #include <linux/rbtree.h>
7c383fe9cSSasha Levin #include <linux/list.h>
85f0a22b7SSasha Levin #include <linux/kvm.h>
95f0a22b7SSasha Levin #include <sys/ioctl.h>
10c383fe9cSSasha Levin
11c383fe9cSSasha Levin #include <stddef.h>
12c383fe9cSSasha Levin #include <stdlib.h>
13c383fe9cSSasha Levin
145f0a22b7SSasha Levin #define IRQCHIP_MASTER 0
155f0a22b7SSasha Levin #define IRQCHIP_SLAVE 1
165f0a22b7SSasha Levin #define IRQCHIP_IOAPIC 2
175f0a22b7SSasha Levin
irq__add_routing(u32 gsi,u32 type,u32 irqchip,u32 pin)185f0a22b7SSasha Levin static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
195f0a22b7SSasha Levin {
20*8ccc8549SAndre Przywara int r = irq__allocate_routing_entry();
21*8ccc8549SAndre Przywara if (r)
22*8ccc8549SAndre Przywara return r;
235f0a22b7SSasha Levin
245f0a22b7SSasha Levin irq_routing->entries[irq_routing->nr++] =
255f0a22b7SSasha Levin (struct kvm_irq_routing_entry) {
265f0a22b7SSasha Levin .gsi = gsi,
275f0a22b7SSasha Levin .type = type,
285f0a22b7SSasha Levin .u.irqchip.irqchip = irqchip,
295f0a22b7SSasha Levin .u.irqchip.pin = pin,
305f0a22b7SSasha Levin };
315f0a22b7SSasha Levin
325f0a22b7SSasha Levin return 0;
335f0a22b7SSasha Levin }
345f0a22b7SSasha Levin
irq__init(struct kvm * kvm)35e3c4f8aaSSasha Levin int irq__init(struct kvm *kvm)
365f0a22b7SSasha Levin {
375f0a22b7SSasha Levin int i, r;
385f0a22b7SSasha Levin
395f0a22b7SSasha Levin /* Hook first 8 GSIs to master IRQCHIP */
405f0a22b7SSasha Levin for (i = 0; i < 8; i++)
412eb7ffa0SSasha Levin if (i != 2)
425f0a22b7SSasha Levin irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_MASTER, i);
435f0a22b7SSasha Levin
445f0a22b7SSasha Levin /* Hook next 8 GSIs to slave IRQCHIP */
455f0a22b7SSasha Levin for (i = 8; i < 16; i++)
462eb7ffa0SSasha Levin irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_SLAVE, i - 8);
475f0a22b7SSasha Levin
485f0a22b7SSasha Levin /* Last but not least, IOAPIC */
495f0a22b7SSasha Levin for (i = 0; i < 24; i++) {
505f0a22b7SSasha Levin if (i == 0)
515f0a22b7SSasha Levin irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, 2);
522eb7ffa0SSasha Levin else if (i != 2)
535f0a22b7SSasha Levin irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, i);
545f0a22b7SSasha Levin }
555f0a22b7SSasha Levin
565f0a22b7SSasha Levin r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
57e3c4f8aaSSasha Levin if (r) {
58e3c4f8aaSSasha Levin free(irq_routing);
59e3c4f8aaSSasha Levin return errno;
60e3c4f8aaSSasha Levin }
61e3c4f8aaSSasha Levin
62*8ccc8549SAndre Przywara next_gsi = i;
63*8ccc8549SAndre Przywara
64e3c4f8aaSSasha Levin return 0;
65e3c4f8aaSSasha Levin }
6649a8afd1SSasha Levin dev_base_init(irq__init);
67