virt-acpi-build.c (40593B)
1/* Support for generating ACPI tables and passing them to Guests 2 * 3 * ARM virt ACPI generation 4 * 5 * Copyright (C) 2008-2010 Kevin O'Connor <kevin@koconnor.net> 6 * Copyright (C) 2006 Fabrice Bellard 7 * Copyright (C) 2013 Red Hat Inc 8 * 9 * Author: Michael S. Tsirkin <mst@redhat.com> 10 * 11 * Copyright (c) 2015 HUAWEI TECHNOLOGIES CO.,LTD. 12 * 13 * Author: Shannon Zhao <zhaoshenglong@huawei.com> 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License as published by 17 * the Free Software Foundation; either version 2 of the License, or 18 * (at your option) any later version. 19 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 25 * You should have received a copy of the GNU General Public License along 26 * with this program; if not, see <http://www.gnu.org/licenses/>. 27 */ 28 29#include "qemu/osdep.h" 30#include "qapi/error.h" 31#include "qemu/bitmap.h" 32#include "trace.h" 33#include "hw/core/cpu.h" 34#include "target/arm/cpu.h" 35#include "hw/acpi/acpi-defs.h" 36#include "hw/acpi/acpi.h" 37#include "hw/nvram/fw_cfg.h" 38#include "hw/acpi/bios-linker-loader.h" 39#include "hw/acpi/aml-build.h" 40#include "hw/acpi/utils.h" 41#include "hw/acpi/pci.h" 42#include "hw/acpi/memory_hotplug.h" 43#include "hw/acpi/generic_event_device.h" 44#include "hw/acpi/tpm.h" 45#include "hw/pci/pcie_host.h" 46#include "hw/pci/pci.h" 47#include "hw/pci/pci_bus.h" 48#include "hw/pci-host/gpex.h" 49#include "hw/arm/virt.h" 50#include "hw/mem/nvdimm.h" 51#include "hw/platform-bus.h" 52#include "sysemu/numa.h" 53#include "sysemu/reset.h" 54#include "sysemu/tpm.h" 55#include "kvm_arm.h" 56#include "migration/vmstate.h" 57#include "hw/acpi/ghes.h" 58 59#define ARM_SPI_BASE 32 60 61#define ACPI_BUILD_TABLE_SIZE 0x20000 62 63static void acpi_dsdt_add_cpus(Aml *scope, VirtMachineState *vms) 64{ 65 MachineState *ms = MACHINE(vms); 66 uint16_t i; 67 68 for (i = 0; i < ms->smp.cpus; i++) { 69 Aml *dev = aml_device("C%.03X", i); 70 aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0007"))); 71 aml_append(dev, aml_name_decl("_UID", aml_int(i))); 72 aml_append(scope, dev); 73 } 74} 75 76static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, 77 uint32_t uart_irq) 78{ 79 Aml *dev = aml_device("COM0"); 80 aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011"))); 81 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 82 83 Aml *crs = aml_resource_template(); 84 aml_append(crs, aml_memory32_fixed(uart_memmap->base, 85 uart_memmap->size, AML_READ_WRITE)); 86 aml_append(crs, 87 aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, 88 AML_EXCLUSIVE, &uart_irq, 1)); 89 aml_append(dev, aml_name_decl("_CRS", crs)); 90 91 aml_append(scope, dev); 92} 93 94static void acpi_dsdt_add_fw_cfg(Aml *scope, const MemMapEntry *fw_cfg_memmap) 95{ 96 Aml *dev = aml_device("FWCF"); 97 aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); 98 /* device present, functioning, decoding, not shown in UI */ 99 aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); 100 aml_append(dev, aml_name_decl("_CCA", aml_int(1))); 101 102 Aml *crs = aml_resource_template(); 103 aml_append(crs, aml_memory32_fixed(fw_cfg_memmap->base, 104 fw_cfg_memmap->size, AML_READ_WRITE)); 105 aml_append(dev, aml_name_decl("_CRS", crs)); 106 aml_append(scope, dev); 107} 108 109static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) 110{ 111 Aml *dev, *crs; 112 hwaddr base = flash_memmap->base; 113 hwaddr size = flash_memmap->size / 2; 114 115 dev = aml_device("FLS0"); 116 aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); 117 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 118 119 crs = aml_resource_template(); 120 aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); 121 aml_append(dev, aml_name_decl("_CRS", crs)); 122 aml_append(scope, dev); 123 124 dev = aml_device("FLS1"); 125 aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); 126 aml_append(dev, aml_name_decl("_UID", aml_int(1))); 127 crs = aml_resource_template(); 128 aml_append(crs, aml_memory32_fixed(base + size, size, AML_READ_WRITE)); 129 aml_append(dev, aml_name_decl("_CRS", crs)); 130 aml_append(scope, dev); 131} 132 133static void acpi_dsdt_add_virtio(Aml *scope, 134 const MemMapEntry *virtio_mmio_memmap, 135 uint32_t mmio_irq, int num) 136{ 137 hwaddr base = virtio_mmio_memmap->base; 138 hwaddr size = virtio_mmio_memmap->size; 139 int i; 140 141 for (i = 0; i < num; i++) { 142 uint32_t irq = mmio_irq + i; 143 Aml *dev = aml_device("VR%02u", i); 144 aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); 145 aml_append(dev, aml_name_decl("_UID", aml_int(i))); 146 aml_append(dev, aml_name_decl("_CCA", aml_int(1))); 147 148 Aml *crs = aml_resource_template(); 149 aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); 150 aml_append(crs, 151 aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, 152 AML_EXCLUSIVE, &irq, 1)); 153 aml_append(dev, aml_name_decl("_CRS", crs)); 154 aml_append(scope, dev); 155 base += size; 156 } 157} 158 159static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, 160 uint32_t irq, bool use_highmem, bool highmem_ecam, 161 VirtMachineState *vms) 162{ 163 int ecam_id = VIRT_ECAM_ID(highmem_ecam); 164 struct GPEXConfig cfg = { 165 .mmio32 = memmap[VIRT_PCIE_MMIO], 166 .pio = memmap[VIRT_PCIE_PIO], 167 .ecam = memmap[ecam_id], 168 .irq = irq, 169 .bus = vms->bus, 170 }; 171 172 if (use_highmem) { 173 cfg.mmio64 = memmap[VIRT_HIGH_PCIE_MMIO]; 174 } 175 176 acpi_dsdt_add_gpex(scope, &cfg); 177} 178 179static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap, 180 uint32_t gpio_irq) 181{ 182 Aml *dev = aml_device("GPO0"); 183 aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0061"))); 184 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 185 186 Aml *crs = aml_resource_template(); 187 aml_append(crs, aml_memory32_fixed(gpio_memmap->base, gpio_memmap->size, 188 AML_READ_WRITE)); 189 aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, 190 AML_EXCLUSIVE, &gpio_irq, 1)); 191 aml_append(dev, aml_name_decl("_CRS", crs)); 192 193 Aml *aei = aml_resource_template(); 194 /* Pin 3 for power button */ 195 const uint32_t pin_list[1] = {3}; 196 aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH, 197 AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1, 198 "GPO0", NULL, 0)); 199 aml_append(dev, aml_name_decl("_AEI", aei)); 200 201 /* _E03 is handle for power button */ 202 Aml *method = aml_method("_E03", 0, AML_NOTSERIALIZED); 203 aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE), 204 aml_int(0x80))); 205 aml_append(dev, method); 206 aml_append(scope, dev); 207} 208 209#ifdef CONFIG_TPM 210static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms) 211{ 212 PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); 213 hwaddr pbus_base = vms->memmap[VIRT_PLATFORM_BUS].base; 214 SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find()); 215 MemoryRegion *sbdev_mr; 216 hwaddr tpm_base; 217 218 if (!sbdev) { 219 return; 220 } 221 222 tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); 223 assert(tpm_base != -1); 224 225 tpm_base += pbus_base; 226 227 sbdev_mr = sysbus_mmio_get_region(sbdev, 0); 228 229 Aml *dev = aml_device("TPM0"); 230 aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); 231 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 232 233 Aml *crs = aml_resource_template(); 234 aml_append(crs, 235 aml_memory32_fixed(tpm_base, 236 (uint32_t)memory_region_size(sbdev_mr), 237 AML_READ_WRITE)); 238 aml_append(dev, aml_name_decl("_CRS", crs)); 239 aml_append(scope, dev); 240} 241#endif 242 243#define ID_MAPPING_ENTRY_SIZE 20 244#define SMMU_V3_ENTRY_SIZE 60 245#define ROOT_COMPLEX_ENTRY_SIZE 32 246#define IORT_NODE_OFFSET 48 247 248static void build_iort_id_mapping(GArray *table_data, uint32_t input_base, 249 uint32_t id_count, uint32_t out_ref) 250{ 251 /* Identity RID mapping covering the whole input RID range */ 252 build_append_int_noprefix(table_data, input_base, 4); /* Input base */ 253 build_append_int_noprefix(table_data, id_count, 4); /* Number of IDs */ 254 build_append_int_noprefix(table_data, input_base, 4); /* Output base */ 255 build_append_int_noprefix(table_data, out_ref, 4); /* Output Reference */ 256 build_append_int_noprefix(table_data, 0, 4); /* Flags */ 257} 258 259struct AcpiIortIdMapping { 260 uint32_t input_base; 261 uint32_t id_count; 262}; 263typedef struct AcpiIortIdMapping AcpiIortIdMapping; 264 265/* Build the iort ID mapping to SMMUv3 for a given PCI host bridge */ 266static int 267iort_host_bridges(Object *obj, void *opaque) 268{ 269 GArray *idmap_blob = opaque; 270 271 if (object_dynamic_cast(obj, TYPE_PCI_HOST_BRIDGE)) { 272 PCIBus *bus = PCI_HOST_BRIDGE(obj)->bus; 273 274 if (bus && !pci_bus_bypass_iommu(bus)) { 275 int min_bus, max_bus; 276 277 pci_bus_range(bus, &min_bus, &max_bus); 278 279 AcpiIortIdMapping idmap = { 280 .input_base = min_bus << 8, 281 .id_count = (max_bus - min_bus + 1) << 8, 282 }; 283 g_array_append_val(idmap_blob, idmap); 284 } 285 } 286 287 return 0; 288} 289 290static int iort_idmap_compare(gconstpointer a, gconstpointer b) 291{ 292 AcpiIortIdMapping *idmap_a = (AcpiIortIdMapping *)a; 293 AcpiIortIdMapping *idmap_b = (AcpiIortIdMapping *)b; 294 295 return idmap_a->input_base - idmap_b->input_base; 296} 297 298/* 299 * Input Output Remapping Table (IORT) 300 * Conforms to "IO Remapping Table System Software on ARM Platforms", 301 * Document number: ARM DEN 0049B, October 2015 302 */ 303static void 304build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) 305{ 306 int i, nb_nodes, rc_mapping_count; 307 const uint32_t iort_node_offset = IORT_NODE_OFFSET; 308 size_t node_size, smmu_offset = 0; 309 AcpiIortIdMapping *idmap; 310 GArray *smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); 311 GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); 312 313 AcpiTable table = { .sig = "IORT", .rev = 0, .oem_id = vms->oem_id, 314 .oem_table_id = vms->oem_table_id }; 315 /* Table 2 The IORT */ 316 acpi_table_begin(&table, table_data); 317 318 if (vms->iommu == VIRT_IOMMU_SMMUV3) { 319 AcpiIortIdMapping next_range = {0}; 320 321 object_child_foreach_recursive(object_get_root(), 322 iort_host_bridges, smmu_idmaps); 323 324 /* Sort the smmu idmap by input_base */ 325 g_array_sort(smmu_idmaps, iort_idmap_compare); 326 327 /* 328 * Split the whole RIDs by mapping from RC to SMMU, 329 * build the ID mapping from RC to ITS directly. 330 */ 331 for (i = 0; i < smmu_idmaps->len; i++) { 332 idmap = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i); 333 334 if (next_range.input_base < idmap->input_base) { 335 next_range.id_count = idmap->input_base - next_range.input_base; 336 g_array_append_val(its_idmaps, next_range); 337 } 338 339 next_range.input_base = idmap->input_base + idmap->id_count; 340 } 341 342 /* Append the last RC -> ITS ID mapping */ 343 if (next_range.input_base < 0xFFFF) { 344 next_range.id_count = 0xFFFF - next_range.input_base; 345 g_array_append_val(its_idmaps, next_range); 346 } 347 348 nb_nodes = 3; /* RC, ITS, SMMUv3 */ 349 rc_mapping_count = smmu_idmaps->len + its_idmaps->len; 350 } else { 351 nb_nodes = 2; /* RC, ITS */ 352 rc_mapping_count = 1; 353 } 354 /* Number of IORT Nodes */ 355 build_append_int_noprefix(table_data, nb_nodes, 4); 356 357 /* Offset to Array of IORT Nodes */ 358 build_append_int_noprefix(table_data, IORT_NODE_OFFSET, 4); 359 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 360 361 /* 3.1.1.3 ITS group node */ 362 build_append_int_noprefix(table_data, 0 /* ITS Group */, 1); /* Type */ 363 node_size = 20 /* fixed header size */ + 4 /* 1 GIC ITS Identifier */; 364 build_append_int_noprefix(table_data, node_size, 2); /* Length */ 365 build_append_int_noprefix(table_data, 0, 1); /* Revision */ 366 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 367 build_append_int_noprefix(table_data, 0, 4); /* Number of ID mappings */ 368 build_append_int_noprefix(table_data, 0, 4); /* Reference to ID Array */ 369 build_append_int_noprefix(table_data, 1, 4); /* Number of ITSs */ 370 /* GIC ITS Identifier Array */ 371 build_append_int_noprefix(table_data, 0 /* MADT translation_id */, 4); 372 373 if (vms->iommu == VIRT_IOMMU_SMMUV3) { 374 int irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE; 375 376 smmu_offset = table_data->len - table.table_offset; 377 /* 3.1.1.2 SMMUv3 */ 378 build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type */ 379 node_size = SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE; 380 build_append_int_noprefix(table_data, node_size, 2); /* Length */ 381 build_append_int_noprefix(table_data, 0, 1); /* Revision */ 382 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 383 build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */ 384 /* Reference to ID Array */ 385 build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4); 386 /* Base address */ 387 build_append_int_noprefix(table_data, vms->memmap[VIRT_SMMU].base, 8); 388 /* Flags */ 389 build_append_int_noprefix(table_data, 1 /* COHACC OverrideNote */, 4); 390 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 391 build_append_int_noprefix(table_data, 0, 8); /* VATOS address */ 392 /* Model */ 393 build_append_int_noprefix(table_data, 0 /* Generic SMMU-v3 */, 4); 394 build_append_int_noprefix(table_data, irq, 4); /* Event */ 395 build_append_int_noprefix(table_data, irq + 1, 4); /* PRI */ 396 build_append_int_noprefix(table_data, irq + 3, 4); /* GERR */ 397 build_append_int_noprefix(table_data, irq + 2, 4); /* Sync */ 398 399 /* output IORT node is the ITS group node (the first node) */ 400 build_iort_id_mapping(table_data, 0, 0xFFFF, IORT_NODE_OFFSET); 401 } 402 403 /* Table 16 Root Complex Node */ 404 build_append_int_noprefix(table_data, 2 /* Root complex */, 1); /* Type */ 405 node_size = ROOT_COMPLEX_ENTRY_SIZE + 406 ID_MAPPING_ENTRY_SIZE * rc_mapping_count; 407 build_append_int_noprefix(table_data, node_size, 2); /* Length */ 408 build_append_int_noprefix(table_data, 0, 1); /* Revision */ 409 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 410 /* Number of ID mappings */ 411 build_append_int_noprefix(table_data, rc_mapping_count, 4); 412 /* Reference to ID Array */ 413 build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 4); 414 415 /* Table 13 Memory access properties */ 416 /* CCA: Cache Coherent Attribute */ 417 build_append_int_noprefix(table_data, 1 /* fully coherent */, 4); 418 build_append_int_noprefix(table_data, 0, 1); /* AH: Note Allocation Hints */ 419 build_append_int_noprefix(table_data, 0, 2); /* Reserved */ 420 /* MAF: Note Memory Access Flags */ 421 build_append_int_noprefix(table_data, 0x3 /* CCA = CPM = DCAS = 1 */, 1); 422 423 build_append_int_noprefix(table_data, 0, 4); /* ATS Attribute */ 424 /* MCFG pci_segment */ 425 build_append_int_noprefix(table_data, 0, 4); /* PCI Segment number */ 426 427 /* Output Reference */ 428 if (vms->iommu == VIRT_IOMMU_SMMUV3) { 429 AcpiIortIdMapping *range; 430 431 /* translated RIDs connect to SMMUv3 node: RC -> SMMUv3 -> ITS */ 432 for (i = 0; i < smmu_idmaps->len; i++) { 433 range = &g_array_index(smmu_idmaps, AcpiIortIdMapping, i); 434 /* output IORT node is the smmuv3 node */ 435 build_iort_id_mapping(table_data, range->input_base, 436 range->id_count, smmu_offset); 437 } 438 439 /* bypassed RIDs connect to ITS group node directly: RC -> ITS */ 440 for (i = 0; i < its_idmaps->len; i++) { 441 range = &g_array_index(its_idmaps, AcpiIortIdMapping, i); 442 /* output IORT node is the ITS group node (the first node) */ 443 build_iort_id_mapping(table_data, range->input_base, 444 range->id_count, iort_node_offset); 445 } 446 } else { 447 /* output IORT node is the ITS group node (the first node) */ 448 build_iort_id_mapping(table_data, 0, 0xFFFF, IORT_NODE_OFFSET); 449 } 450 451 acpi_table_end(linker, &table); 452 g_array_free(smmu_idmaps, true); 453 g_array_free(its_idmaps, true); 454} 455 456/* 457 * Serial Port Console Redirection Table (SPCR) 458 * Rev: 1.07 459 */ 460static void 461build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) 462{ 463 AcpiTable table = { .sig = "SPCR", .rev = 2, .oem_id = vms->oem_id, 464 .oem_table_id = vms->oem_table_id }; 465 466 acpi_table_begin(&table, table_data); 467 468 /* Interface Type */ 469 build_append_int_noprefix(table_data, 3, 1); /* ARM PL011 UART */ 470 build_append_int_noprefix(table_data, 0, 3); /* Reserved */ 471 /* Base Address */ 472 build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 8, 0, 1, 473 vms->memmap[VIRT_UART].base); 474 /* Interrupt Type */ 475 build_append_int_noprefix(table_data, 476 (1 << 3) /* Bit[3] ARMH GIC interrupt */, 1); 477 build_append_int_noprefix(table_data, 0, 1); /* IRQ */ 478 /* Global System Interrupt */ 479 build_append_int_noprefix(table_data, 480 vms->irqmap[VIRT_UART] + ARM_SPI_BASE, 4); 481 build_append_int_noprefix(table_data, 3 /* 9600 */, 1); /* Baud Rate */ 482 build_append_int_noprefix(table_data, 0 /* No Parity */, 1); /* Parity */ 483 /* Stop Bits */ 484 build_append_int_noprefix(table_data, 1 /* 1 Stop bit */, 1); 485 /* Flow Control */ 486 build_append_int_noprefix(table_data, 487 (1 << 1) /* RTS/CTS hardware flow control */, 1); 488 /* Terminal Type */ 489 build_append_int_noprefix(table_data, 0 /* VT100 */, 1); 490 build_append_int_noprefix(table_data, 0, 1); /* Language */ 491 /* PCI Device ID */ 492 build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2); 493 /* PCI Vendor ID */ 494 build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2); 495 build_append_int_noprefix(table_data, 0, 1); /* PCI Bus Number */ 496 build_append_int_noprefix(table_data, 0, 1); /* PCI Device Number */ 497 build_append_int_noprefix(table_data, 0, 1); /* PCI Function Number */ 498 build_append_int_noprefix(table_data, 0, 4); /* PCI Flags */ 499 build_append_int_noprefix(table_data, 0, 1); /* PCI Segment */ 500 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 501 502 acpi_table_end(linker, &table); 503} 504 505/* 506 * ACPI spec, Revision 5.1 507 * 5.2.16 System Resource Affinity Table (SRAT) 508 */ 509static void 510build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) 511{ 512 int i; 513 uint64_t mem_base; 514 MachineClass *mc = MACHINE_GET_CLASS(vms); 515 MachineState *ms = MACHINE(vms); 516 const CPUArchIdList *cpu_list = mc->possible_cpu_arch_ids(ms); 517 AcpiTable table = { .sig = "SRAT", .rev = 3, .oem_id = vms->oem_id, 518 .oem_table_id = vms->oem_table_id }; 519 520 acpi_table_begin(&table, table_data); 521 build_append_int_noprefix(table_data, 1, 4); /* Reserved */ 522 build_append_int_noprefix(table_data, 0, 8); /* Reserved */ 523 524 for (i = 0; i < cpu_list->len; ++i) { 525 uint32_t nodeid = cpu_list->cpus[i].props.node_id; 526 /* 527 * 5.2.16.4 GICC Affinity Structure 528 */ 529 build_append_int_noprefix(table_data, 3, 1); /* Type */ 530 build_append_int_noprefix(table_data, 18, 1); /* Length */ 531 build_append_int_noprefix(table_data, nodeid, 4); /* Proximity Domain */ 532 build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ 533 /* Flags, Table 5-76 */ 534 build_append_int_noprefix(table_data, 1 /* Enabled */, 4); 535 build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */ 536 } 537 538 mem_base = vms->memmap[VIRT_MEM].base; 539 for (i = 0; i < ms->numa_state->num_nodes; ++i) { 540 if (ms->numa_state->nodes[i].node_mem > 0) { 541 build_srat_memory(table_data, mem_base, 542 ms->numa_state->nodes[i].node_mem, i, 543 MEM_AFFINITY_ENABLED); 544 mem_base += ms->numa_state->nodes[i].node_mem; 545 } 546 } 547 548 if (ms->nvdimms_state->is_enabled) { 549 nvdimm_build_srat(table_data); 550 } 551 552 if (ms->device_memory) { 553 build_srat_memory(table_data, ms->device_memory->base, 554 memory_region_size(&ms->device_memory->mr), 555 ms->numa_state->num_nodes - 1, 556 MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); 557 } 558 559 acpi_table_end(linker, &table); 560} 561 562/* 563 * ACPI spec, Revision 5.1 564 * 5.2.24 Generic Timer Description Table (GTDT) 565 */ 566static void 567build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) 568{ 569 VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); 570 /* 571 * Table 5-117 Flag Definitions 572 * set only "Timer interrupt Mode" and assume "Timer Interrupt 573 * polarity" bit as '0: Interrupt is Active high' 574 */ 575 uint32_t irqflags = vmc->claim_edge_triggered_timers ? 576 1 : /* Interrupt is Edge triggered */ 577 0; /* Interrupt is Level triggered */ 578 AcpiTable table = { .sig = "GTDT", .rev = 2, .oem_id = vms->oem_id, 579 .oem_table_id = vms->oem_table_id }; 580 581 acpi_table_begin(&table, table_data); 582 583 /* CntControlBase Physical Address */ 584 /* FIXME: invalid value, should be 0xFFFFFFFFFFFFFFFF if not impl. ? */ 585 build_append_int_noprefix(table_data, 0, 8); 586 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 587 /* 588 * FIXME: clarify comment: 589 * The interrupt values are the same with the device tree when adding 16 590 */ 591 /* Secure EL1 timer GSIV */ 592 build_append_int_noprefix(table_data, ARCH_TIMER_S_EL1_IRQ + 16, 4); 593 /* Secure EL1 timer Flags */ 594 build_append_int_noprefix(table_data, irqflags, 4); 595 /* Non-Secure EL1 timer GSIV */ 596 build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL1_IRQ + 16, 4); 597 /* Non-Secure EL1 timer Flags */ 598 build_append_int_noprefix(table_data, irqflags | 599 1UL << 2, /* Always-on Capability */ 600 4); 601 /* Virtual timer GSIV */ 602 build_append_int_noprefix(table_data, ARCH_TIMER_VIRT_IRQ + 16, 4); 603 /* Virtual Timer Flags */ 604 build_append_int_noprefix(table_data, irqflags, 4); 605 /* Non-Secure EL2 timer GSIV */ 606 build_append_int_noprefix(table_data, ARCH_TIMER_NS_EL2_IRQ + 16, 4); 607 /* Non-Secure EL2 timer Flags */ 608 build_append_int_noprefix(table_data, irqflags, 4); 609 /* CntReadBase Physical address */ 610 build_append_int_noprefix(table_data, 0, 8); 611 /* Platform Timer Count */ 612 build_append_int_noprefix(table_data, 0, 4); 613 /* Platform Timer Offset */ 614 build_append_int_noprefix(table_data, 0, 4); 615 616 acpi_table_end(linker, &table); 617} 618 619/* 620 * ACPI spec, Revision 5.1 Errata A 621 * 5.2.12 Multiple APIC Description Table (MADT) 622 */ 623static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size) 624{ 625 build_append_int_noprefix(table_data, 0xE, 1); /* Type */ 626 build_append_int_noprefix(table_data, 16, 1); /* Length */ 627 build_append_int_noprefix(table_data, 0, 2); /* Reserved */ 628 /* Discovery Range Base Addres */ 629 build_append_int_noprefix(table_data, base, 8); 630 build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */ 631} 632 633static void 634build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) 635{ 636 int i; 637 VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); 638 const MemMapEntry *memmap = vms->memmap; 639 AcpiTable table = { .sig = "APIC", .rev = 3, .oem_id = vms->oem_id, 640 .oem_table_id = vms->oem_table_id }; 641 642 acpi_table_begin(&table, table_data); 643 /* Local Interrupt Controller Address */ 644 build_append_int_noprefix(table_data, 0, 4); 645 build_append_int_noprefix(table_data, 0, 4); /* Flags */ 646 647 /* 5.2.12.15 GIC Distributor Structure */ 648 build_append_int_noprefix(table_data, 0xC, 1); /* Type */ 649 build_append_int_noprefix(table_data, 24, 1); /* Length */ 650 build_append_int_noprefix(table_data, 0, 2); /* Reserved */ 651 build_append_int_noprefix(table_data, 0, 4); /* GIC ID */ 652 /* Physical Base Address */ 653 build_append_int_noprefix(table_data, memmap[VIRT_GIC_DIST].base, 8); 654 build_append_int_noprefix(table_data, 0, 4); /* System Vector Base */ 655 /* GIC version */ 656 build_append_int_noprefix(table_data, vms->gic_version, 1); 657 build_append_int_noprefix(table_data, 0, 3); /* Reserved */ 658 659 for (i = 0; i < MACHINE(vms)->smp.cpus; i++) { 660 ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(i)); 661 uint64_t physical_base_address = 0, gich = 0, gicv = 0; 662 uint32_t vgic_interrupt = vms->virt ? PPI(ARCH_GIC_MAINT_IRQ) : 0; 663 uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? 664 PPI(VIRTUAL_PMU_IRQ) : 0; 665 666 if (vms->gic_version == 2) { 667 physical_base_address = memmap[VIRT_GIC_CPU].base; 668 gicv = memmap[VIRT_GIC_VCPU].base; 669 gich = memmap[VIRT_GIC_HYP].base; 670 } 671 672 /* 5.2.12.14 GIC Structure */ 673 build_append_int_noprefix(table_data, 0xB, 1); /* Type */ 674 build_append_int_noprefix(table_data, 76, 1); /* Length */ 675 build_append_int_noprefix(table_data, 0, 2); /* Reserved */ 676 build_append_int_noprefix(table_data, i, 4); /* GIC ID */ 677 build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ 678 /* Flags */ 679 build_append_int_noprefix(table_data, 1, 4); /* Enabled */ 680 /* Parking Protocol Version */ 681 build_append_int_noprefix(table_data, 0, 4); 682 /* Performance Interrupt GSIV */ 683 build_append_int_noprefix(table_data, pmu_interrupt, 4); 684 build_append_int_noprefix(table_data, 0, 8); /* Parked Address */ 685 /* Physical Base Address */ 686 build_append_int_noprefix(table_data, physical_base_address, 8); 687 build_append_int_noprefix(table_data, gicv, 8); /* GICV */ 688 build_append_int_noprefix(table_data, gich, 8); /* GICH */ 689 /* VGIC Maintenance interrupt */ 690 build_append_int_noprefix(table_data, vgic_interrupt, 4); 691 build_append_int_noprefix(table_data, 0, 8); /* GICR Base Address*/ 692 /* MPIDR */ 693 build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); 694 } 695 696 if (vms->gic_version == 3) { 697 build_append_gicr(table_data, memmap[VIRT_GIC_REDIST].base, 698 memmap[VIRT_GIC_REDIST].size); 699 if (virt_gicv3_redist_region_count(vms) == 2) { 700 build_append_gicr(table_data, memmap[VIRT_HIGH_GIC_REDIST2].base, 701 memmap[VIRT_HIGH_GIC_REDIST2].size); 702 } 703 704 if (its_class_name() && !vmc->no_its) { 705 /* 706 * FIXME: Structure is from Revision 6.0 where 'GIC Structure' 707 * has additional fields on top of implemented 5.1 Errata A, 708 * to make it consistent with v6.0 we need to bump everything 709 * to v6.0 710 */ 711 /* 712 * ACPI spec, Revision 6.0 Errata A 713 * (original 6.0 definition has invalid Length) 714 * 5.2.12.18 GIC ITS Structure 715 */ 716 build_append_int_noprefix(table_data, 0xF, 1); /* Type */ 717 build_append_int_noprefix(table_data, 20, 1); /* Length */ 718 build_append_int_noprefix(table_data, 0, 2); /* Reserved */ 719 build_append_int_noprefix(table_data, 0, 4); /* GIC ITS ID */ 720 /* Physical Base Address */ 721 build_append_int_noprefix(table_data, memmap[VIRT_GIC_ITS].base, 8); 722 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 723 } 724 } else { 725 const uint16_t spi_base = vms->irqmap[VIRT_GIC_V2M] + ARM_SPI_BASE; 726 727 /* 5.2.12.16 GIC MSI Frame Structure */ 728 build_append_int_noprefix(table_data, 0xD, 1); /* Type */ 729 build_append_int_noprefix(table_data, 24, 1); /* Length */ 730 build_append_int_noprefix(table_data, 0, 2); /* Reserved */ 731 build_append_int_noprefix(table_data, 0, 4); /* GIC MSI Frame ID */ 732 /* Physical Base Address */ 733 build_append_int_noprefix(table_data, memmap[VIRT_GIC_V2M].base, 8); 734 build_append_int_noprefix(table_data, 1, 4); /* Flags */ 735 /* SPI Count */ 736 build_append_int_noprefix(table_data, NUM_GICV2M_SPIS, 2); 737 build_append_int_noprefix(table_data, spi_base, 2); /* SPI Base */ 738 } 739 acpi_table_end(linker, &table); 740} 741 742/* FADT */ 743static void build_fadt_rev5(GArray *table_data, BIOSLinker *linker, 744 VirtMachineState *vms, unsigned dsdt_tbl_offset) 745{ 746 /* ACPI v5.1 */ 747 AcpiFadtData fadt = { 748 .rev = 5, 749 .minor_ver = 1, 750 .flags = 1 << ACPI_FADT_F_HW_REDUCED_ACPI, 751 .xdsdt_tbl_offset = &dsdt_tbl_offset, 752 }; 753 754 switch (vms->psci_conduit) { 755 case QEMU_PSCI_CONDUIT_DISABLED: 756 fadt.arm_boot_arch = 0; 757 break; 758 case QEMU_PSCI_CONDUIT_HVC: 759 fadt.arm_boot_arch = ACPI_FADT_ARM_PSCI_COMPLIANT | 760 ACPI_FADT_ARM_PSCI_USE_HVC; 761 break; 762 case QEMU_PSCI_CONDUIT_SMC: 763 fadt.arm_boot_arch = ACPI_FADT_ARM_PSCI_COMPLIANT; 764 break; 765 default: 766 g_assert_not_reached(); 767 } 768 769 build_fadt(table_data, linker, &fadt, vms->oem_id, vms->oem_table_id); 770} 771 772/* DSDT */ 773static void 774build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) 775{ 776 VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); 777 Aml *scope, *dsdt; 778 MachineState *ms = MACHINE(vms); 779 const MemMapEntry *memmap = vms->memmap; 780 const int *irqmap = vms->irqmap; 781 AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = vms->oem_id, 782 .oem_table_id = vms->oem_table_id }; 783 784 acpi_table_begin(&table, table_data); 785 dsdt = init_aml_allocator(); 786 787 /* When booting the VM with UEFI, UEFI takes ownership of the RTC hardware. 788 * While UEFI can use libfdt to disable the RTC device node in the DTB that 789 * it passes to the OS, it cannot modify AML. Therefore, we won't generate 790 * the RTC ACPI device at all when using UEFI. 791 */ 792 scope = aml_scope("\\_SB"); 793 acpi_dsdt_add_cpus(scope, vms); 794 acpi_dsdt_add_uart(scope, &memmap[VIRT_UART], 795 (irqmap[VIRT_UART] + ARM_SPI_BASE)); 796 if (vmc->acpi_expose_flash) { 797 acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); 798 } 799 acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); 800 acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], 801 (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); 802 acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE), 803 vms->highmem, vms->highmem_ecam, vms); 804 if (vms->acpi_dev) { 805 build_ged_aml(scope, "\\_SB."GED_DEVICE, 806 HOTPLUG_HANDLER(vms->acpi_dev), 807 irqmap[VIRT_ACPI_GED] + ARM_SPI_BASE, AML_SYSTEM_MEMORY, 808 memmap[VIRT_ACPI_GED].base); 809 } else { 810 acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO], 811 (irqmap[VIRT_GPIO] + ARM_SPI_BASE)); 812 } 813 814 if (vms->acpi_dev) { 815 uint32_t event = object_property_get_uint(OBJECT(vms->acpi_dev), 816 "ged-event", &error_abort); 817 818 if (event & ACPI_GED_MEM_HOTPLUG_EVT) { 819 build_memory_hotplug_aml(scope, ms->ram_slots, "\\_SB", NULL, 820 AML_SYSTEM_MEMORY, 821 memmap[VIRT_PCDIMM_ACPI].base); 822 } 823 } 824 825 acpi_dsdt_add_power_button(scope); 826#ifdef CONFIG_TPM 827 acpi_dsdt_add_tpm(scope, vms); 828#endif 829 830 aml_append(dsdt, scope); 831 832 /* copy AML table into ACPI tables blob */ 833 g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); 834 835 acpi_table_end(linker, &table); 836 free_aml_allocator(); 837} 838 839typedef 840struct AcpiBuildState { 841 /* Copy of table in RAM (for patching). */ 842 MemoryRegion *table_mr; 843 MemoryRegion *rsdp_mr; 844 MemoryRegion *linker_mr; 845 /* Is table patched? */ 846 bool patched; 847} AcpiBuildState; 848 849static void acpi_align_size(GArray *blob, unsigned align) 850{ 851 /* 852 * Align size to multiple of given size. This reduces the chance 853 * we need to change size in the future (breaking cross version migration). 854 */ 855 g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); 856} 857 858static 859void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) 860{ 861 VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); 862 GArray *table_offsets; 863 unsigned dsdt, xsdt; 864 GArray *tables_blob = tables->table_data; 865 MachineState *ms = MACHINE(vms); 866 867 table_offsets = g_array_new(false, true /* clear */, 868 sizeof(uint32_t)); 869 870 bios_linker_loader_alloc(tables->linker, 871 ACPI_BUILD_TABLE_FILE, tables_blob, 872 64, false /* high memory */); 873 874 /* DSDT is pointed to by FADT */ 875 dsdt = tables_blob->len; 876 build_dsdt(tables_blob, tables->linker, vms); 877 878 /* FADT MADT GTDT MCFG SPCR pointed to by RSDT */ 879 acpi_add_table(table_offsets, tables_blob); 880 build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); 881 882 acpi_add_table(table_offsets, tables_blob); 883 build_madt(tables_blob, tables->linker, vms); 884 885 acpi_add_table(table_offsets, tables_blob); 886 build_gtdt(tables_blob, tables->linker, vms); 887 888 acpi_add_table(table_offsets, tables_blob); 889 { 890 AcpiMcfgInfo mcfg = { 891 .base = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].base, 892 .size = vms->memmap[VIRT_ECAM_ID(vms->highmem_ecam)].size, 893 }; 894 build_mcfg(tables_blob, tables->linker, &mcfg, vms->oem_id, 895 vms->oem_table_id); 896 } 897 898 acpi_add_table(table_offsets, tables_blob); 899 build_spcr(tables_blob, tables->linker, vms); 900 901 if (vms->ras) { 902 build_ghes_error_table(tables->hardware_errors, tables->linker); 903 acpi_add_table(table_offsets, tables_blob); 904 acpi_build_hest(tables_blob, tables->linker, vms->oem_id, 905 vms->oem_table_id); 906 } 907 908 if (ms->numa_state->num_nodes > 0) { 909 acpi_add_table(table_offsets, tables_blob); 910 build_srat(tables_blob, tables->linker, vms); 911 if (ms->numa_state->have_numa_distance) { 912 acpi_add_table(table_offsets, tables_blob); 913 build_slit(tables_blob, tables->linker, ms, vms->oem_id, 914 vms->oem_table_id); 915 } 916 } 917 918 if (ms->nvdimms_state->is_enabled) { 919 nvdimm_build_acpi(table_offsets, tables_blob, tables->linker, 920 ms->nvdimms_state, ms->ram_slots, vms->oem_id, 921 vms->oem_table_id); 922 } 923 924 if (its_class_name() && !vmc->no_its) { 925 acpi_add_table(table_offsets, tables_blob); 926 build_iort(tables_blob, tables->linker, vms); 927 } 928 929#ifdef CONFIG_TPM 930 if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) { 931 acpi_add_table(table_offsets, tables_blob); 932 build_tpm2(tables_blob, tables->linker, tables->tcpalog, vms->oem_id, 933 vms->oem_table_id); 934 } 935#endif 936 937 /* XSDT is pointed to by RSDP */ 938 xsdt = tables_blob->len; 939 build_xsdt(tables_blob, tables->linker, table_offsets, vms->oem_id, 940 vms->oem_table_id); 941 942 /* RSDP is in FSEG memory, so allocate it separately */ 943 { 944 AcpiRsdpData rsdp_data = { 945 .revision = 2, 946 .oem_id = vms->oem_id, 947 .xsdt_tbl_offset = &xsdt, 948 .rsdt_tbl_offset = NULL, 949 }; 950 build_rsdp(tables->rsdp, tables->linker, &rsdp_data); 951 } 952 953 /* 954 * The align size is 128, warn if 64k is not enough therefore 955 * the align size could be resized. 956 */ 957 if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) { 958 warn_report("ACPI table size %u exceeds %d bytes," 959 " migration may not work", 960 tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2); 961 error_printf("Try removing CPUs, NUMA nodes, memory slots" 962 " or PCI bridges."); 963 } 964 acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE); 965 966 967 /* Cleanup memory that's no longer used. */ 968 g_array_free(table_offsets, true); 969} 970 971static void acpi_ram_update(MemoryRegion *mr, GArray *data) 972{ 973 uint32_t size = acpi_data_len(data); 974 975 /* Make sure RAM size is correct - in case it got changed 976 * e.g. by migration */ 977 memory_region_ram_resize(mr, size, &error_abort); 978 979 memcpy(memory_region_get_ram_ptr(mr), data->data, size); 980 memory_region_set_dirty(mr, 0, size); 981} 982 983static void virt_acpi_build_update(void *build_opaque) 984{ 985 AcpiBuildState *build_state = build_opaque; 986 AcpiBuildTables tables; 987 988 /* No state to update or already patched? Nothing to do. */ 989 if (!build_state || build_state->patched) { 990 return; 991 } 992 build_state->patched = true; 993 994 acpi_build_tables_init(&tables); 995 996 virt_acpi_build(VIRT_MACHINE(qdev_get_machine()), &tables); 997 998 acpi_ram_update(build_state->table_mr, tables.table_data); 999 acpi_ram_update(build_state->rsdp_mr, tables.rsdp); 1000 acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob); 1001 1002 acpi_build_tables_cleanup(&tables, true); 1003} 1004 1005static void virt_acpi_build_reset(void *build_opaque) 1006{ 1007 AcpiBuildState *build_state = build_opaque; 1008 build_state->patched = false; 1009} 1010 1011static const VMStateDescription vmstate_virt_acpi_build = { 1012 .name = "virt_acpi_build", 1013 .version_id = 1, 1014 .minimum_version_id = 1, 1015 .fields = (VMStateField[]) { 1016 VMSTATE_BOOL(patched, AcpiBuildState), 1017 VMSTATE_END_OF_LIST() 1018 }, 1019}; 1020 1021void virt_acpi_setup(VirtMachineState *vms) 1022{ 1023 AcpiBuildTables tables; 1024 AcpiBuildState *build_state; 1025 AcpiGedState *acpi_ged_state; 1026 1027 if (!vms->fw_cfg) { 1028 trace_virt_acpi_setup(); 1029 return; 1030 } 1031 1032 if (!virt_is_acpi_enabled(vms)) { 1033 trace_virt_acpi_setup(); 1034 return; 1035 } 1036 1037 build_state = g_malloc0(sizeof *build_state); 1038 1039 acpi_build_tables_init(&tables); 1040 virt_acpi_build(vms, &tables); 1041 1042 /* Now expose it all to Guest */ 1043 build_state->table_mr = acpi_add_rom_blob(virt_acpi_build_update, 1044 build_state, tables.table_data, 1045 ACPI_BUILD_TABLE_FILE); 1046 assert(build_state->table_mr != NULL); 1047 1048 build_state->linker_mr = acpi_add_rom_blob(virt_acpi_build_update, 1049 build_state, 1050 tables.linker->cmd_blob, 1051 ACPI_BUILD_LOADER_FILE); 1052 1053 fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data, 1054 acpi_data_len(tables.tcpalog)); 1055 1056 if (vms->ras) { 1057 assert(vms->acpi_dev); 1058 acpi_ged_state = ACPI_GED(vms->acpi_dev); 1059 acpi_ghes_add_fw_cfg(&acpi_ged_state->ghes_state, 1060 vms->fw_cfg, tables.hardware_errors); 1061 } 1062 1063 build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update, 1064 build_state, tables.rsdp, 1065 ACPI_BUILD_RSDP_FILE); 1066 1067 qemu_register_reset(virt_acpi_build_reset, build_state); 1068 virt_acpi_build_reset(build_state); 1069 vmstate_register(NULL, 0, &vmstate_virt_acpi_build, build_state); 1070 1071 /* Cleanup tables but don't free the memory: we track it 1072 * in build_state. 1073 */ 1074 acpi_build_tables_cleanup(&tables, false); 1075}