1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#include "qemu/osdep.h"
24#include "qapi/error.h"
25
26#include "exec/memory.h"
27#include "hw/acpi/acpi.h"
28#include "hw/acpi/aml-build.h"
29#include "hw/acpi/utils.h"
30#include "hw/i386/pc.h"
31#include "target/i386/cpu.h"
32
33#include "acpi-build.h"
34#include "acpi-common.h"
35
36void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
37 const CPUArchIdList *apic_ids, GArray *entry,
38 bool force_enabled)
39{
40 uint32_t apic_id = apic_ids->cpus[uid].arch_id;
41
42 uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
43 1 : 0;
44
45
46
47
48
49
50
51 if (apic_id < 255) {
52
53 build_append_int_noprefix(entry, 0, 1);
54 build_append_int_noprefix(entry, 8, 1);
55 build_append_int_noprefix(entry, uid, 1);
56 build_append_int_noprefix(entry, apic_id, 1);
57 build_append_int_noprefix(entry, flags, 4);
58 } else {
59
60 build_append_int_noprefix(entry, 9, 1);
61 build_append_int_noprefix(entry, 16, 1);
62 build_append_int_noprefix(entry, 0, 2);
63 build_append_int_noprefix(entry, apic_id, 4);
64 build_append_int_noprefix(entry, flags, 4);
65 build_append_int_noprefix(entry, uid, 4);
66 }
67}
68
69static void build_ioapic(GArray *entry, uint8_t id, uint32_t addr, uint32_t irq)
70{
71
72 build_append_int_noprefix(entry, 1, 1);
73 build_append_int_noprefix(entry, 12, 1);
74 build_append_int_noprefix(entry, id, 1);
75 build_append_int_noprefix(entry, 0, 1);
76 build_append_int_noprefix(entry, addr, 4);
77 build_append_int_noprefix(entry, irq, 4);
78}
79
80static void
81build_xrupt_override(GArray *entry, uint8_t src, uint32_t gsi, uint16_t flags)
82{
83
84 build_append_int_noprefix(entry, 2, 1);
85 build_append_int_noprefix(entry, 10, 1);
86 build_append_int_noprefix(entry, 0, 1);
87 build_append_int_noprefix(entry, src, 1);
88
89 build_append_int_noprefix(entry, gsi, 4);
90 build_append_int_noprefix(entry, flags, 2);
91}
92
93
94
95
96
97void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
98 X86MachineState *x86ms, AcpiDeviceIf *adev,
99 const char *oem_id, const char *oem_table_id)
100{
101 int i;
102 bool x2apic_mode = false;
103 MachineClass *mc = MACHINE_GET_CLASS(x86ms);
104 const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
105 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
106 AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
107 .oem_table_id = oem_table_id };
108
109 acpi_table_begin(&table, table_data);
110
111 build_append_int_noprefix(table_data, APIC_DEFAULT_ADDRESS, 4);
112 build_append_int_noprefix(table_data, 1 , 4);
113
114 for (i = 0; i < apic_ids->len; i++) {
115 adevc->madt_cpu(adev, i, apic_ids, table_data, false);
116 if (apic_ids->cpus[i].arch_id > 254) {
117 x2apic_mode = true;
118 }
119 }
120
121 build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID, IO_APIC_DEFAULT_ADDRESS, 0);
122 if (x86ms->ioapic2) {
123 build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID + 1,
124 IO_APIC_SECONDARY_ADDRESS, IO_APIC_SECONDARY_IRQBASE);
125 }
126
127 if (x86ms->apic_xrupt_override) {
128 build_xrupt_override(table_data, 0, 2,
129 0 );
130 }
131
132 for (i = 1; i < 16; i++) {
133 if (!(x86ms->pci_irq_mask & (1 << i))) {
134
135 continue;
136 }
137 build_xrupt_override(table_data, i, i,
138 0xd );
139 }
140
141 if (x2apic_mode) {
142
143 build_append_int_noprefix(table_data, 0xA, 1);
144 build_append_int_noprefix(table_data, 12, 1);
145 build_append_int_noprefix(table_data, 0, 2);
146
147 build_append_int_noprefix(table_data, 0xFFFFFFFF ,
148 4);
149
150 build_append_int_noprefix(table_data, 1 , 1);
151 build_append_int_noprefix(table_data, 0, 3);
152 } else {
153
154 build_append_int_noprefix(table_data, 4, 1);
155 build_append_int_noprefix(table_data, 6, 1);
156
157 build_append_int_noprefix(table_data, 0xFF , 1);
158 build_append_int_noprefix(table_data, 0, 2);
159
160 build_append_int_noprefix(table_data, 1 , 1);
161 }
162
163 acpi_table_end(linker, &table);
164}
165
166