xref: /openbmc/qemu/hw/intc/apic_common.c (revision fee5b753)
1 /*
2  *  APIC support - common bits of emulated and KVM kernel model
3  *
4  *  Copyright (c) 2004-2005 Fabrice Bellard
5  *  Copyright (c) 2011      Jan Kiszka, Siemens AG
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, see <http://www.gnu.org/licenses/>
19  */
20 #include "qemu/osdep.h"
21 #include "hw/i386/apic.h"
22 #include "hw/i386/apic_internal.h"
23 #include "trace.h"
24 #include "sysemu/kvm.h"
25 #include "hw/qdev.h"
26 #include "hw/sysbus.h"
27 
28 static int apic_irq_delivered;
29 bool apic_report_tpr_access;
30 
31 void cpu_set_apic_base(DeviceState *dev, uint64_t val)
32 {
33     trace_cpu_set_apic_base(val);
34 
35     if (dev) {
36         APICCommonState *s = APIC_COMMON(dev);
37         APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
38         info->set_base(s, val);
39     }
40 }
41 
42 uint64_t cpu_get_apic_base(DeviceState *dev)
43 {
44     if (dev) {
45         APICCommonState *s = APIC_COMMON(dev);
46         trace_cpu_get_apic_base((uint64_t)s->apicbase);
47         return s->apicbase;
48     } else {
49         trace_cpu_get_apic_base(MSR_IA32_APICBASE_BSP);
50         return MSR_IA32_APICBASE_BSP;
51     }
52 }
53 
54 void cpu_set_apic_tpr(DeviceState *dev, uint8_t val)
55 {
56     APICCommonState *s;
57     APICCommonClass *info;
58 
59     if (!dev) {
60         return;
61     }
62 
63     s = APIC_COMMON(dev);
64     info = APIC_COMMON_GET_CLASS(s);
65 
66     info->set_tpr(s, val);
67 }
68 
69 uint8_t cpu_get_apic_tpr(DeviceState *dev)
70 {
71     APICCommonState *s;
72     APICCommonClass *info;
73 
74     if (!dev) {
75         return 0;
76     }
77 
78     s = APIC_COMMON(dev);
79     info = APIC_COMMON_GET_CLASS(s);
80 
81     return info->get_tpr(s);
82 }
83 
84 void apic_enable_tpr_access_reporting(DeviceState *dev, bool enable)
85 {
86     APICCommonState *s = APIC_COMMON(dev);
87     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
88 
89     apic_report_tpr_access = enable;
90     if (info->enable_tpr_reporting) {
91         info->enable_tpr_reporting(s, enable);
92     }
93 }
94 
95 void apic_enable_vapic(DeviceState *dev, hwaddr paddr)
96 {
97     APICCommonState *s = APIC_COMMON(dev);
98     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
99 
100     s->vapic_paddr = paddr;
101     info->vapic_base_update(s);
102 }
103 
104 void apic_handle_tpr_access_report(DeviceState *dev, target_ulong ip,
105                                    TPRAccess access)
106 {
107     APICCommonState *s = APIC_COMMON(dev);
108 
109     vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access);
110 }
111 
112 void apic_report_irq_delivered(int delivered)
113 {
114     apic_irq_delivered += delivered;
115 
116     trace_apic_report_irq_delivered(apic_irq_delivered);
117 }
118 
119 void apic_reset_irq_delivered(void)
120 {
121     /* Copy this into a local variable to encourage gcc to emit a plain
122      * register for a sys/sdt.h marker.  For details on this workaround, see:
123      * https://sourceware.org/bugzilla/show_bug.cgi?id=13296
124      */
125     volatile int a_i_d = apic_irq_delivered;
126     trace_apic_reset_irq_delivered(a_i_d);
127 
128     apic_irq_delivered = 0;
129 }
130 
131 int apic_get_irq_delivered(void)
132 {
133     trace_apic_get_irq_delivered(apic_irq_delivered);
134 
135     return apic_irq_delivered;
136 }
137 
138 void apic_deliver_nmi(DeviceState *dev)
139 {
140     APICCommonState *s = APIC_COMMON(dev);
141     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
142 
143     info->external_nmi(s);
144 }
145 
146 bool apic_next_timer(APICCommonState *s, int64_t current_time)
147 {
148     int64_t d;
149 
150     /* We need to store the timer state separately to support APIC
151      * implementations that maintain a non-QEMU timer, e.g. inside the
152      * host kernel. This open-coded state allows us to migrate between
153      * both models. */
154     s->timer_expiry = -1;
155 
156     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED) {
157         return false;
158     }
159 
160     d = (current_time - s->initial_count_load_time) >> s->count_shift;
161 
162     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
163         if (!s->initial_count) {
164             return false;
165         }
166         d = ((d / ((uint64_t)s->initial_count + 1)) + 1) *
167             ((uint64_t)s->initial_count + 1);
168     } else {
169         if (d >= s->initial_count) {
170             return false;
171         }
172         d = (uint64_t)s->initial_count + 1;
173     }
174     s->next_time = s->initial_count_load_time + (d << s->count_shift);
175     s->timer_expiry = s->next_time;
176     return true;
177 }
178 
179 void apic_init_reset(DeviceState *dev)
180 {
181     APICCommonState *s;
182     APICCommonClass *info;
183     int i;
184 
185     if (!dev) {
186         return;
187     }
188     s = APIC_COMMON(dev);
189     s->tpr = 0;
190     s->spurious_vec = 0xff;
191     s->log_dest = 0;
192     s->dest_mode = 0xf;
193     memset(s->isr, 0, sizeof(s->isr));
194     memset(s->tmr, 0, sizeof(s->tmr));
195     memset(s->irr, 0, sizeof(s->irr));
196     for (i = 0; i < APIC_LVT_NB; i++) {
197         s->lvt[i] = APIC_LVT_MASKED;
198     }
199     s->esr = 0;
200     memset(s->icr, 0, sizeof(s->icr));
201     s->divide_conf = 0;
202     s->count_shift = 0;
203     s->initial_count = 0;
204     s->initial_count_load_time = 0;
205     s->next_time = 0;
206     s->wait_for_sipi = !cpu_is_bsp(s->cpu);
207 
208     if (s->timer) {
209         timer_del(s->timer);
210     }
211     s->timer_expiry = -1;
212 
213     info = APIC_COMMON_GET_CLASS(s);
214     if (info->reset) {
215         info->reset(s);
216     }
217 }
218 
219 void apic_designate_bsp(DeviceState *dev, bool bsp)
220 {
221     if (dev == NULL) {
222         return;
223     }
224 
225     APICCommonState *s = APIC_COMMON(dev);
226     if (bsp) {
227         s->apicbase |= MSR_IA32_APICBASE_BSP;
228     } else {
229         s->apicbase &= ~MSR_IA32_APICBASE_BSP;
230     }
231 }
232 
233 static void apic_reset_common(DeviceState *dev)
234 {
235     APICCommonState *s = APIC_COMMON(dev);
236     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
237     uint32_t bsp;
238 
239     bsp = s->apicbase & MSR_IA32_APICBASE_BSP;
240     s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
241 
242     s->vapic_paddr = 0;
243     info->vapic_base_update(s);
244 
245     apic_init_reset(dev);
246 }
247 
248 /* This function is only used for old state version 1 and 2 */
249 static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
250 {
251     APICCommonState *s = opaque;
252     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
253     int i;
254 
255     if (version_id > 2) {
256         return -EINVAL;
257     }
258 
259     /* XXX: what if the base changes? (registered memory regions) */
260     qemu_get_be32s(f, &s->apicbase);
261     qemu_get_8s(f, &s->id);
262     qemu_get_8s(f, &s->arb_id);
263     qemu_get_8s(f, &s->tpr);
264     qemu_get_be32s(f, &s->spurious_vec);
265     qemu_get_8s(f, &s->log_dest);
266     qemu_get_8s(f, &s->dest_mode);
267     for (i = 0; i < 8; i++) {
268         qemu_get_be32s(f, &s->isr[i]);
269         qemu_get_be32s(f, &s->tmr[i]);
270         qemu_get_be32s(f, &s->irr[i]);
271     }
272     for (i = 0; i < APIC_LVT_NB; i++) {
273         qemu_get_be32s(f, &s->lvt[i]);
274     }
275     qemu_get_be32s(f, &s->esr);
276     qemu_get_be32s(f, &s->icr[0]);
277     qemu_get_be32s(f, &s->icr[1]);
278     qemu_get_be32s(f, &s->divide_conf);
279     s->count_shift = qemu_get_be32(f);
280     qemu_get_be32s(f, &s->initial_count);
281     s->initial_count_load_time = qemu_get_be64(f);
282     s->next_time = qemu_get_be64(f);
283 
284     if (version_id >= 2) {
285         s->timer_expiry = qemu_get_be64(f);
286     }
287 
288     if (info->post_load) {
289         info->post_load(s);
290     }
291     return 0;
292 }
293 
294 static void apic_common_realize(DeviceState *dev, Error **errp)
295 {
296     APICCommonState *s = APIC_COMMON(dev);
297     APICCommonClass *info;
298     static DeviceState *vapic;
299     static int apic_no;
300 
301     if (apic_no >= MAX_APICS) {
302         error_setg(errp, "%s initialization failed.",
303                    object_get_typename(OBJECT(dev)));
304         return;
305     }
306     s->idx = apic_no++;
307 
308     info = APIC_COMMON_GET_CLASS(s);
309     info->realize(dev, errp);
310 
311     /* Note: We need at least 1M to map the VAPIC option ROM */
312     if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
313         ram_size >= 1024 * 1024) {
314         vapic = sysbus_create_simple("kvmvapic", -1, NULL);
315     }
316     s->vapic = vapic;
317     if (apic_report_tpr_access && info->enable_tpr_reporting) {
318         info->enable_tpr_reporting(s, true);
319     }
320 
321 }
322 
323 static int apic_pre_load(void *opaque)
324 {
325     APICCommonState *s = APIC_COMMON(opaque);
326 
327     /* The default is !cpu_is_bsp(s->cpu), but the common value is 0
328      * so that's what apic_common_sipi_needed checks for.  Reset to
329      * the value that is assumed when the apic_sipi subsection is
330      * absent.
331      */
332     s->wait_for_sipi = 0;
333     return 0;
334 }
335 
336 static void apic_dispatch_pre_save(void *opaque)
337 {
338     APICCommonState *s = APIC_COMMON(opaque);
339     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
340 
341     if (info->pre_save) {
342         info->pre_save(s);
343     }
344 }
345 
346 static int apic_dispatch_post_load(void *opaque, int version_id)
347 {
348     APICCommonState *s = APIC_COMMON(opaque);
349     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
350 
351     if (info->post_load) {
352         info->post_load(s);
353     }
354     return 0;
355 }
356 
357 static bool apic_common_sipi_needed(void *opaque)
358 {
359     APICCommonState *s = APIC_COMMON(opaque);
360     return s->wait_for_sipi != 0;
361 }
362 
363 static const VMStateDescription vmstate_apic_common_sipi = {
364     .name = "apic_sipi",
365     .version_id = 1,
366     .minimum_version_id = 1,
367     .needed = apic_common_sipi_needed,
368     .fields = (VMStateField[]) {
369         VMSTATE_INT32(sipi_vector, APICCommonState),
370         VMSTATE_INT32(wait_for_sipi, APICCommonState),
371         VMSTATE_END_OF_LIST()
372     }
373 };
374 
375 static const VMStateDescription vmstate_apic_common = {
376     .name = "apic",
377     .version_id = 3,
378     .minimum_version_id = 3,
379     .minimum_version_id_old = 1,
380     .load_state_old = apic_load_old,
381     .pre_load = apic_pre_load,
382     .pre_save = apic_dispatch_pre_save,
383     .post_load = apic_dispatch_post_load,
384     .fields = (VMStateField[]) {
385         VMSTATE_UINT32(apicbase, APICCommonState),
386         VMSTATE_UINT8(id, APICCommonState),
387         VMSTATE_UINT8(arb_id, APICCommonState),
388         VMSTATE_UINT8(tpr, APICCommonState),
389         VMSTATE_UINT32(spurious_vec, APICCommonState),
390         VMSTATE_UINT8(log_dest, APICCommonState),
391         VMSTATE_UINT8(dest_mode, APICCommonState),
392         VMSTATE_UINT32_ARRAY(isr, APICCommonState, 8),
393         VMSTATE_UINT32_ARRAY(tmr, APICCommonState, 8),
394         VMSTATE_UINT32_ARRAY(irr, APICCommonState, 8),
395         VMSTATE_UINT32_ARRAY(lvt, APICCommonState, APIC_LVT_NB),
396         VMSTATE_UINT32(esr, APICCommonState),
397         VMSTATE_UINT32_ARRAY(icr, APICCommonState, 2),
398         VMSTATE_UINT32(divide_conf, APICCommonState),
399         VMSTATE_INT32(count_shift, APICCommonState),
400         VMSTATE_UINT32(initial_count, APICCommonState),
401         VMSTATE_INT64(initial_count_load_time, APICCommonState),
402         VMSTATE_INT64(next_time, APICCommonState),
403         VMSTATE_INT64(timer_expiry,
404                       APICCommonState), /* open-coded timer state */
405         VMSTATE_END_OF_LIST()
406     },
407     .subsections = (const VMStateDescription*[]) {
408         &vmstate_apic_common_sipi,
409         NULL
410     }
411 };
412 
413 static Property apic_properties_common[] = {
414     DEFINE_PROP_UINT8("id", APICCommonState, id, -1),
415     DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14),
416     DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
417                     true),
418     DEFINE_PROP_END_OF_LIST(),
419 };
420 
421 static void apic_common_class_init(ObjectClass *klass, void *data)
422 {
423     DeviceClass *dc = DEVICE_CLASS(klass);
424 
425     dc->vmsd = &vmstate_apic_common;
426     dc->reset = apic_reset_common;
427     dc->props = apic_properties_common;
428     dc->realize = apic_common_realize;
429     /*
430      * Reason: APIC and CPU need to be wired up by
431      * x86_cpu_apic_create()
432      */
433     dc->cannot_instantiate_with_device_add_yet = true;
434 }
435 
436 static const TypeInfo apic_common_type = {
437     .name = TYPE_APIC_COMMON,
438     .parent = TYPE_DEVICE,
439     .instance_size = sizeof(APICCommonState),
440     .class_size = sizeof(APICCommonClass),
441     .class_init = apic_common_class_init,
442     .abstract = true,
443 };
444 
445 static void apic_common_register_types(void)
446 {
447     type_register_static(&apic_common_type);
448 }
449 
450 type_init(apic_common_register_types)
451