2 * QEMU x86 CPU <-> APIC
4 * Copyright (c) 2003-2004 Fabrice Bellard
6 * SPDX-License-Identifier: MIT
9 #include "qemu/osdep.h"
10 #include "qapi/qmp/qdict.h"
11 #include "qapi/error.h"
12 #include "monitor/monitor.h"
13 #include "monitor/hmp-target.h"
14 #include "sysemu/hw_accel.h"
15 #include "sysemu/kvm.h"
16 #include "sysemu/xen.h"
17 #include "exec/address-spaces.h"
18 #include "hw/qdev-properties.h"
19 #include "hw/i386/apic_internal.h"
20 #include "cpu-internal.h"
22 APICCommonClass
*apic_get_class(Error
**errp
)
24 const char *apic_type
= "apic";
26 /* TODO: in-kernel irqchip for hvf */
28 if (!kvm_irqchip_in_kernel()) {
29 error_setg(errp
, "KVM does not support userspace APIC");
32 apic_type
= "kvm-apic";
33 } else if (xen_enabled()) {
34 apic_type
= "xen-apic";
35 } else if (whpx_apic_in_platform()) {
36 apic_type
= "whpx-apic";
39 return APIC_COMMON_CLASS(object_class_by_name(apic_type
));
42 void x86_cpu_apic_create(X86CPU
*cpu
, Error
**errp
)
44 APICCommonState
*apic
;
45 APICCommonClass
*apic_class
= apic_get_class(errp
);
51 cpu
->apic_state
= DEVICE(object_new_with_class(OBJECT_CLASS(apic_class
)));
52 object_property_add_child(OBJECT(cpu
), "lapic",
53 OBJECT(cpu
->apic_state
));
54 object_unref(OBJECT(cpu
->apic_state
));
56 /* TODO: convert to link<> */
57 apic
= APIC_COMMON(cpu
->apic_state
);
59 apic
->apicbase
= APIC_DEFAULT_ADDRESS
| MSR_IA32_APICBASE_ENABLE
;
62 * apic_common_set_id needs to check if the CPU has x2APIC
63 * feature in case APIC ID >= 255, so we need to set apic->cpu
64 * before setting APIC ID
66 qdev_prop_set_uint32(cpu
->apic_state
, "id", cpu
->apic_id
);
69 void x86_cpu_apic_realize(X86CPU
*cpu
, Error
**errp
)
71 APICCommonState
*apic
;
72 static bool apic_mmio_map_once
;
74 if (cpu
->apic_state
== NULL
) {
77 qdev_realize(DEVICE(cpu
->apic_state
), NULL
, errp
);
79 /* Map APIC MMIO area */
80 apic
= APIC_COMMON(cpu
->apic_state
);
81 if (!apic_mmio_map_once
) {
82 memory_region_add_subregion_overlap(get_system_memory(),
84 MSR_IA32_APICBASE_BASE
,
87 apic_mmio_map_once
= true;
91 void hmp_info_local_apic(Monitor
*mon
, const QDict
*qdict
)
95 if (qdict_haskey(qdict
, "apic-id")) {
96 int id
= qdict_get_try_int(qdict
, "apic-id", 0);
98 cs
= cpu_by_arch_id(id
);
100 cpu_synchronize_state(cs
);
103 cs
= mon_get_cpu(mon
);
108 monitor_printf(mon
, "No CPU available\n");
111 x86_cpu_dump_local_apic_state(cs
, CPU_DUMP_FPU
);