xref: /openbmc/qemu/hw/i386/kvm/ioapic.c (revision e1fe50dc)
1 /*
2  * KVM in-kernel IOPIC support
3  *
4  * Copyright (c) 2011 Siemens AG
5  *
6  * Authors:
7  *  Jan Kiszka          <jan.kiszka@siemens.com>
8  *
9  * This work is licensed under the terms of the GNU GPL version 2.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 #include "hw/i386/pc.h"
14 #include "hw/i386/ioapic_internal.h"
15 #include "hw/i386/apic_internal.h"
16 #include "sysemu/kvm.h"
17 
18 /* PC Utility function */
19 void kvm_pc_setup_irq_routing(bool pci_enabled)
20 {
21     KVMState *s = kvm_state;
22     int i;
23 
24     if (kvm_check_extension(s, KVM_CAP_IRQ_ROUTING)) {
25         for (i = 0; i < 8; ++i) {
26             if (i == 2) {
27                 continue;
28             }
29             kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_MASTER, i);
30         }
31         for (i = 8; i < 16; ++i) {
32             kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
33         }
34         if (pci_enabled) {
35             for (i = 0; i < 24; ++i) {
36                 if (i == 0) {
37                     kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, 2);
38                 } else if (i != 2) {
39                     kvm_irqchip_add_irq_route(s, i, KVM_IRQCHIP_IOAPIC, i);
40                 }
41             }
42         }
43     }
44 }
45 
46 void kvm_pc_gsi_handler(void *opaque, int n, int level)
47 {
48     GSIState *s = opaque;
49 
50     if (n < ISA_NUM_IRQS) {
51         /* Kernel will forward to both PIC and IOAPIC */
52         qemu_set_irq(s->i8259_irq[n], level);
53     } else {
54         qemu_set_irq(s->ioapic_irq[n], level);
55     }
56 }
57 
58 typedef struct KVMIOAPICState KVMIOAPICState;
59 
60 struct KVMIOAPICState {
61     IOAPICCommonState ioapic;
62     uint32_t kvm_gsi_base;
63 };
64 
65 static void kvm_ioapic_get(IOAPICCommonState *s)
66 {
67     struct kvm_irqchip chip;
68     struct kvm_ioapic_state *kioapic;
69     int ret, i;
70 
71     chip.chip_id = KVM_IRQCHIP_IOAPIC;
72     ret = kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, &chip);
73     if (ret < 0) {
74         fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
75         abort();
76     }
77 
78     kioapic = &chip.chip.ioapic;
79 
80     s->id = kioapic->id;
81     s->ioregsel = kioapic->ioregsel;
82     s->irr = kioapic->irr;
83     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
84         s->ioredtbl[i] = kioapic->redirtbl[i].bits;
85     }
86 }
87 
88 static void kvm_ioapic_put(IOAPICCommonState *s)
89 {
90     struct kvm_irqchip chip;
91     struct kvm_ioapic_state *kioapic;
92     int ret, i;
93 
94     chip.chip_id = KVM_IRQCHIP_IOAPIC;
95     kioapic = &chip.chip.ioapic;
96 
97     kioapic->id = s->id;
98     kioapic->ioregsel = s->ioregsel;
99     kioapic->base_address = s->busdev.mmio[0].addr;
100     kioapic->irr = s->irr;
101     for (i = 0; i < IOAPIC_NUM_PINS; i++) {
102         kioapic->redirtbl[i].bits = s->ioredtbl[i];
103     }
104 
105     ret = kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, &chip);
106     if (ret < 0) {
107         fprintf(stderr, "KVM_GET_IRQCHIP failed: %s\n", strerror(ret));
108         abort();
109     }
110 }
111 
112 static void kvm_ioapic_reset(DeviceState *dev)
113 {
114     IOAPICCommonState *s = DO_UPCAST(IOAPICCommonState, busdev.qdev, dev);
115 
116     ioapic_reset_common(dev);
117     kvm_ioapic_put(s);
118 }
119 
120 static void kvm_ioapic_set_irq(void *opaque, int irq, int level)
121 {
122     KVMIOAPICState *s = opaque;
123     int delivered;
124 
125     delivered = kvm_set_irq(kvm_state, s->kvm_gsi_base + irq, level);
126     apic_report_irq_delivered(delivered);
127 }
128 
129 static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no)
130 {
131     memory_region_init_reservation(&s->io_memory, "kvm-ioapic", 0x1000);
132 
133     qdev_init_gpio_in(&s->busdev.qdev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
134 }
135 
136 static Property kvm_ioapic_properties[] = {
137     DEFINE_PROP_UINT32("gsi_base", KVMIOAPICState, kvm_gsi_base, 0),
138     DEFINE_PROP_END_OF_LIST()
139 };
140 
141 static void kvm_ioapic_class_init(ObjectClass *klass, void *data)
142 {
143     IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
144     DeviceClass *dc = DEVICE_CLASS(klass);
145 
146     k->init      = kvm_ioapic_init;
147     k->pre_save  = kvm_ioapic_get;
148     k->post_load = kvm_ioapic_put;
149     dc->reset    = kvm_ioapic_reset;
150     dc->props    = kvm_ioapic_properties;
151 }
152 
153 static const TypeInfo kvm_ioapic_info = {
154     .name  = "kvm-ioapic",
155     .parent = TYPE_IOAPIC_COMMON,
156     .instance_size = sizeof(KVMIOAPICState),
157     .class_init = kvm_ioapic_class_init,
158 };
159 
160 static void kvm_ioapic_register_types(void)
161 {
162     type_register_static(&kvm_ioapic_info);
163 }
164 
165 type_init(kvm_ioapic_register_types)
166