xref: /openbmc/qemu/hw/intc/apic_common.c (revision 7618fffd)
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.1 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 
21 #include "qemu/osdep.h"
22 #include "qemu/error-report.h"
23 #include "qemu/module.h"
24 #include "qapi/error.h"
25 #include "qapi/visitor.h"
26 #include "hw/i386/apic.h"
27 #include "hw/i386/apic_internal.h"
28 #include "hw/intc/kvm_irqcount.h"
29 #include "trace.h"
30 #include "hw/boards.h"
31 #include "sysemu/kvm.h"
32 #include "hw/qdev-properties.h"
33 #include "hw/sysbus.h"
34 #include "migration/vmstate.h"
35 
36 bool apic_report_tpr_access;
37 
38 int cpu_set_apic_base(DeviceState *dev, uint64_t val)
39 {
40     trace_cpu_set_apic_base(val);
41 
42     if (dev) {
43         APICCommonState *s = APIC_COMMON(dev);
44         APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
45         /* Reset possibly modified xAPIC ID */
46         s->id = s->initial_apic_id;
47         return info->set_base(s, val);
48     }
49 
50     return 0;
51 }
52 
53 uint64_t cpu_get_apic_base(DeviceState *dev)
54 {
55     if (dev) {
56         APICCommonState *s = APIC_COMMON(dev);
57         trace_cpu_get_apic_base((uint64_t)s->apicbase);
58         return s->apicbase;
59     } else {
60         trace_cpu_get_apic_base(MSR_IA32_APICBASE_BSP);
61         return MSR_IA32_APICBASE_BSP;
62     }
63 }
64 
65 void cpu_set_apic_tpr(DeviceState *dev, uint8_t val)
66 {
67     APICCommonState *s;
68     APICCommonClass *info;
69 
70     if (!dev) {
71         return;
72     }
73 
74     s = APIC_COMMON(dev);
75     info = APIC_COMMON_GET_CLASS(s);
76 
77     info->set_tpr(s, val);
78 }
79 
80 uint8_t cpu_get_apic_tpr(DeviceState *dev)
81 {
82     APICCommonState *s;
83     APICCommonClass *info;
84 
85     if (!dev) {
86         return 0;
87     }
88 
89     s = APIC_COMMON(dev);
90     info = APIC_COMMON_GET_CLASS(s);
91 
92     return info->get_tpr(s);
93 }
94 
95 void apic_enable_tpr_access_reporting(DeviceState *dev, bool enable)
96 {
97     APICCommonState *s = APIC_COMMON(dev);
98     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
99 
100     apic_report_tpr_access = enable;
101     if (info->enable_tpr_reporting) {
102         info->enable_tpr_reporting(s, enable);
103     }
104 }
105 
106 void apic_enable_vapic(DeviceState *dev, hwaddr paddr)
107 {
108     APICCommonState *s = APIC_COMMON(dev);
109     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
110 
111     s->vapic_paddr = paddr;
112     info->vapic_base_update(s);
113 }
114 
115 void apic_handle_tpr_access_report(DeviceState *dev, target_ulong ip,
116                                    TPRAccess access)
117 {
118     APICCommonState *s = APIC_COMMON(dev);
119 
120     vapic_report_tpr_access(s->vapic, CPU(s->cpu), ip, access);
121 }
122 
123 void apic_deliver_nmi(DeviceState *dev)
124 {
125     APICCommonState *s = APIC_COMMON(dev);
126     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
127 
128     info->external_nmi(s);
129 }
130 
131 bool apic_next_timer(APICCommonState *s, int64_t current_time)
132 {
133     int64_t d;
134 
135     /* We need to store the timer state separately to support APIC
136      * implementations that maintain a non-QEMU timer, e.g. inside the
137      * host kernel. This open-coded state allows us to migrate between
138      * both models. */
139     s->timer_expiry = -1;
140 
141     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED) {
142         return false;
143     }
144 
145     d = (current_time - s->initial_count_load_time) >> s->count_shift;
146 
147     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
148         if (!s->initial_count) {
149             return false;
150         }
151         d = ((d / ((uint64_t)s->initial_count + 1)) + 1) *
152             ((uint64_t)s->initial_count + 1);
153     } else {
154         if (d >= s->initial_count) {
155             return false;
156         }
157         d = (uint64_t)s->initial_count + 1;
158     }
159     s->next_time = s->initial_count_load_time + (d << s->count_shift);
160     s->timer_expiry = s->next_time;
161     return true;
162 }
163 
164 uint32_t apic_get_current_count(APICCommonState *s)
165 {
166     int64_t d;
167     uint32_t val;
168     d = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->initial_count_load_time) >>
169         s->count_shift;
170     if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
171         /* periodic */
172         val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
173     } else {
174         if (d >= s->initial_count) {
175             val = 0;
176         } else {
177             val = s->initial_count - d;
178         }
179     }
180     return val;
181 }
182 
183 void apic_init_reset(DeviceState *dev)
184 {
185     APICCommonState *s;
186     APICCommonClass *info;
187     int i;
188 
189     if (!dev) {
190         return;
191     }
192     s = APIC_COMMON(dev);
193     s->tpr = 0;
194     s->spurious_vec = 0xff;
195     s->log_dest = 0;
196     s->dest_mode = 0xf;
197     memset(s->isr, 0, sizeof(s->isr));
198     memset(s->tmr, 0, sizeof(s->tmr));
199     memset(s->irr, 0, sizeof(s->irr));
200     for (i = 0; i < APIC_LVT_NB; i++) {
201         s->lvt[i] = APIC_LVT_MASKED;
202     }
203     s->esr = 0;
204     memset(s->icr, 0, sizeof(s->icr));
205     s->divide_conf = 0;
206     s->count_shift = 0;
207     s->initial_count = 0;
208     s->initial_count_load_time = 0;
209     s->next_time = 0;
210     s->wait_for_sipi = !cpu_is_bsp(s->cpu);
211 
212     if (s->timer) {
213         timer_del(s->timer);
214     }
215     s->timer_expiry = -1;
216 
217     info = APIC_COMMON_GET_CLASS(s);
218     if (info->reset) {
219         info->reset(s);
220     }
221 }
222 
223 void apic_designate_bsp(DeviceState *dev, bool bsp)
224 {
225     if (dev == NULL) {
226         return;
227     }
228 
229     APICCommonState *s = APIC_COMMON(dev);
230     if (bsp) {
231         s->apicbase |= MSR_IA32_APICBASE_BSP;
232     } else {
233         s->apicbase &= ~MSR_IA32_APICBASE_BSP;
234     }
235 }
236 
237 static void apic_reset_common(DeviceState *dev)
238 {
239     APICCommonState *s = APIC_COMMON(dev);
240     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
241     uint32_t bsp;
242 
243     bsp = s->apicbase & MSR_IA32_APICBASE_BSP;
244     s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
245     s->id = s->initial_apic_id;
246 
247     kvm_reset_irq_delivered();
248 
249     s->vapic_paddr = 0;
250     info->vapic_base_update(s);
251 
252     apic_init_reset(dev);
253 }
254 
255 static const VMStateDescription vmstate_apic_common;
256 
257 static void apic_common_realize(DeviceState *dev, Error **errp)
258 {
259     ERRP_GUARD();
260     APICCommonState *s = APIC_COMMON(dev);
261     APICCommonClass *info;
262     static DeviceState *vapic;
263     uint32_t instance_id = s->initial_apic_id;
264 
265     /* Normally initial APIC ID should be no more than hundreds */
266     assert(instance_id != VMSTATE_INSTANCE_ID_ANY);
267 
268     info = APIC_COMMON_GET_CLASS(s);
269     info->realize(dev, errp);
270     if (*errp) {
271         return;
272     }
273 
274     /* Note: We need at least 1M to map the VAPIC option ROM */
275     if (!vapic && s->vapic_control & VAPIC_ENABLE_MASK &&
276             current_machine->ram_size >= 1024 * 1024) {
277         vapic = sysbus_create_simple("kvmvapic", -1, NULL);
278     }
279     s->vapic = vapic;
280     if (apic_report_tpr_access && info->enable_tpr_reporting) {
281         info->enable_tpr_reporting(s, true);
282     }
283 
284     if (s->legacy_instance_id) {
285         instance_id = VMSTATE_INSTANCE_ID_ANY;
286     }
287     vmstate_register_with_alias_id(NULL, instance_id, &vmstate_apic_common,
288                                    s, -1, 0, NULL);
289 
290     /* APIC LDR in x2APIC mode */
291     s->extended_log_dest = ((s->initial_apic_id >> 4) << 16) |
292                             (1 << (s->initial_apic_id & 0xf));
293 }
294 
295 static void apic_common_unrealize(DeviceState *dev)
296 {
297     APICCommonState *s = APIC_COMMON(dev);
298     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
299 
300     vmstate_unregister(NULL, &vmstate_apic_common, s);
301     info->unrealize(dev);
302 
303     if (apic_report_tpr_access && info->enable_tpr_reporting) {
304         info->enable_tpr_reporting(s, false);
305     }
306 }
307 
308 static int apic_pre_load(void *opaque)
309 {
310     APICCommonState *s = APIC_COMMON(opaque);
311 
312     /* The default is !cpu_is_bsp(s->cpu), but the common value is 0
313      * so that's what apic_common_sipi_needed checks for.  Reset to
314      * the value that is assumed when the apic_sipi subsection is
315      * absent.
316      */
317     s->wait_for_sipi = 0;
318     return 0;
319 }
320 
321 static int apic_dispatch_pre_save(void *opaque)
322 {
323     APICCommonState *s = APIC_COMMON(opaque);
324     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
325 
326     if (info->pre_save) {
327         info->pre_save(s);
328     }
329 
330     return 0;
331 }
332 
333 static int apic_dispatch_post_load(void *opaque, int version_id)
334 {
335     APICCommonState *s = APIC_COMMON(opaque);
336     APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
337 
338     if (info->post_load) {
339         info->post_load(s);
340     }
341     return 0;
342 }
343 
344 static bool apic_common_sipi_needed(void *opaque)
345 {
346     APICCommonState *s = APIC_COMMON(opaque);
347     return s->wait_for_sipi != 0;
348 }
349 
350 static const VMStateDescription vmstate_apic_common_sipi = {
351     .name = "apic_sipi",
352     .version_id = 1,
353     .minimum_version_id = 1,
354     .needed = apic_common_sipi_needed,
355     .fields = (const VMStateField[]) {
356         VMSTATE_INT32(sipi_vector, APICCommonState),
357         VMSTATE_INT32(wait_for_sipi, APICCommonState),
358         VMSTATE_END_OF_LIST()
359     }
360 };
361 
362 static const VMStateDescription vmstate_apic_common = {
363     .name = "apic",
364     .version_id = 3,
365     .minimum_version_id = 3,
366     .pre_load = apic_pre_load,
367     .pre_save = apic_dispatch_pre_save,
368     .post_load = apic_dispatch_post_load,
369     .fields = (const VMStateField[]) {
370         VMSTATE_UINT32(apicbase, APICCommonState),
371         VMSTATE_UINT8(id, APICCommonState),
372         VMSTATE_UINT8(arb_id, APICCommonState),
373         VMSTATE_UINT8(tpr, APICCommonState),
374         VMSTATE_UINT32(spurious_vec, APICCommonState),
375         VMSTATE_UINT8(log_dest, APICCommonState),
376         VMSTATE_UINT8(dest_mode, APICCommonState),
377         VMSTATE_UINT32_ARRAY(isr, APICCommonState, 8),
378         VMSTATE_UINT32_ARRAY(tmr, APICCommonState, 8),
379         VMSTATE_UINT32_ARRAY(irr, APICCommonState, 8),
380         VMSTATE_UINT32_ARRAY(lvt, APICCommonState, APIC_LVT_NB),
381         VMSTATE_UINT32(esr, APICCommonState),
382         VMSTATE_UINT32_ARRAY(icr, APICCommonState, 2),
383         VMSTATE_UINT32(divide_conf, APICCommonState),
384         VMSTATE_INT32(count_shift, APICCommonState),
385         VMSTATE_UINT32(initial_count, APICCommonState),
386         VMSTATE_INT64(initial_count_load_time, APICCommonState),
387         VMSTATE_INT64(next_time, APICCommonState),
388         VMSTATE_INT64(timer_expiry,
389                       APICCommonState), /* open-coded timer state */
390         VMSTATE_END_OF_LIST()
391     },
392     .subsections = (const VMStateDescription * const []) {
393         &vmstate_apic_common_sipi,
394         NULL
395     }
396 };
397 
398 static Property apic_properties_common[] = {
399     DEFINE_PROP_UINT8("version", APICCommonState, version, 0x14),
400     DEFINE_PROP_BIT("vapic", APICCommonState, vapic_control, VAPIC_ENABLE_BIT,
401                     true),
402     DEFINE_PROP_BOOL("legacy-instance-id", APICCommonState, legacy_instance_id,
403                      false),
404     DEFINE_PROP_END_OF_LIST(),
405 };
406 
407 static void apic_common_get_id(Object *obj, Visitor *v, const char *name,
408                                void *opaque, Error **errp)
409 {
410     APICCommonState *s = APIC_COMMON(obj);
411     uint32_t value;
412 
413     value = s->apicbase & MSR_IA32_APICBASE_EXTD ? s->initial_apic_id : s->id;
414     visit_type_uint32(v, name, &value, errp);
415 }
416 
417 static void apic_common_set_id(Object *obj, Visitor *v, const char *name,
418                                void *opaque, Error **errp)
419 {
420     APICCommonState *s = APIC_COMMON(obj);
421     DeviceState *dev = DEVICE(obj);
422     uint32_t value;
423 
424     if (dev->realized) {
425         qdev_prop_set_after_realize(dev, name, errp);
426         return;
427     }
428 
429     if (!visit_type_uint32(v, name, &value, errp)) {
430         return;
431     }
432 
433     if (value >= 255 && !cpu_has_x2apic_feature(&s->cpu->env)) {
434         error_setg(errp, "APIC ID %d requires x2APIC feature in CPU", value);
435         return;
436     }
437 
438     s->initial_apic_id = value;
439     s->id = (uint8_t)value;
440 }
441 
442 static void apic_common_initfn(Object *obj)
443 {
444     APICCommonState *s = APIC_COMMON(obj);
445 
446     s->id = s->initial_apic_id = -1;
447     object_property_add(obj, "id", "uint32",
448                         apic_common_get_id,
449                         apic_common_set_id, NULL, NULL);
450 }
451 
452 static void apic_common_class_init(ObjectClass *klass, void *data)
453 {
454     DeviceClass *dc = DEVICE_CLASS(klass);
455 
456     dc->reset = apic_reset_common;
457     device_class_set_props(dc, apic_properties_common);
458     dc->realize = apic_common_realize;
459     dc->unrealize = apic_common_unrealize;
460     /*
461      * Reason: APIC and CPU need to be wired up by
462      * x86_cpu_apic_create()
463      */
464     dc->user_creatable = false;
465 }
466 
467 static const TypeInfo apic_common_type = {
468     .name = TYPE_APIC_COMMON,
469     .parent = TYPE_DEVICE,
470     .instance_size = sizeof(APICCommonState),
471     .instance_init = apic_common_initfn,
472     .class_size = sizeof(APICCommonClass),
473     .class_init = apic_common_class_init,
474     .abstract = true,
475 };
476 
477 static void apic_common_register_types(void)
478 {
479     type_register_static(&apic_common_type);
480 }
481 
482 type_init(apic_common_register_types)
483