]> Git Repo - qemu.git/blame - hw/i386/acpi-build.c
piix4: add acpi pci hotplug support
[qemu.git] / hw / i386 / acpi-build.c
CommitLineData
72c194f7
MT
1/* Support for generating ACPI tables and passing them to Guests
2 *
3 * Copyright (C) 2008-2010 Kevin O'Connor <[email protected]>
4 * Copyright (C) 2006 Fabrice Bellard
5 * Copyright (C) 2013 Red Hat Inc
6 *
7 * Author: Michael S. Tsirkin <[email protected]>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include "acpi-build.h"
24#include <stddef.h>
25#include <glib.h>
26#include "qemu-common.h"
27#include "qemu/bitmap.h"
28#include "qemu/range.h"
29#include "hw/pci/pci.h"
30#include "qom/cpu.h"
31#include "hw/i386/pc.h"
32#include "target-i386/cpu.h"
33#include "hw/timer/hpet.h"
34#include "hw/i386/acpi-defs.h"
35#include "hw/acpi/acpi.h"
36#include "hw/nvram/fw_cfg.h"
37#include "bios-linker-loader.h"
38#include "hw/loader.h"
15bce1b7 39#include "hw/isa/isa.h"
72c194f7
MT
40
41/* Supported chipsets: */
42#include "hw/acpi/piix4.h"
43#include "hw/i386/ich9.h"
44#include "hw/pci/pci_bus.h"
45#include "hw/pci-host/q35.h"
46
47#include "hw/i386/q35-acpi-dsdt.hex"
48#include "hw/i386/acpi-dsdt.hex"
49
50#include "qapi/qmp/qint.h"
51#include "qom/qom-qobject.h"
52
53typedef struct AcpiCpuInfo {
54 DECLARE_BITMAP(found_cpus, MAX_CPUMASK_BITS + 1);
55} AcpiCpuInfo;
56
57typedef struct AcpiMcfgInfo {
58 uint64_t mcfg_base;
59 uint32_t mcfg_size;
60} AcpiMcfgInfo;
61
62typedef struct AcpiPmInfo {
63 bool s3_disabled;
64 bool s4_disabled;
65 uint8_t s4_val;
66 uint16_t sci_int;
67 uint8_t acpi_enable_cmd;
68 uint8_t acpi_disable_cmd;
69 uint32_t gpe0_blk;
70 uint32_t gpe0_blk_len;
71 uint32_t io_base;
72} AcpiPmInfo;
73
74typedef struct AcpiMiscInfo {
75 bool has_hpet;
76 DECLARE_BITMAP(slot_hotplug_enable, PCI_SLOT_MAX);
77 const unsigned char *dsdt_code;
78 unsigned dsdt_size;
79 uint16_t pvpanic_port;
80} AcpiMiscInfo;
81
82static void acpi_get_dsdt(AcpiMiscInfo *info)
83{
8977557a 84 uint16_t *applesmc_sta;
72c194f7
MT
85 Object *piix = piix4_pm_find();
86 Object *lpc = ich9_lpc_find();
87 assert(!!piix != !!lpc);
88
89 if (piix) {
90 info->dsdt_code = AcpiDsdtAmlCode;
91 info->dsdt_size = sizeof AcpiDsdtAmlCode;
8977557a 92 applesmc_sta = piix_dsdt_applesmc_sta;
72c194f7
MT
93 }
94 if (lpc) {
95 info->dsdt_code = Q35AcpiDsdtAmlCode;
96 info->dsdt_size = sizeof Q35AcpiDsdtAmlCode;
8977557a 97 applesmc_sta = q35_dsdt_applesmc_sta;
72c194f7 98 }
15bce1b7
GS
99
100 /* Patch in appropriate value for AppleSMC _STA */
8977557a
GS
101 *(uint8_t *)(info->dsdt_code + *applesmc_sta) =
102 applesmc_find() ? 0x0b : 0x00;
72c194f7
MT
103}
104
105static
106int acpi_add_cpu_info(Object *o, void *opaque)
107{
108 AcpiCpuInfo *cpu = opaque;
109 uint64_t apic_id;
110
111 if (object_dynamic_cast(o, TYPE_CPU)) {
112 apic_id = object_property_get_int(o, "apic-id", NULL);
113 assert(apic_id <= MAX_CPUMASK_BITS);
114
115 set_bit(apic_id, cpu->found_cpus);
116 }
117
118 object_child_foreach(o, acpi_add_cpu_info, opaque);
119 return 0;
120}
121
122static void acpi_get_cpu_info(AcpiCpuInfo *cpu)
123{
124 Object *root = object_get_root();
125
126 memset(cpu->found_cpus, 0, sizeof cpu->found_cpus);
127 object_child_foreach(root, acpi_add_cpu_info, cpu);
128}
129
130static void acpi_get_pm_info(AcpiPmInfo *pm)
131{
132 Object *piix = piix4_pm_find();
133 Object *lpc = ich9_lpc_find();
134 Object *obj = NULL;
135 QObject *o;
136
137 if (piix) {
138 obj = piix;
139 }
140 if (lpc) {
141 obj = lpc;
142 }
143 assert(obj);
144
145 /* Fill in optional s3/s4 related properties */
146 o = object_property_get_qobject(obj, ACPI_PM_PROP_S3_DISABLED, NULL);
147 if (o) {
148 pm->s3_disabled = qint_get_int(qobject_to_qint(o));
149 } else {
150 pm->s3_disabled = false;
151 }
152 o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_DISABLED, NULL);
153 if (o) {
154 pm->s4_disabled = qint_get_int(qobject_to_qint(o));
155 } else {
156 pm->s4_disabled = false;
157 }
158 o = object_property_get_qobject(obj, ACPI_PM_PROP_S4_VAL, NULL);
159 if (o) {
160 pm->s4_val = qint_get_int(qobject_to_qint(o));
161 } else {
162 pm->s4_val = false;
163 }
164
165 /* Fill in mandatory properties */
166 pm->sci_int = object_property_get_int(obj, ACPI_PM_PROP_SCI_INT, NULL);
167
168 pm->acpi_enable_cmd = object_property_get_int(obj,
169 ACPI_PM_PROP_ACPI_ENABLE_CMD,
170 NULL);
171 pm->acpi_disable_cmd = object_property_get_int(obj,
172 ACPI_PM_PROP_ACPI_DISABLE_CMD,
173 NULL);
174 pm->io_base = object_property_get_int(obj, ACPI_PM_PROP_PM_IO_BASE,
175 NULL);
176 pm->gpe0_blk = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK,
177 NULL);
178 pm->gpe0_blk_len = object_property_get_int(obj, ACPI_PM_PROP_GPE0_BLK_LEN,
179 NULL);
180}
181
182static void acpi_get_hotplug_info(AcpiMiscInfo *misc)
183{
184 int i;
185 PCIBus *bus = find_i440fx();
186
187 if (!bus) {
188 /* Only PIIX supports ACPI hotplug */
189 memset(misc->slot_hotplug_enable, 0, sizeof misc->slot_hotplug_enable);
190 return;
191 }
192
193 memset(misc->slot_hotplug_enable, 0xff,
194 DIV_ROUND_UP(PCI_SLOT_MAX, BITS_PER_BYTE));
195
196 for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
197 PCIDeviceClass *pc;
198 PCIDevice *pdev = bus->devices[i];
199
200 if (!pdev) {
201 continue;
202 }
203
204 pc = PCI_DEVICE_GET_CLASS(pdev);
205
206 if (pc->no_hotplug) {
207 int slot = PCI_SLOT(i);
208
209 clear_bit(slot, misc->slot_hotplug_enable);
210 }
211 }
212}
213
214static void acpi_get_misc_info(AcpiMiscInfo *info)
215{
216 info->has_hpet = hpet_find();
217 info->pvpanic_port = pvpanic_port();
218}
219
220static void acpi_get_pci_info(PcPciInfo *info)
221{
222 Object *pci_host;
223 bool ambiguous;
224
225 pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
226 g_assert(!ambiguous);
227 g_assert(pci_host);
228
229 info->w32.begin = object_property_get_int(pci_host,
230 PCI_HOST_PROP_PCI_HOLE_START,
231 NULL);
232 info->w32.end = object_property_get_int(pci_host,
233 PCI_HOST_PROP_PCI_HOLE_END,
234 NULL);
235 info->w64.begin = object_property_get_int(pci_host,
236 PCI_HOST_PROP_PCI_HOLE64_START,
237 NULL);
238 info->w64.end = object_property_get_int(pci_host,
239 PCI_HOST_PROP_PCI_HOLE64_END,
240 NULL);
241}
242
243#define ACPI_BUILD_APPNAME "Bochs"
244#define ACPI_BUILD_APPNAME6 "BOCHS "
245#define ACPI_BUILD_APPNAME4 "BXPC"
246
247#define ACPI_BUILD_DPRINTF(level, fmt, ...) do {} while (0)
248
249#define ACPI_BUILD_TABLE_FILE "etc/acpi/tables"
250#define ACPI_BUILD_RSDP_FILE "etc/acpi/rsdp"
251
252static void
253build_header(GArray *linker, GArray *table_data,
254 AcpiTableHeader *h, uint32_t sig, int len, uint8_t rev)
255{
256 h->signature = cpu_to_le32(sig);
257 h->length = cpu_to_le32(len);
258 h->revision = rev;
259 memcpy(h->oem_id, ACPI_BUILD_APPNAME6, 6);
260 memcpy(h->oem_table_id, ACPI_BUILD_APPNAME4, 4);
261 memcpy(h->oem_table_id + 4, (void *)&sig, 4);
262 h->oem_revision = cpu_to_le32(1);
263 memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
264 h->asl_compiler_revision = cpu_to_le32(1);
265 h->checksum = 0;
266 /* Checksum to be filled in by Guest linker */
267 bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
268 table_data->data, h, len, &h->checksum);
269}
270
271static inline GArray *build_alloc_array(void)
272{
273 return g_array_new(false, true /* clear */, 1);
274}
275
276static inline void build_free_array(GArray *array)
277{
278 g_array_free(array, true);
279}
280
281static inline void build_prepend_byte(GArray *array, uint8_t val)
282{
283 g_array_prepend_val(array, val);
284}
285
286static inline void build_append_byte(GArray *array, uint8_t val)
287{
288 g_array_append_val(array, val);
289}
290
291static inline void build_append_array(GArray *array, GArray *val)
292{
293 g_array_append_vals(array, val->data, val->len);
294}
295
867d898c
SW
296static void GCC_FMT_ATTR(2, 3)
297build_append_nameseg(GArray *array, const char *format, ...)
72c194f7 298{
542da88f
MT
299 /* It would be nicer to use g_string_vprintf but it's only there in 2.22 */
300 char s[] = "XXXX";
301 int len;
72c194f7
MT
302 va_list args;
303
304 va_start(args, format);
542da88f 305 len = vsnprintf(s, sizeof s, format, args);
72c194f7
MT
306 va_end(args);
307
542da88f
MT
308 assert(len == 4);
309 g_array_append_vals(array, s, len);
72c194f7
MT
310}
311
312/* 5.4 Definition Block Encoding */
313enum {
314 PACKAGE_LENGTH_1BYTE_SHIFT = 6, /* Up to 63 - use extra 2 bits. */
315 PACKAGE_LENGTH_2BYTE_SHIFT = 4,
316 PACKAGE_LENGTH_3BYTE_SHIFT = 12,
317 PACKAGE_LENGTH_4BYTE_SHIFT = 20,
318};
319
320static void build_prepend_package_length(GArray *package, unsigned min_bytes)
321{
322 uint8_t byte;
323 unsigned length = package->len;
324 unsigned length_bytes;
325
326 if (length + 1 < (1 << PACKAGE_LENGTH_1BYTE_SHIFT)) {
327 length_bytes = 1;
328 } else if (length + 2 < (1 << PACKAGE_LENGTH_3BYTE_SHIFT)) {
329 length_bytes = 2;
330 } else if (length + 3 < (1 << PACKAGE_LENGTH_4BYTE_SHIFT)) {
331 length_bytes = 3;
332 } else {
333 length_bytes = 4;
334 }
335
336 /* Force length to at least min_bytes.
337 * This wastes memory but that's how bios did it.
338 */
339 length_bytes = MAX(length_bytes, min_bytes);
340
341 /* PkgLength is the length of the inclusive length of the data. */
342 length += length_bytes;
343
344 switch (length_bytes) {
345 case 1:
346 byte = length;
347 build_prepend_byte(package, byte);
348 return;
349 case 4:
350 byte = length >> PACKAGE_LENGTH_4BYTE_SHIFT;
351 build_prepend_byte(package, byte);
352 length &= (1 << PACKAGE_LENGTH_4BYTE_SHIFT) - 1;
353 /* fall through */
354 case 3:
355 byte = length >> PACKAGE_LENGTH_3BYTE_SHIFT;
356 build_prepend_byte(package, byte);
357 length &= (1 << PACKAGE_LENGTH_3BYTE_SHIFT) - 1;
358 /* fall through */
359 case 2:
360 byte = length >> PACKAGE_LENGTH_2BYTE_SHIFT;
361 build_prepend_byte(package, byte);
362 length &= (1 << PACKAGE_LENGTH_2BYTE_SHIFT) - 1;
363 /* fall through */
364 }
365 /*
366 * Most significant two bits of byte zero indicate how many following bytes
367 * are in PkgLength encoding.
368 */
369 byte = ((length_bytes - 1) << PACKAGE_LENGTH_1BYTE_SHIFT) | length;
370 build_prepend_byte(package, byte);
371}
372
373static void build_package(GArray *package, uint8_t op, unsigned min_bytes)
374{
375 build_prepend_package_length(package, min_bytes);
376 build_prepend_byte(package, op);
377}
378
379static void build_append_value(GArray *table, uint32_t value, int size)
380{
381 uint8_t prefix;
382 int i;
383
384 switch (size) {
385 case 1:
386 prefix = 0x0A; /* BytePrefix */
387 break;
388 case 2:
389 prefix = 0x0B; /* WordPrefix */
390 break;
391 case 4:
392 prefix = 0x0C; /* DWordPrefix */
393 break;
394 default:
395 assert(0);
396 return;
397 }
398 build_append_byte(table, prefix);
399 for (i = 0; i < size; ++i) {
400 build_append_byte(table, value & 0xFF);
401 value = value >> 8;
402 }
403}
404
405static void build_append_notify_target(GArray *method, GArray *target_name,
406 uint32_t value, int size)
407{
408 GArray *notify = build_alloc_array();
409 uint8_t op = 0xA0; /* IfOp */
410
411 build_append_byte(notify, 0x93); /* LEqualOp */
412 build_append_byte(notify, 0x68); /* Arg0Op */
413 build_append_value(notify, value, size);
414 build_append_byte(notify, 0x86); /* NotifyOp */
415 build_append_array(notify, target_name);
416 build_append_byte(notify, 0x69); /* Arg1Op */
417
418 /* Pack it up */
419 build_package(notify, op, 1);
420
421 build_append_array(method, notify);
422
423 build_free_array(notify);
424}
425
426#define ACPI_PORT_SMI_CMD 0x00b2 /* TODO: this is APM_CNT_IOPORT */
427
428static inline void *acpi_data_push(GArray *table_data, unsigned size)
429{
430 unsigned off = table_data->len;
431 g_array_set_size(table_data, off + size);
432 return table_data->data + off;
433}
434
435static unsigned acpi_data_len(GArray *table)
436{
134d42d6 437#if GLIB_CHECK_VERSION(2, 22, 0)
b15654c2
MT
438 assert(g_array_get_element_size(table) == 1);
439#endif
440 return table->len;
72c194f7
MT
441}
442
443static void acpi_align_size(GArray *blob, unsigned align)
444{
445 /* Align size to multiple of given size. This reduces the chance
446 * we need to change size in the future (breaking cross version migration).
447 */
134d42d6 448 g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
72c194f7
MT
449}
450
451/* Get pointer within table in a safe manner */
452#define ACPI_BUILD_PTR(table, size, off, type) \
453 ((type *)(acpi_data_get_ptr(table, size, off, sizeof(type))))
454
455static inline void *acpi_data_get_ptr(uint8_t *table_data, unsigned table_size,
456 unsigned off, unsigned size)
457{
458 assert(off + size > off);
459 assert(off + size <= table_size);
460 return table_data + off;
461}
462
463static inline void acpi_add_table(GArray *table_offsets, GArray *table_data)
464{
465 uint32_t offset = cpu_to_le32(table_data->len);
466 g_array_append_val(table_offsets, offset);
467}
468
469/* FACS */
470static void
471build_facs(GArray *table_data, GArray *linker, PcGuestInfo *guest_info)
472{
473 AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
474 facs->signature = cpu_to_le32(ACPI_FACS_SIGNATURE);
475 facs->length = cpu_to_le32(sizeof(*facs));
476}
477
478/* Load chipset information in FADT */
479static void fadt_setup(AcpiFadtDescriptorRev1 *fadt, AcpiPmInfo *pm)
480{
481 fadt->model = 1;
482 fadt->reserved1 = 0;
483 fadt->sci_int = cpu_to_le16(pm->sci_int);
484 fadt->smi_cmd = cpu_to_le32(ACPI_PORT_SMI_CMD);
485 fadt->acpi_enable = pm->acpi_enable_cmd;
486 fadt->acpi_disable = pm->acpi_disable_cmd;
487 /* EVT, CNT, TMR offset matches hw/acpi/core.c */
488 fadt->pm1a_evt_blk = cpu_to_le32(pm->io_base);
489 fadt->pm1a_cnt_blk = cpu_to_le32(pm->io_base + 0x04);
490 fadt->pm_tmr_blk = cpu_to_le32(pm->io_base + 0x08);
491 fadt->gpe0_blk = cpu_to_le32(pm->gpe0_blk);
492 /* EVT, CNT, TMR length matches hw/acpi/core.c */
493 fadt->pm1_evt_len = 4;
494 fadt->pm1_cnt_len = 2;
495 fadt->pm_tmr_len = 4;
496 fadt->gpe0_blk_len = pm->gpe0_blk_len;
497 fadt->plvl2_lat = cpu_to_le16(0xfff); /* C2 state not supported */
498 fadt->plvl3_lat = cpu_to_le16(0xfff); /* C3 state not supported */
499 fadt->flags = cpu_to_le32((1 << ACPI_FADT_F_WBINVD) |
500 (1 << ACPI_FADT_F_PROC_C1) |
501 (1 << ACPI_FADT_F_SLP_BUTTON) |
502 (1 << ACPI_FADT_F_RTC_S4));
503 fadt->flags |= cpu_to_le32(1 << ACPI_FADT_F_USE_PLATFORM_CLOCK);
504}
505
506
507/* FADT */
508static void
509build_fadt(GArray *table_data, GArray *linker, AcpiPmInfo *pm,
510 unsigned facs, unsigned dsdt)
511{
512 AcpiFadtDescriptorRev1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
513
514 fadt->firmware_ctrl = cpu_to_le32(facs);
515 /* FACS address to be filled by Guest linker */
516 bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
517 ACPI_BUILD_TABLE_FILE,
518 table_data, &fadt->firmware_ctrl,
519 sizeof fadt->firmware_ctrl);
520
521 fadt->dsdt = cpu_to_le32(dsdt);
522 /* DSDT address to be filled by Guest linker */
523 bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
524 ACPI_BUILD_TABLE_FILE,
525 table_data, &fadt->dsdt,
526 sizeof fadt->dsdt);
527
528 fadt_setup(fadt, pm);
529
530 build_header(linker, table_data,
531 (void *)fadt, ACPI_FACP_SIGNATURE, sizeof(*fadt), 1);
532}
533
534static void
535build_madt(GArray *table_data, GArray *linker, AcpiCpuInfo *cpu,
536 PcGuestInfo *guest_info)
537{
538 int madt_start = table_data->len;
539
540 AcpiMultipleApicTable *madt;
541 AcpiMadtIoApic *io_apic;
542 AcpiMadtIntsrcovr *intsrcovr;
543 AcpiMadtLocalNmi *local_nmi;
544 int i;
545
546 madt = acpi_data_push(table_data, sizeof *madt);
547 madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS);
548 madt->flags = cpu_to_le32(1);
549
550 for (i = 0; i < guest_info->apic_id_limit; i++) {
551 AcpiMadtProcessorApic *apic = acpi_data_push(table_data, sizeof *apic);
552 apic->type = ACPI_APIC_PROCESSOR;
553 apic->length = sizeof(*apic);
554 apic->processor_id = i;
555 apic->local_apic_id = i;
556 if (test_bit(i, cpu->found_cpus)) {
557 apic->flags = cpu_to_le32(1);
558 } else {
559 apic->flags = cpu_to_le32(0);
560 }
561 }
562 io_apic = acpi_data_push(table_data, sizeof *io_apic);
563 io_apic->type = ACPI_APIC_IO;
564 io_apic->length = sizeof(*io_apic);
565#define ACPI_BUILD_IOAPIC_ID 0x0
566 io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID;
567 io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
568 io_apic->interrupt = cpu_to_le32(0);
569
570 if (guest_info->apic_xrupt_override) {
571 intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
572 intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE;
573 intsrcovr->length = sizeof(*intsrcovr);
574 intsrcovr->source = 0;
575 intsrcovr->gsi = cpu_to_le32(2);
576 intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */
577 }
578 for (i = 1; i < 16; i++) {
579#define ACPI_BUILD_PCI_IRQS ((1<<5) | (1<<9) | (1<<10) | (1<<11))
580 if (!(ACPI_BUILD_PCI_IRQS & (1 << i))) {
581 /* No need for a INT source override structure. */
582 continue;
583 }
584 intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
585 intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE;
586 intsrcovr->length = sizeof(*intsrcovr);
587 intsrcovr->source = i;
588 intsrcovr->gsi = cpu_to_le32(i);
589 intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
590 }
591
592 local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
593 local_nmi->type = ACPI_APIC_LOCAL_NMI;
594 local_nmi->length = sizeof(*local_nmi);
595 local_nmi->processor_id = 0xff; /* all processors */
596 local_nmi->flags = cpu_to_le16(0);
597 local_nmi->lint = 1; /* ACPI_LINT1 */
598
599 build_header(linker, table_data,
600 (void *)(table_data->data + madt_start), ACPI_APIC_SIGNATURE,
601 table_data->len - madt_start, 1);
602}
603
604/* Encode a hex value */
605static inline char acpi_get_hex(uint32_t val)
606{
607 val &= 0x0f;
608 return (val <= 9) ? ('0' + val) : ('A' + val - 10);
609}
610
611#include "hw/i386/ssdt-proc.hex"
612
613/* 0x5B 0x83 ProcessorOp PkgLength NameString ProcID */
614#define ACPI_PROC_OFFSET_CPUHEX (*ssdt_proc_name - *ssdt_proc_start + 2)
615#define ACPI_PROC_OFFSET_CPUID1 (*ssdt_proc_name - *ssdt_proc_start + 4)
616#define ACPI_PROC_OFFSET_CPUID2 (*ssdt_proc_id - *ssdt_proc_start)
617#define ACPI_PROC_SIZEOF (*ssdt_proc_end - *ssdt_proc_start)
618#define ACPI_PROC_AML (ssdp_proc_aml + *ssdt_proc_start)
619
620/* 0x5B 0x82 DeviceOp PkgLength NameString */
621#define ACPI_PCIHP_OFFSET_HEX (*ssdt_pcihp_name - *ssdt_pcihp_start + 1)
622#define ACPI_PCIHP_OFFSET_ID (*ssdt_pcihp_id - *ssdt_pcihp_start)
623#define ACPI_PCIHP_OFFSET_ADR (*ssdt_pcihp_adr - *ssdt_pcihp_start)
624#define ACPI_PCIHP_OFFSET_EJ0 (*ssdt_pcihp_ej0 - *ssdt_pcihp_start)
625#define ACPI_PCIHP_SIZEOF (*ssdt_pcihp_end - *ssdt_pcihp_start)
626#define ACPI_PCIHP_AML (ssdp_pcihp_aml + *ssdt_pcihp_start)
627
628#define ACPI_SSDT_SIGNATURE 0x54445353 /* SSDT */
629#define ACPI_SSDT_HEADER_LENGTH 36
630
631#include "hw/i386/ssdt-misc.hex"
632#include "hw/i386/ssdt-pcihp.hex"
633
634static void
635build_append_notify(GArray *device, const char *name,
636 const char *format, int skip, int count)
637{
638 int i;
639 GArray *method = build_alloc_array();
640 uint8_t op = 0x14; /* MethodOp */
641
867d898c 642 build_append_nameseg(method, "%s", name);
72c194f7
MT
643 build_append_byte(method, 0x02); /* MethodFlags: ArgCount */
644 for (i = skip; i < count; i++) {
645 GArray *target = build_alloc_array();
646 build_append_nameseg(target, format, i);
647 assert(i < 256); /* Fits in 1 byte */
648 build_append_notify_target(method, target, i, 1);
649 build_free_array(target);
650 }
651 build_package(method, op, 2);
652
653 build_append_array(device, method);
654 build_free_array(method);
655}
656
657static void patch_pcihp(int slot, uint8_t *ssdt_ptr, uint32_t eject)
658{
659 ssdt_ptr[ACPI_PCIHP_OFFSET_HEX] = acpi_get_hex(slot >> 4);
660 ssdt_ptr[ACPI_PCIHP_OFFSET_HEX + 1] = acpi_get_hex(slot);
661 ssdt_ptr[ACPI_PCIHP_OFFSET_ID] = slot;
662 ssdt_ptr[ACPI_PCIHP_OFFSET_ADR + 2] = slot;
663
664 /* Runtime patching of ACPI_EJ0: to disable hotplug for a slot,
665 * replace the method name: _EJ0 by ACPI_EJ0_.
666 */
667 /* Sanity check */
668 assert(!memcmp(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "_EJ0", 4));
669
670 if (!eject) {
671 memcpy(ssdt_ptr + ACPI_PCIHP_OFFSET_EJ0, "EJ0_", 4);
672 }
673}
674
675static void patch_pci_windows(PcPciInfo *pci, uint8_t *start, unsigned size)
676{
677 *ACPI_BUILD_PTR(start, size, acpi_pci32_start[0], uint32_t) =
678 cpu_to_le32(pci->w32.begin);
679
680 *ACPI_BUILD_PTR(start, size, acpi_pci32_end[0], uint32_t) =
681 cpu_to_le32(pci->w32.end - 1);
682
683 if (pci->w64.end || pci->w64.begin) {
684 *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 1;
685 *ACPI_BUILD_PTR(start, size, acpi_pci64_start[0], uint64_t) =
686 cpu_to_le64(pci->w64.begin);
687 *ACPI_BUILD_PTR(start, size, acpi_pci64_end[0], uint64_t) =
688 cpu_to_le64(pci->w64.end - 1);
689 *ACPI_BUILD_PTR(start, size, acpi_pci64_length[0], uint64_t) =
690 cpu_to_le64(pci->w64.end - pci->w64.begin);
691 } else {
692 *ACPI_BUILD_PTR(start, size, acpi_pci64_valid[0], uint8_t) = 0;
693 }
694}
695
696static void
697build_ssdt(GArray *table_data, GArray *linker,
698 AcpiCpuInfo *cpu, AcpiPmInfo *pm, AcpiMiscInfo *misc,
699 PcPciInfo *pci, PcGuestInfo *guest_info)
700{
701 int acpi_cpus = MIN(0xff, guest_info->apic_id_limit);
702 int ssdt_start = table_data->len;
703 uint8_t *ssdt_ptr;
704 int i;
705
706 /* Copy header and patch values in the S3_ / S4_ / S5_ packages */
707 ssdt_ptr = acpi_data_push(table_data, sizeof(ssdp_misc_aml));
708 memcpy(ssdt_ptr, ssdp_misc_aml, sizeof(ssdp_misc_aml));
709 if (pm->s3_disabled) {
710 ssdt_ptr[acpi_s3_name[0]] = 'X';
711 }
712 if (pm->s4_disabled) {
713 ssdt_ptr[acpi_s4_name[0]] = 'X';
714 } else {
715 ssdt_ptr[acpi_s4_pkg[0] + 1] = ssdt_ptr[acpi_s4_pkg[0] + 3] =
716 pm->s4_val;
717 }
718
719 patch_pci_windows(pci, ssdt_ptr, sizeof(ssdp_misc_aml));
720
721 *(uint16_t *)(ssdt_ptr + *ssdt_isa_pest) =
722 cpu_to_le16(misc->pvpanic_port);
723
724 {
725 GArray *sb_scope = build_alloc_array();
726 uint8_t op = 0x10; /* ScopeOp */
727
728 build_append_nameseg(sb_scope, "_SB_");
729
730 /* build Processor object for each processor */
731 for (i = 0; i < acpi_cpus; i++) {
732 uint8_t *proc = acpi_data_push(sb_scope, ACPI_PROC_SIZEOF);
733 memcpy(proc, ACPI_PROC_AML, ACPI_PROC_SIZEOF);
734 proc[ACPI_PROC_OFFSET_CPUHEX] = acpi_get_hex(i >> 4);
735 proc[ACPI_PROC_OFFSET_CPUHEX+1] = acpi_get_hex(i);
736 proc[ACPI_PROC_OFFSET_CPUID1] = i;
737 proc[ACPI_PROC_OFFSET_CPUID2] = i;
738 }
739
740 /* build this code:
741 * Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
742 */
743 /* Arg0 = Processor ID = APIC ID */
744 build_append_notify(sb_scope, "NTFY", "CP%0.02X", 0, acpi_cpus);
745
746 /* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })" */
747 build_append_byte(sb_scope, 0x08); /* NameOp */
748 build_append_nameseg(sb_scope, "CPON");
749
750 {
751 GArray *package = build_alloc_array();
752 uint8_t op = 0x12; /* PackageOp */
753
754 build_append_byte(package, acpi_cpus); /* NumElements */
755 for (i = 0; i < acpi_cpus; i++) {
756 uint8_t b = test_bit(i, cpu->found_cpus) ? 0x01 : 0x00;
757 build_append_byte(package, b);
758 }
759
760 build_package(package, op, 2);
761 build_append_array(sb_scope, package);
762 build_free_array(package);
763 }
764
765 {
766 GArray *pci0 = build_alloc_array();
767 uint8_t op = 0x10; /* ScopeOp */;
768
769 build_append_nameseg(pci0, "PCI0");
770
771 /* build Device object for each slot */
772 for (i = 1; i < PCI_SLOT_MAX; i++) {
773 bool eject = test_bit(i, misc->slot_hotplug_enable);
774 void *pcihp = acpi_data_push(pci0, ACPI_PCIHP_SIZEOF);
775
776 memcpy(pcihp, ACPI_PCIHP_AML, ACPI_PCIHP_SIZEOF);
777 patch_pcihp(i, pcihp, eject);
778 }
779
780 build_append_notify(pci0, "PCNT", "S%0.02X_", 1, PCI_SLOT_MAX);
781 build_package(pci0, op, 3);
782 build_append_array(sb_scope, pci0);
783 build_free_array(pci0);
784 }
785
786 build_package(sb_scope, op, 3);
787 build_append_array(table_data, sb_scope);
788 build_free_array(sb_scope);
789 }
790
791 build_header(linker, table_data,
792 (void *)(table_data->data + ssdt_start),
793 ACPI_SSDT_SIGNATURE, table_data->len - ssdt_start, 1);
794}
795
796static void
797build_hpet(GArray *table_data, GArray *linker)
798{
799 Acpi20Hpet *hpet;
800
801 hpet = acpi_data_push(table_data, sizeof(*hpet));
802 /* Note timer_block_id value must be kept in sync with value advertised by
803 * emulated hpet
804 */
805 hpet->timer_block_id = cpu_to_le32(0x8086a201);
806 hpet->addr.address = cpu_to_le64(HPET_BASE);
807 build_header(linker, table_data,
808 (void *)hpet, ACPI_HPET_SIGNATURE, sizeof(*hpet), 1);
809}
810
811static void
812acpi_build_srat_memory(AcpiSratMemoryAffinity *numamem,
813 uint64_t base, uint64_t len, int node, int enabled)
814{
815 numamem->type = ACPI_SRAT_MEMORY;
816 numamem->length = sizeof(*numamem);
817 memset(numamem->proximity, 0, 4);
818 numamem->proximity[0] = node;
819 numamem->flags = cpu_to_le32(!!enabled);
820 numamem->base_addr = cpu_to_le64(base);
821 numamem->range_length = cpu_to_le64(len);
822}
823
824static void
825build_srat(GArray *table_data, GArray *linker,
826 AcpiCpuInfo *cpu, PcGuestInfo *guest_info)
827{
828 AcpiSystemResourceAffinityTable *srat;
829 AcpiSratProcessorAffinity *core;
830 AcpiSratMemoryAffinity *numamem;
831
832 int i;
833 uint64_t curnode;
834 int srat_start, numa_start, slots;
835 uint64_t mem_len, mem_base, next_base;
836
837 srat_start = table_data->len;
838
839 srat = acpi_data_push(table_data, sizeof *srat);
840 srat->reserved1 = cpu_to_le32(1);
841 core = (void *)(srat + 1);
842
843 for (i = 0; i < guest_info->apic_id_limit; ++i) {
844 core = acpi_data_push(table_data, sizeof *core);
845 core->type = ACPI_SRAT_PROCESSOR;
846 core->length = sizeof(*core);
847 core->local_apic_id = i;
848 curnode = guest_info->node_cpu[i];
849 core->proximity_lo = curnode;
850 memset(core->proximity_hi, 0, 3);
851 core->local_sapic_eid = 0;
852 if (test_bit(i, cpu->found_cpus)) {
853 core->flags = cpu_to_le32(1);
854 } else {
855 core->flags = cpu_to_le32(0);
856 }
857 }
858
859
860 /* the memory map is a bit tricky, it contains at least one hole
861 * from 640k-1M and possibly another one from 3.5G-4G.
862 */
863 next_base = 0;
864 numa_start = table_data->len;
865
866 numamem = acpi_data_push(table_data, sizeof *numamem);
867 acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
868 next_base = 1024 * 1024;
869 for (i = 1; i < guest_info->numa_nodes + 1; ++i) {
870 mem_base = next_base;
871 mem_len = guest_info->node_mem[i - 1];
872 if (i == 1) {
873 mem_len -= 1024 * 1024;
874 }
875 next_base = mem_base + mem_len;
876
877 /* Cut out the ACPI_PCI hole */
878 if (mem_base <= guest_info->ram_size &&
879 next_base > guest_info->ram_size) {
880 mem_len -= next_base - guest_info->ram_size;
881 if (mem_len > 0) {
882 numamem = acpi_data_push(table_data, sizeof *numamem);
883 acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
884 }
885 mem_base = 1ULL << 32;
886 mem_len = next_base - guest_info->ram_size;
887 next_base += (1ULL << 32) - guest_info->ram_size;
888 }
889 numamem = acpi_data_push(table_data, sizeof *numamem);
890 acpi_build_srat_memory(numamem, mem_base, mem_len, i - 1, 1);
891 }
892 slots = (table_data->len - numa_start) / sizeof *numamem;
893 for (; slots < guest_info->numa_nodes + 2; slots++) {
894 numamem = acpi_data_push(table_data, sizeof *numamem);
895 acpi_build_srat_memory(numamem, 0, 0, 0, 0);
896 }
897
898 build_header(linker, table_data,
899 (void *)(table_data->data + srat_start),
900 ACPI_SRAT_SIGNATURE,
901 table_data->len - srat_start, 1);
902}
903
904static void
905build_mcfg_q35(GArray *table_data, GArray *linker, AcpiMcfgInfo *info)
906{
907 AcpiTableMcfg *mcfg;
908 uint32_t sig;
909 int len = sizeof(*mcfg) + 1 * sizeof(mcfg->allocation[0]);
910
911 mcfg = acpi_data_push(table_data, len);
912 mcfg->allocation[0].address = cpu_to_le64(info->mcfg_base);
913 /* Only a single allocation so no need to play with segments */
914 mcfg->allocation[0].pci_segment = cpu_to_le16(0);
915 mcfg->allocation[0].start_bus_number = 0;
916 mcfg->allocation[0].end_bus_number = PCIE_MMCFG_BUS(info->mcfg_size - 1);
917
918 /* MCFG is used for ECAM which can be enabled or disabled by guest.
919 * To avoid table size changes (which create migration issues),
920 * always create the table even if there are no allocations,
921 * but set the signature to a reserved value in this case.
922 * ACPI spec requires OSPMs to ignore such tables.
923 */
924 if (info->mcfg_base == PCIE_BASE_ADDR_UNMAPPED) {
925 sig = ACPI_RSRV_SIGNATURE;
926 } else {
927 sig = ACPI_MCFG_SIGNATURE;
928 }
929 build_header(linker, table_data, (void *)mcfg, sig, len, 1);
930}
931
932static void
933build_dsdt(GArray *table_data, GArray *linker, AcpiMiscInfo *misc)
934{
53db092a
MT
935 AcpiTableHeader *dsdt;
936
72c194f7 937 assert(misc->dsdt_code && misc->dsdt_size);
53db092a 938
72c194f7
MT
939 dsdt = acpi_data_push(table_data, misc->dsdt_size);
940 memcpy(dsdt, misc->dsdt_code, misc->dsdt_size);
53db092a
MT
941
942 memset(dsdt, 0, sizeof *dsdt);
943 build_header(linker, table_data, dsdt, ACPI_DSDT_SIGNATURE,
944 misc->dsdt_size, 1);
72c194f7
MT
945}
946
947/* Build final rsdt table */
948static void
949build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
950{
951 AcpiRsdtDescriptorRev1 *rsdt;
952 size_t rsdt_len;
953 int i;
954
955 rsdt_len = sizeof(*rsdt) + sizeof(uint32_t) * table_offsets->len;
956 rsdt = acpi_data_push(table_data, rsdt_len);
957 memcpy(rsdt->table_offset_entry, table_offsets->data,
958 sizeof(uint32_t) * table_offsets->len);
959 for (i = 0; i < table_offsets->len; ++i) {
960 /* rsdt->table_offset_entry to be filled by Guest linker */
961 bios_linker_loader_add_pointer(linker,
962 ACPI_BUILD_TABLE_FILE,
963 ACPI_BUILD_TABLE_FILE,
964 table_data, &rsdt->table_offset_entry[i],
965 sizeof(uint32_t));
966 }
967 build_header(linker, table_data,
968 (void *)rsdt, ACPI_RSDT_SIGNATURE, rsdt_len, 1);
969}
970
971static GArray *
972build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
973{
974 AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
975
976 bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 1,
977 true /* fseg memory */);
978
979 rsdp->signature = cpu_to_le64(ACPI_RSDP_SIGNATURE);
980 memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
981 rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
982 /* Address to be filled by Guest linker */
983 bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
984 ACPI_BUILD_TABLE_FILE,
985 rsdp_table, &rsdp->rsdt_physical_address,
986 sizeof rsdp->rsdt_physical_address);
987 rsdp->checksum = 0;
988 /* Checksum to be filled by Guest linker */
989 bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
990 rsdp, rsdp, sizeof *rsdp, &rsdp->checksum);
991
992 return rsdp_table;
993}
994
995typedef
996struct AcpiBuildTables {
997 GArray *table_data;
998 GArray *rsdp;
999 GArray *linker;
1000} AcpiBuildTables;
1001
1002static inline void acpi_build_tables_init(AcpiBuildTables *tables)
1003{
1004 tables->rsdp = g_array_new(false, true /* clear */, 1);
1005 tables->table_data = g_array_new(false, true /* clear */, 1);
1006 tables->linker = bios_linker_loader_init();
1007}
1008
1009static inline void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
1010{
1011 void *linker_data = bios_linker_loader_cleanup(tables->linker);
1012 if (mfre) {
1013 g_free(linker_data);
1014 }
1015 g_array_free(tables->rsdp, mfre);
1016 g_array_free(tables->table_data, mfre);
1017}
1018
1019typedef
1020struct AcpiBuildState {
1021 /* Copy of table in RAM (for patching). */
1022 uint8_t *table_ram;
1023 uint32_t table_size;
1024 /* Is table patched? */
1025 uint8_t patched;
1026 PcGuestInfo *guest_info;
1027} AcpiBuildState;
1028
1029static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
1030{
1031 Object *pci_host;
1032 QObject *o;
1033 bool ambiguous;
1034
1035 pci_host = object_resolve_path_type("", TYPE_PCI_HOST_BRIDGE, &ambiguous);
1036 g_assert(!ambiguous);
1037 g_assert(pci_host);
1038
1039 o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_BASE, NULL);
1040 if (!o) {
1041 return false;
1042 }
1043 mcfg->mcfg_base = qint_get_int(qobject_to_qint(o));
1044
1045 o = object_property_get_qobject(pci_host, PCIE_HOST_MCFG_SIZE, NULL);
1046 assert(o);
1047 mcfg->mcfg_size = qint_get_int(qobject_to_qint(o));
1048 return true;
1049}
1050
1051static
1052void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
1053{
1054 GArray *table_offsets;
1055 unsigned facs, dsdt, rsdt;
1056 AcpiCpuInfo cpu;
1057 AcpiPmInfo pm;
1058 AcpiMiscInfo misc;
1059 AcpiMcfgInfo mcfg;
1060 PcPciInfo pci;
1061 uint8_t *u;
1062
1063 acpi_get_cpu_info(&cpu);
1064 acpi_get_pm_info(&pm);
1065 acpi_get_dsdt(&misc);
1066 acpi_get_hotplug_info(&misc);
1067 acpi_get_misc_info(&misc);
1068 acpi_get_pci_info(&pci);
1069
1070 table_offsets = g_array_new(false, true /* clear */,
1071 sizeof(uint32_t));
1072 ACPI_BUILD_DPRINTF(3, "init ACPI tables\n");
1073
1074 bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
1075 64 /* Ensure FACS is aligned */,
1076 false /* high memory */);
1077
1078 /*
1079 * FACS is pointed to by FADT.
1080 * We place it first since it's the only table that has alignment
1081 * requirements.
1082 */
1083 facs = tables->table_data->len;
1084 build_facs(tables->table_data, tables->linker, guest_info);
1085
1086 /* DSDT is pointed to by FADT */
1087 dsdt = tables->table_data->len;
1088 build_dsdt(tables->table_data, tables->linker, &misc);
1089
1090 /* ACPI tables pointed to by RSDT */
1091 acpi_add_table(table_offsets, tables->table_data);
1092 build_fadt(tables->table_data, tables->linker, &pm, facs, dsdt);
1093 acpi_add_table(table_offsets, tables->table_data);
1094
1095 build_ssdt(tables->table_data, tables->linker, &cpu, &pm, &misc, &pci,
1096 guest_info);
1097 acpi_add_table(table_offsets, tables->table_data);
1098
1099 build_madt(tables->table_data, tables->linker, &cpu, guest_info);
1100 acpi_add_table(table_offsets, tables->table_data);
1101 if (misc.has_hpet) {
1102 build_hpet(tables->table_data, tables->linker);
1103 }
1104 if (guest_info->numa_nodes) {
1105 acpi_add_table(table_offsets, tables->table_data);
1106 build_srat(tables->table_data, tables->linker, &cpu, guest_info);
1107 }
1108 if (acpi_get_mcfg(&mcfg)) {
1109 acpi_add_table(table_offsets, tables->table_data);
1110 build_mcfg_q35(tables->table_data, tables->linker, &mcfg);
1111 }
1112
1113 /* Add tables supplied by user (if any) */
1114 for (u = acpi_table_first(); u; u = acpi_table_next(u)) {
1115 unsigned len = acpi_table_len(u);
1116
1117 acpi_add_table(table_offsets, tables->table_data);
1118 g_array_append_vals(tables->table_data, u, len);
1119 }
1120
1121 /* RSDT is pointed to by RSDP */
1122 rsdt = tables->table_data->len;
1123 build_rsdt(tables->table_data, tables->linker, table_offsets);
1124
1125 /* RSDP is in FSEG memory, so allocate it separately */
1126 build_rsdp(tables->rsdp, tables->linker, rsdt);
1127
1128 /* We'll expose it all to Guest so align size to reduce
1129 * chance of size changes.
1130 * RSDP is small so it's easy to keep it immutable, no need to
1131 * bother with alignment.
1132 */
1133 acpi_align_size(tables->table_data, 0x1000);
1134
1135 acpi_align_size(tables->linker, 0x1000);
1136
1137 /* Cleanup memory that's no longer used. */
1138 g_array_free(table_offsets, true);
1139}
1140
1141static void acpi_build_update(void *build_opaque, uint32_t offset)
1142{
1143 AcpiBuildState *build_state = build_opaque;
1144 AcpiBuildTables tables;
1145
1146 /* No state to update or already patched? Nothing to do. */
1147 if (!build_state || build_state->patched) {
1148 return;
1149 }
1150 build_state->patched = 1;
1151
1152 acpi_build_tables_init(&tables);
1153
1154 acpi_build(build_state->guest_info, &tables);
1155
1156 assert(acpi_data_len(tables.table_data) == build_state->table_size);
1157 memcpy(build_state->table_ram, tables.table_data->data,
1158 build_state->table_size);
1159
1160 acpi_build_tables_cleanup(&tables, true);
1161}
1162
1163static void acpi_build_reset(void *build_opaque)
1164{
1165 AcpiBuildState *build_state = build_opaque;
1166 build_state->patched = 0;
1167}
1168
1169static void *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob,
1170 const char *name)
1171{
1172 return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name,
1173 acpi_build_update, build_state);
1174}
1175
1176static const VMStateDescription vmstate_acpi_build = {
1177 .name = "acpi_build",
1178 .version_id = 1,
1179 .minimum_version_id = 1,
1180 .minimum_version_id_old = 1,
1181 .fields = (VMStateField[]) {
1182 VMSTATE_UINT8(patched, AcpiBuildState),
1183 VMSTATE_END_OF_LIST()
1184 },
1185};
1186
1187void acpi_setup(PcGuestInfo *guest_info)
1188{
1189 AcpiBuildTables tables;
1190 AcpiBuildState *build_state;
1191
1192 if (!guest_info->fw_cfg) {
1193 ACPI_BUILD_DPRINTF(3, "No fw cfg. Bailing out.\n");
1194 return;
1195 }
1196
1197 if (!guest_info->has_acpi_build) {
1198 ACPI_BUILD_DPRINTF(3, "ACPI build disabled. Bailing out.\n");
1199 return;
1200 }
1201
81adc513
MT
1202 if (!acpi_enabled) {
1203 ACPI_BUILD_DPRINTF(3, "ACPI disabled. Bailing out.\n");
1204 return;
1205 }
1206
72c194f7
MT
1207 build_state = g_malloc0(sizeof *build_state);
1208
1209 build_state->guest_info = guest_info;
1210
1211 acpi_build_tables_init(&tables);
1212 acpi_build(build_state->guest_info, &tables);
1213
1214 /* Now expose it all to Guest */
1215 build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data,
1216 ACPI_BUILD_TABLE_FILE);
1217 build_state->table_size = acpi_data_len(tables.table_data);
1218
1219 acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader");
1220
1221 /*
1222 * RSDP is small so it's easy to keep it immutable, no need to
1223 * bother with ROM blobs.
1224 */
1225 fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
1226 tables.rsdp->data, acpi_data_len(tables.rsdp));
1227
1228 qemu_register_reset(acpi_build_reset, build_state);
1229 acpi_build_reset(build_state);
1230 vmstate_register(NULL, 0, &vmstate_acpi_build, build_state);
1231
1232 /* Cleanup tables but don't free the memory: we track it
1233 * in build_state.
1234 */
1235 acpi_build_tables_cleanup(&tables, false);
1236}
This page took 0.16312 seconds and 4 git commands to generate.