1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 * Support for generating ACPI tables and passing them to Guests
5 * Copyright (C) 2021 Loongson Technology Corporation Limited
8 #include "qemu/osdep.h"
9 #include "qapi/error.h"
10 #include "qemu/error-report.h"
11 #include "qemu/bitmap.h"
12 #include "hw/pci/pci.h"
13 #include "hw/core/cpu.h"
14 #include "target/loongarch/cpu.h"
15 #include "hw/acpi/acpi-defs.h"
16 #include "hw/acpi/acpi.h"
17 #include "hw/nvram/fw_cfg.h"
18 #include "hw/acpi/bios-linker-loader.h"
19 #include "migration/vmstate.h"
20 #include "hw/mem/memory-device.h"
21 #include "sysemu/reset.h"
23 /* Supported chipsets: */
24 #include "hw/pci-host/ls7a.h"
25 #include "hw/loongarch/virt.h"
27 #include "hw/acpi/utils.h"
28 #include "hw/acpi/pci.h"
30 #include "qom/qom-qobject.h"
32 #include "hw/acpi/generic_event_device.h"
33 #include "hw/pci-host/gpex.h"
34 #include "sysemu/tpm.h"
35 #include "hw/platform-bus.h"
36 #include "hw/acpi/aml-build.h"
37 #include "hw/acpi/hmat.h"
39 #define ACPI_BUILD_ALIGN_SIZE 0x1000
40 #define ACPI_BUILD_TABLE_SIZE 0x20000
42 #ifdef DEBUG_ACPI_BUILD
43 #define ACPI_BUILD_DPRINTF(fmt, ...) \
44 do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0)
46 #define ACPI_BUILD_DPRINTF(fmt, ...)
50 static void init_common_fadt_data(AcpiFadtData
*data
)
53 /* ACPI 5.0: 4.1 Hardware-Reduced ACPI */
55 .flags
= ((1 << ACPI_FADT_F_HW_REDUCED_ACPI
) |
56 (1 << ACPI_FADT_F_RESET_REG_SUP
)),
58 /* ACPI 5.0: 4.8.3.7 Sleep Control and Status Registers */
60 .space_id
= AML_AS_SYSTEM_MEMORY
,
62 .address
= VIRT_GED_REG_ADDR
+ ACPI_GED_REG_SLEEP_CTL
,
65 .space_id
= AML_AS_SYSTEM_MEMORY
,
67 .address
= VIRT_GED_REG_ADDR
+ ACPI_GED_REG_SLEEP_STS
,
70 /* ACPI 5.0: 4.8.3.6 Reset Register */
72 .space_id
= AML_AS_SYSTEM_MEMORY
,
74 .address
= VIRT_GED_REG_ADDR
+ ACPI_GED_REG_RESET
,
76 .reset_val
= ACPI_GED_RESET_VALUE
,
81 static void acpi_align_size(GArray
*blob
, unsigned align
)
84 * Align size to multiple of given size. This reduces the chance
85 * we need to change size in the future (breaking cross version migration).
87 g_array_set_size(blob
, ROUND_UP(acpi_data_len(blob
), align
));
92 build_facs(GArray
*table_data
)
94 const char *sig
= "FACS";
95 const uint8_t reserved
[40] = {};
97 g_array_append_vals(table_data
, sig
, 4); /* Signature */
98 build_append_int_noprefix(table_data
, 64, 4); /* Length */
99 build_append_int_noprefix(table_data
, 0, 4); /* Hardware Signature */
100 build_append_int_noprefix(table_data
, 0, 4); /* Firmware Waking Vector */
101 build_append_int_noprefix(table_data
, 0, 4); /* Global Lock */
102 build_append_int_noprefix(table_data
, 0, 4); /* Flags */
103 g_array_append_vals(table_data
, reserved
, 40); /* Reserved */
108 build_madt(GArray
*table_data
, BIOSLinker
*linker
,
109 LoongArchVirtMachineState
*lvms
)
111 MachineState
*ms
= MACHINE(lvms
);
112 MachineClass
*mc
= MACHINE_GET_CLASS(ms
);
113 const CPUArchIdList
*arch_ids
= mc
->possible_cpu_arch_ids(ms
);
115 AcpiTable table
= { .sig
= "APIC", .rev
= 1, .oem_id
= lvms
->oem_id
,
116 .oem_table_id
= lvms
->oem_table_id
};
118 acpi_table_begin(&table
, table_data
);
120 /* Local APIC Address */
121 build_append_int_noprefix(table_data
, 0, 4);
122 build_append_int_noprefix(table_data
, 1 /* PCAT_COMPAT */, 4); /* Flags */
124 for (i
= 0; i
< arch_ids
->len
; i
++) {
125 /* Processor Core Interrupt Controller Structure */
126 arch_id
= arch_ids
->cpus
[i
].arch_id
;
128 build_append_int_noprefix(table_data
, 17, 1); /* Type */
129 build_append_int_noprefix(table_data
, 15, 1); /* Length */
130 build_append_int_noprefix(table_data
, 1, 1); /* Version */
131 build_append_int_noprefix(table_data
, i
, 4); /* ACPI Processor ID */
132 build_append_int_noprefix(table_data
, arch_id
, 4); /* Core ID */
133 build_append_int_noprefix(table_data
, 1, 4); /* Flags */
136 /* Extend I/O Interrupt Controller Structure */
137 build_append_int_noprefix(table_data
, 20, 1); /* Type */
138 build_append_int_noprefix(table_data
, 13, 1); /* Length */
139 build_append_int_noprefix(table_data
, 1, 1); /* Version */
140 build_append_int_noprefix(table_data
, 3, 1); /* Cascade */
141 build_append_int_noprefix(table_data
, 0, 1); /* Node */
142 build_append_int_noprefix(table_data
, 0xffff, 8); /* Node map */
144 /* MSI Interrupt Controller Structure */
145 build_append_int_noprefix(table_data
, 21, 1); /* Type */
146 build_append_int_noprefix(table_data
, 19, 1); /* Length */
147 build_append_int_noprefix(table_data
, 1, 1); /* Version */
148 build_append_int_noprefix(table_data
, VIRT_PCH_MSI_ADDR_LOW
, 8);/* Address */
149 build_append_int_noprefix(table_data
, 0x40, 4); /* Start */
150 build_append_int_noprefix(table_data
, 0xc0, 4); /* Count */
152 /* Bridge I/O Interrupt Controller Structure */
153 build_append_int_noprefix(table_data
, 22, 1); /* Type */
154 build_append_int_noprefix(table_data
, 17, 1); /* Length */
155 build_append_int_noprefix(table_data
, 1, 1); /* Version */
156 build_append_int_noprefix(table_data
, VIRT_PCH_REG_BASE
, 8);/* Address */
157 build_append_int_noprefix(table_data
, 0x1000, 2); /* Size */
158 build_append_int_noprefix(table_data
, 0, 2); /* Id */
159 build_append_int_noprefix(table_data
, 0x40, 2); /* Base */
161 acpi_table_end(linker
, &table
);
166 build_srat(GArray
*table_data
, BIOSLinker
*linker
, MachineState
*machine
)
168 int i
, arch_id
, node_id
;
169 hwaddr len
, base
, gap
;
171 int nodes
, nb_numa_nodes
= machine
->numa_state
->num_nodes
;
172 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(machine
);
173 MachineClass
*mc
= MACHINE_GET_CLASS(lvms
);
174 const CPUArchIdList
*arch_ids
= mc
->possible_cpu_arch_ids(machine
);
175 AcpiTable table
= { .sig
= "SRAT", .rev
= 1, .oem_id
= lvms
->oem_id
,
176 .oem_table_id
= lvms
->oem_table_id
};
178 acpi_table_begin(&table
, table_data
);
179 build_append_int_noprefix(table_data
, 1, 4); /* Reserved */
180 build_append_int_noprefix(table_data
, 0, 8); /* Reserved */
182 for (i
= 0; i
< arch_ids
->len
; ++i
) {
183 arch_id
= arch_ids
->cpus
[i
].arch_id
;
184 node_id
= arch_ids
->cpus
[i
].props
.node_id
;
186 /* Processor Local APIC/SAPIC Affinity Structure */
187 build_append_int_noprefix(table_data
, 0, 1); /* Type */
188 build_append_int_noprefix(table_data
, 16, 1); /* Length */
189 /* Proximity Domain [7:0] */
190 build_append_int_noprefix(table_data
, node_id
, 1);
191 build_append_int_noprefix(table_data
, arch_id
, 1); /* APIC ID */
192 /* Flags, Table 5-36 */
193 build_append_int_noprefix(table_data
, 1, 4);
194 build_append_int_noprefix(table_data
, 0, 1); /* Local SAPIC EID */
195 /* Proximity Domain [31:8] */
196 build_append_int_noprefix(table_data
, 0, 3);
197 build_append_int_noprefix(table_data
, 0, 4); /* Reserved */
200 base
= VIRT_LOWMEM_BASE
;
201 gap
= VIRT_LOWMEM_SIZE
;
202 numa_info
= machine
->numa_state
->nodes
;
203 nodes
= nb_numa_nodes
;
208 for (i
= 0; i
< nodes
; i
++) {
210 len
= numa_info
[i
].node_mem
;
212 len
= machine
->ram_size
;
216 * memory for the node splited into two part
217 * lowram: [base, +gap)
218 * highram: [VIRT_HIGHMEM_BASE, +(len - gap))
221 build_srat_memory(table_data
, base
, gap
, i
, MEM_AFFINITY_ENABLED
);
223 base
= VIRT_HIGHMEM_BASE
;
224 gap
= machine
->ram_size
- VIRT_LOWMEM_SIZE
;
228 build_srat_memory(table_data
, base
, len
, i
, MEM_AFFINITY_ENABLED
);
234 if (machine
->device_memory
) {
235 build_srat_memory(table_data
, machine
->device_memory
->base
,
236 memory_region_size(&machine
->device_memory
->mr
),
238 MEM_AFFINITY_HOTPLUGGABLE
| MEM_AFFINITY_ENABLED
);
241 acpi_table_end(linker
, &table
);
245 struct AcpiBuildState
{
246 /* Copy of table in RAM (for patching). */
247 MemoryRegion
*table_mr
;
248 /* Is table patched? */
251 MemoryRegion
*rsdp_mr
;
252 MemoryRegion
*linker_mr
;
255 static void build_uart_device_aml(Aml
*table
)
259 Aml
*pkg0
, *pkg1
, *pkg2
;
260 uint32_t uart_irq
= VIRT_UART_IRQ
;
262 Aml
*scope
= aml_scope("_SB");
263 dev
= aml_device("COMA");
264 aml_append(dev
, aml_name_decl("_HID", aml_string("PNP0501")));
265 aml_append(dev
, aml_name_decl("_UID", aml_int(0)));
266 aml_append(dev
, aml_name_decl("_CCA", aml_int(1)));
267 crs
= aml_resource_template();
269 aml_qword_memory(AML_POS_DECODE
, AML_MIN_FIXED
, AML_MAX_FIXED
,
270 AML_NON_CACHEABLE
, AML_READ_WRITE
,
271 0, VIRT_UART_BASE
, VIRT_UART_BASE
+ VIRT_UART_SIZE
- 1,
273 aml_append(crs
, aml_interrupt(AML_CONSUMER
, AML_LEVEL
, AML_ACTIVE_HIGH
,
274 AML_SHARED
, &uart_irq
, 1));
275 aml_append(dev
, aml_name_decl("_CRS", crs
));
276 pkg0
= aml_package(0x2);
277 aml_append(pkg0
, aml_int(0x05F5E100));
278 aml_append(pkg0
, aml_string("clock-frenquency"));
279 pkg1
= aml_package(0x1);
280 aml_append(pkg1
, pkg0
);
281 pkg2
= aml_package(0x2);
282 aml_append(pkg2
, aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301"));
283 aml_append(pkg2
, pkg1
);
284 aml_append(dev
, aml_name_decl("_DSD", pkg2
));
285 aml_append(scope
, dev
);
286 aml_append(table
, scope
);
290 build_la_ged_aml(Aml
*dsdt
, MachineState
*machine
)
293 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(machine
);
295 build_ged_aml(dsdt
, "\\_SB."GED_DEVICE
,
296 HOTPLUG_HANDLER(lvms
->acpi_ged
),
297 VIRT_SCI_IRQ
, AML_SYSTEM_MEMORY
,
299 event
= object_property_get_uint(OBJECT(lvms
->acpi_ged
),
300 "ged-event", &error_abort
);
301 if (event
& ACPI_GED_MEM_HOTPLUG_EVT
) {
302 build_memory_hotplug_aml(dsdt
, machine
->ram_slots
, "\\_SB", NULL
,
306 acpi_dsdt_add_power_button(dsdt
);
309 static void build_pci_device_aml(Aml
*scope
, LoongArchVirtMachineState
*lvms
)
311 struct GPEXConfig cfg
= {
312 .mmio64
.base
= VIRT_PCI_MEM_BASE
,
313 .mmio64
.size
= VIRT_PCI_MEM_SIZE
,
314 .pio
.base
= VIRT_PCI_IO_BASE
,
315 .pio
.size
= VIRT_PCI_IO_SIZE
,
316 .ecam
.base
= VIRT_PCI_CFG_BASE
,
317 .ecam
.size
= VIRT_PCI_CFG_SIZE
,
318 .irq
= VIRT_GSI_BASE
+ VIRT_DEVICE_IRQS
,
319 .bus
= lvms
->pci_bus
,
322 acpi_dsdt_add_gpex(scope
, &cfg
);
325 static void build_flash_aml(Aml
*scope
, LoongArchVirtMachineState
*lvms
)
328 MemoryRegion
*flash_mem
;
336 flash_mem
= pflash_cfi01_get_memory(lvms
->flash
[0]);
337 flash0_base
= flash_mem
->addr
;
338 flash0_size
= memory_region_size(flash_mem
);
340 flash_mem
= pflash_cfi01_get_memory(lvms
->flash
[1]);
341 flash1_base
= flash_mem
->addr
;
342 flash1_size
= memory_region_size(flash_mem
);
344 dev
= aml_device("FLS0");
345 aml_append(dev
, aml_name_decl("_HID", aml_string("LNRO0015")));
346 aml_append(dev
, aml_name_decl("_UID", aml_int(0)));
348 crs
= aml_resource_template();
349 aml_append(crs
, aml_memory32_fixed(flash0_base
, flash0_size
,
351 aml_append(dev
, aml_name_decl("_CRS", crs
));
352 aml_append(scope
, dev
);
354 dev
= aml_device("FLS1");
355 aml_append(dev
, aml_name_decl("_HID", aml_string("LNRO0015")));
356 aml_append(dev
, aml_name_decl("_UID", aml_int(1)));
358 crs
= aml_resource_template();
359 aml_append(crs
, aml_memory32_fixed(flash1_base
, flash1_size
,
361 aml_append(dev
, aml_name_decl("_CRS", crs
));
362 aml_append(scope
, dev
);
366 static void acpi_dsdt_add_tpm(Aml
*scope
, LoongArchVirtMachineState
*vms
)
368 PlatformBusDevice
*pbus
= PLATFORM_BUS_DEVICE(vms
->platform_bus_dev
);
369 hwaddr pbus_base
= VIRT_PLATFORM_BUS_BASEADDRESS
;
370 SysBusDevice
*sbdev
= SYS_BUS_DEVICE(tpm_find());
371 MemoryRegion
*sbdev_mr
;
378 tpm_base
= platform_bus_get_mmio_addr(pbus
, sbdev
, 0);
379 assert(tpm_base
!= -1);
381 tpm_base
+= pbus_base
;
383 sbdev_mr
= sysbus_mmio_get_region(sbdev
, 0);
385 Aml
*dev
= aml_device("TPM0");
386 aml_append(dev
, aml_name_decl("_HID", aml_string("MSFT0101")));
387 aml_append(dev
, aml_name_decl("_STR", aml_string("TPM 2.0 Device")));
388 aml_append(dev
, aml_name_decl("_UID", aml_int(0)));
390 Aml
*crs
= aml_resource_template();
392 aml_memory32_fixed(tpm_base
,
393 (uint32_t)memory_region_size(sbdev_mr
),
395 aml_append(dev
, aml_name_decl("_CRS", crs
));
396 aml_append(scope
, dev
);
402 build_dsdt(GArray
*table_data
, BIOSLinker
*linker
, MachineState
*machine
)
404 Aml
*dsdt
, *scope
, *pkg
;
405 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(machine
);
406 AcpiTable table
= { .sig
= "DSDT", .rev
= 1, .oem_id
= lvms
->oem_id
,
407 .oem_table_id
= lvms
->oem_table_id
};
409 acpi_table_begin(&table
, table_data
);
410 dsdt
= init_aml_allocator();
411 build_uart_device_aml(dsdt
);
412 build_pci_device_aml(dsdt
, lvms
);
413 build_la_ged_aml(dsdt
, machine
);
414 build_flash_aml(dsdt
, lvms
);
416 acpi_dsdt_add_tpm(dsdt
, lvms
);
418 /* System State Package */
419 scope
= aml_scope("\\");
420 pkg
= aml_package(4);
421 aml_append(pkg
, aml_int(ACPI_GED_SLP_TYP_S5
));
422 aml_append(pkg
, aml_int(0)); /* ignored */
423 aml_append(pkg
, aml_int(0)); /* reserved */
424 aml_append(pkg
, aml_int(0)); /* reserved */
425 aml_append(scope
, aml_name_decl("_S5", pkg
));
426 aml_append(dsdt
, scope
);
427 /* Copy AML table into ACPI tables blob and patch header there */
428 g_array_append_vals(table_data
, dsdt
->buf
->data
, dsdt
->buf
->len
);
429 acpi_table_end(linker
, &table
);
430 free_aml_allocator();
433 static void acpi_build(AcpiBuildTables
*tables
, MachineState
*machine
)
435 LoongArchVirtMachineState
*lvms
= LOONGARCH_VIRT_MACHINE(machine
);
436 GArray
*table_offsets
;
437 AcpiFadtData fadt_data
;
438 unsigned facs
, rsdt
, dsdt
;
440 GArray
*tables_blob
= tables
->table_data
;
442 init_common_fadt_data(&fadt_data
);
444 table_offsets
= g_array_new(false, true, sizeof(uint32_t));
445 ACPI_BUILD_DPRINTF("init ACPI tables\n");
447 bios_linker_loader_alloc(tables
->linker
,
448 ACPI_BUILD_TABLE_FILE
, tables_blob
,
452 * FACS is pointed to by FADT.
453 * We place it first since it's the only table that has alignment
456 facs
= tables_blob
->len
;
457 build_facs(tables_blob
);
459 /* DSDT is pointed to by FADT */
460 dsdt
= tables_blob
->len
;
461 build_dsdt(tables_blob
, tables
->linker
, machine
);
463 /* ACPI tables pointed to by RSDT */
464 acpi_add_table(table_offsets
, tables_blob
);
465 fadt_data
.facs_tbl_offset
= &facs
;
466 fadt_data
.dsdt_tbl_offset
= &dsdt
;
467 fadt_data
.xdsdt_tbl_offset
= &dsdt
;
468 build_fadt(tables_blob
, tables
->linker
, &fadt_data
,
469 lvms
->oem_id
, lvms
->oem_table_id
);
471 acpi_add_table(table_offsets
, tables_blob
);
472 build_madt(tables_blob
, tables
->linker
, lvms
);
474 acpi_add_table(table_offsets
, tables_blob
);
475 build_pptt(tables_blob
, tables
->linker
, machine
,
476 lvms
->oem_id
, lvms
->oem_table_id
);
478 acpi_add_table(table_offsets
, tables_blob
);
479 build_srat(tables_blob
, tables
->linker
, machine
);
481 if (machine
->numa_state
->num_nodes
) {
482 if (machine
->numa_state
->have_numa_distance
) {
483 acpi_add_table(table_offsets
, tables_blob
);
484 build_slit(tables_blob
, tables
->linker
, machine
, lvms
->oem_id
,
487 if (machine
->numa_state
->hmat_enabled
) {
488 acpi_add_table(table_offsets
, tables_blob
);
489 build_hmat(tables_blob
, tables
->linker
, machine
->numa_state
,
490 lvms
->oem_id
, lvms
->oem_table_id
);
494 acpi_add_table(table_offsets
, tables_blob
);
496 AcpiMcfgInfo mcfg
= {
497 .base
= cpu_to_le64(VIRT_PCI_CFG_BASE
),
498 .size
= cpu_to_le64(VIRT_PCI_CFG_SIZE
),
500 build_mcfg(tables_blob
, tables
->linker
, &mcfg
, lvms
->oem_id
,
506 if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0
) {
507 acpi_add_table(table_offsets
, tables_blob
);
508 build_tpm2(tables_blob
, tables
->linker
,
509 tables
->tcpalog
, lvms
->oem_id
,
513 /* Add tables supplied by user (if any) */
514 for (u
= acpi_table_first(); u
; u
= acpi_table_next(u
)) {
515 unsigned len
= acpi_table_len(u
);
517 acpi_add_table(table_offsets
, tables_blob
);
518 g_array_append_vals(tables_blob
, u
, len
);
521 /* RSDT is pointed to by RSDP */
522 rsdt
= tables_blob
->len
;
523 build_rsdt(tables_blob
, tables
->linker
, table_offsets
,
524 lvms
->oem_id
, lvms
->oem_table_id
);
526 /* RSDP is in FSEG memory, so allocate it separately */
528 AcpiRsdpData rsdp_data
= {
530 .oem_id
= lvms
->oem_id
,
531 .xsdt_tbl_offset
= NULL
,
532 .rsdt_tbl_offset
= &rsdt
,
534 build_rsdp(tables
->rsdp
, tables
->linker
, &rsdp_data
);
538 * The align size is 128, warn if 64k is not enough therefore
539 * the align size could be resized.
541 if (tables_blob
->len
> ACPI_BUILD_TABLE_SIZE
/ 2) {
542 warn_report("ACPI table size %u exceeds %d bytes,"
543 " migration may not work",
544 tables_blob
->len
, ACPI_BUILD_TABLE_SIZE
/ 2);
545 error_printf("Try removing CPUs, NUMA nodes, memory slots"
546 " or PCI bridges.\n");
549 acpi_align_size(tables
->linker
->cmd_blob
, ACPI_BUILD_ALIGN_SIZE
);
551 /* Cleanup memory that's no longer used. */
552 g_array_free(table_offsets
, true);
555 static void acpi_ram_update(MemoryRegion
*mr
, GArray
*data
)
557 uint32_t size
= acpi_data_len(data
);
560 * Make sure RAM size is correct - in case it got changed
563 memory_region_ram_resize(mr
, size
, &error_abort
);
565 memcpy(memory_region_get_ram_ptr(mr
), data
->data
, size
);
566 memory_region_set_dirty(mr
, 0, size
);
569 static void acpi_build_update(void *build_opaque
)
571 AcpiBuildState
*build_state
= build_opaque
;
572 AcpiBuildTables tables
;
574 /* No state to update or already patched? Nothing to do. */
575 if (!build_state
|| build_state
->patched
) {
578 build_state
->patched
= 1;
580 acpi_build_tables_init(&tables
);
582 acpi_build(&tables
, MACHINE(qdev_get_machine()));
584 acpi_ram_update(build_state
->table_mr
, tables
.table_data
);
585 acpi_ram_update(build_state
->rsdp_mr
, tables
.rsdp
);
586 acpi_ram_update(build_state
->linker_mr
, tables
.linker
->cmd_blob
);
588 acpi_build_tables_cleanup(&tables
, true);
591 static void acpi_build_reset(void *build_opaque
)
593 AcpiBuildState
*build_state
= build_opaque
;
594 build_state
->patched
= 0;
597 static const VMStateDescription vmstate_acpi_build
= {
598 .name
= "acpi_build",
600 .minimum_version_id
= 1,
601 .fields
= (const VMStateField
[]) {
602 VMSTATE_UINT8(patched
, AcpiBuildState
),
603 VMSTATE_END_OF_LIST()
607 static bool loongarch_is_acpi_enabled(LoongArchVirtMachineState
*lvms
)
609 if (lvms
->acpi
== ON_OFF_AUTO_OFF
) {
615 void loongarch_acpi_setup(LoongArchVirtMachineState
*lvms
)
617 AcpiBuildTables tables
;
618 AcpiBuildState
*build_state
;
621 ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
625 if (!loongarch_is_acpi_enabled(lvms
)) {
626 ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n");
630 build_state
= g_malloc0(sizeof *build_state
);
632 acpi_build_tables_init(&tables
);
633 acpi_build(&tables
, MACHINE(lvms
));
635 /* Now expose it all to Guest */
636 build_state
->table_mr
= acpi_add_rom_blob(acpi_build_update
,
637 build_state
, tables
.table_data
,
638 ACPI_BUILD_TABLE_FILE
);
639 assert(build_state
->table_mr
!= NULL
);
641 build_state
->linker_mr
=
642 acpi_add_rom_blob(acpi_build_update
, build_state
,
643 tables
.linker
->cmd_blob
, ACPI_BUILD_LOADER_FILE
);
645 build_state
->rsdp_mr
= acpi_add_rom_blob(acpi_build_update
,
646 build_state
, tables
.rsdp
,
647 ACPI_BUILD_RSDP_FILE
);
649 fw_cfg_add_file(lvms
->fw_cfg
, ACPI_BUILD_TPMLOG_FILE
, tables
.tcpalog
->data
,
650 acpi_data_len(tables
.tcpalog
));
652 qemu_register_reset(acpi_build_reset
, build_state
);
653 acpi_build_reset(build_state
);
654 vmstate_register(NULL
, 0, &vmstate_acpi_build
, build_state
);
657 * Cleanup tables but don't free the memory: we track it
660 acpi_build_tables_cleanup(&tables
, false);