Merge tag 'sdmmc-20240716' of https://github.com/philmd/qemu into staging
[qemu/armbru.git] / target / i386 / cpu-apic.c
blobd397ec94dc1f765bd5ccdab3bed193e3fad456a1
1 /*
2 * QEMU x86 CPU <-> APIC
4 * Copyright (c) 2003-2004 Fabrice Bellard
6 * SPDX-License-Identifier: MIT
7 */
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 */
27 if (kvm_enabled()) {
28 if (!kvm_irqchip_in_kernel()) {
29 error_setg(errp, "KVM does not support userspace APIC");
30 return NULL;
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);
47 if (!apic_class) {
48 return;
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);
58 apic->cpu = cpu;
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) {
75 return;
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(),
83 apic->apicbase &
84 MSR_IA32_APICBASE_BASE,
85 &apic->io_memory,
86 0x1000);
87 apic_mmio_map_once = true;
91 void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
93 CPUState *cs;
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);
99 if (cs) {
100 cpu_synchronize_state(cs);
102 } else {
103 cs = mon_get_cpu(mon);
107 if (!cs) {
108 monitor_printf(mon, "No CPU available\n");
109 return;
111 x86_cpu_dump_local_apic_state(cs, CPU_DUMP_FPU);