xref: /kvmtool/x86/irq.c (revision 8ccc85497ca3136688b015fecaa956fd95b936a1)
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