1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Support for generating ACPI tables and passing them to Guests 4 * 5 * Copyright (C) 2021 Loongson Technology Corporation Limited 6 */ 7 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" 22 23 /* Supported chipsets: */ 24 #include "hw/pci-host/ls7a.h" 25 #include "hw/loongarch/virt.h" 26 27 #include "hw/acpi/utils.h" 28 #include "hw/acpi/pci.h" 29 30 #include "qom/qom-qobject.h" 31 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 38 #define ACPI_BUILD_ALIGN_SIZE 0x1000 39 #define ACPI_BUILD_TABLE_SIZE 0x20000 40 41 #ifdef DEBUG_ACPI_BUILD 42 #define ACPI_BUILD_DPRINTF(fmt, ...) \ 43 do {printf("ACPI_BUILD: " fmt, ## __VA_ARGS__); } while (0) 44 #else 45 #define ACPI_BUILD_DPRINTF(fmt, ...) 46 #endif 47 48 /* build FADT */ 49 static void init_common_fadt_data(AcpiFadtData *data) 50 { 51 AcpiFadtData fadt = { 52 /* ACPI 5.0: 4.1 Hardware-Reduced ACPI */ 53 .rev = 5, 54 .flags = ((1 << ACPI_FADT_F_HW_REDUCED_ACPI) | 55 (1 << ACPI_FADT_F_RESET_REG_SUP)), 56 57 /* ACPI 5.0: 4.8.3.7 Sleep Control and Status Registers */ 58 .sleep_ctl = { 59 .space_id = AML_AS_SYSTEM_MEMORY, 60 .bit_width = 8, 61 .address = VIRT_GED_REG_ADDR + ACPI_GED_REG_SLEEP_CTL, 62 }, 63 .sleep_sts = { 64 .space_id = AML_AS_SYSTEM_MEMORY, 65 .bit_width = 8, 66 .address = VIRT_GED_REG_ADDR + ACPI_GED_REG_SLEEP_STS, 67 }, 68 69 /* ACPI 5.0: 4.8.3.6 Reset Register */ 70 .reset_reg = { 71 .space_id = AML_AS_SYSTEM_MEMORY, 72 .bit_width = 8, 73 .address = VIRT_GED_REG_ADDR + ACPI_GED_REG_RESET, 74 }, 75 .reset_val = ACPI_GED_RESET_VALUE, 76 }; 77 *data = fadt; 78 } 79 80 static void acpi_align_size(GArray *blob, unsigned align) 81 { 82 /* 83 * Align size to multiple of given size. This reduces the chance 84 * we need to change size in the future (breaking cross version migration). 85 */ 86 g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); 87 } 88 89 /* build FACS */ 90 static void 91 build_facs(GArray *table_data) 92 { 93 const char *sig = "FACS"; 94 const uint8_t reserved[40] = {}; 95 96 g_array_append_vals(table_data, sig, 4); /* Signature */ 97 build_append_int_noprefix(table_data, 64, 4); /* Length */ 98 build_append_int_noprefix(table_data, 0, 4); /* Hardware Signature */ 99 build_append_int_noprefix(table_data, 0, 4); /* Firmware Waking Vector */ 100 build_append_int_noprefix(table_data, 0, 4); /* Global Lock */ 101 build_append_int_noprefix(table_data, 0, 4); /* Flags */ 102 g_array_append_vals(table_data, reserved, 40); /* Reserved */ 103 } 104 105 /* build MADT */ 106 static void 107 build_madt(GArray *table_data, BIOSLinker *linker, LoongArchMachineState *lams) 108 { 109 MachineState *ms = MACHINE(lams); 110 int i; 111 AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = lams->oem_id, 112 .oem_table_id = lams->oem_table_id }; 113 114 acpi_table_begin(&table, table_data); 115 116 /* Local APIC Address */ 117 build_append_int_noprefix(table_data, 0, 4); 118 build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */ 119 120 for (i = 0; i < ms->smp.cpus; i++) { 121 /* Processor Core Interrupt Controller Structure */ 122 build_append_int_noprefix(table_data, 17, 1); /* Type */ 123 build_append_int_noprefix(table_data, 15, 1); /* Length */ 124 build_append_int_noprefix(table_data, 1, 1); /* Version */ 125 build_append_int_noprefix(table_data, i + 1, 4); /* ACPI Processor ID */ 126 build_append_int_noprefix(table_data, i, 4); /* Core ID */ 127 build_append_int_noprefix(table_data, 1, 4); /* Flags */ 128 } 129 130 /* Extend I/O Interrupt Controller Structure */ 131 build_append_int_noprefix(table_data, 20, 1); /* Type */ 132 build_append_int_noprefix(table_data, 13, 1); /* Length */ 133 build_append_int_noprefix(table_data, 1, 1); /* Version */ 134 build_append_int_noprefix(table_data, 3, 1); /* Cascade */ 135 build_append_int_noprefix(table_data, 0, 1); /* Node */ 136 build_append_int_noprefix(table_data, 0xffff, 8); /* Node map */ 137 138 /* MSI Interrupt Controller Structure */ 139 build_append_int_noprefix(table_data, 21, 1); /* Type */ 140 build_append_int_noprefix(table_data, 19, 1); /* Length */ 141 build_append_int_noprefix(table_data, 1, 1); /* Version */ 142 build_append_int_noprefix(table_data, VIRT_PCH_MSI_ADDR_LOW, 8);/* Address */ 143 build_append_int_noprefix(table_data, 0x40, 4); /* Start */ 144 build_append_int_noprefix(table_data, 0xc0, 4); /* Count */ 145 146 /* Bridge I/O Interrupt Controller Structure */ 147 build_append_int_noprefix(table_data, 22, 1); /* Type */ 148 build_append_int_noprefix(table_data, 17, 1); /* Length */ 149 build_append_int_noprefix(table_data, 1, 1); /* Version */ 150 build_append_int_noprefix(table_data, VIRT_PCH_REG_BASE, 8);/* Address */ 151 build_append_int_noprefix(table_data, 0x1000, 2); /* Size */ 152 build_append_int_noprefix(table_data, 0, 2); /* Id */ 153 build_append_int_noprefix(table_data, 0x40, 2); /* Base */ 154 155 acpi_table_end(linker, &table); 156 } 157 158 /* build SRAT */ 159 static void 160 build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) 161 { 162 uint64_t i; 163 LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); 164 MachineState *ms = MACHINE(lams); 165 AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lams->oem_id, 166 .oem_table_id = lams->oem_table_id }; 167 168 acpi_table_begin(&table, table_data); 169 build_append_int_noprefix(table_data, 1, 4); /* Reserved */ 170 build_append_int_noprefix(table_data, 0, 8); /* Reserved */ 171 172 for (i = 0; i < ms->smp.cpus; ++i) { 173 /* Processor Local APIC/SAPIC Affinity Structure */ 174 build_append_int_noprefix(table_data, 0, 1); /* Type */ 175 build_append_int_noprefix(table_data, 16, 1); /* Length */ 176 /* Proximity Domain [7:0] */ 177 build_append_int_noprefix(table_data, 0, 1); 178 build_append_int_noprefix(table_data, i, 1); /* APIC ID */ 179 /* Flags, Table 5-36 */ 180 build_append_int_noprefix(table_data, 1, 4); 181 build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */ 182 /* Proximity Domain [31:8] */ 183 build_append_int_noprefix(table_data, 0, 3); 184 build_append_int_noprefix(table_data, 0, 4); /* Reserved */ 185 } 186 187 build_srat_memory(table_data, VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 188 0, MEM_AFFINITY_ENABLED); 189 190 build_srat_memory(table_data, VIRT_HIGHMEM_BASE, machine->ram_size - VIRT_LOWMEM_SIZE, 191 0, MEM_AFFINITY_ENABLED); 192 193 if (ms->device_memory) { 194 build_srat_memory(table_data, ms->device_memory->base, 195 memory_region_size(&ms->device_memory->mr), 196 0, MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); 197 } 198 199 acpi_table_end(linker, &table); 200 } 201 202 typedef 203 struct AcpiBuildState { 204 /* Copy of table in RAM (for patching). */ 205 MemoryRegion *table_mr; 206 /* Is table patched? */ 207 uint8_t patched; 208 void *rsdp; 209 MemoryRegion *rsdp_mr; 210 MemoryRegion *linker_mr; 211 } AcpiBuildState; 212 213 static void build_uart_device_aml(Aml *table) 214 { 215 Aml *dev; 216 Aml *crs; 217 Aml *pkg0, *pkg1, *pkg2; 218 uint32_t uart_irq = VIRT_UART_IRQ; 219 220 Aml *scope = aml_scope("_SB"); 221 dev = aml_device("COMA"); 222 aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501"))); 223 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 224 aml_append(dev, aml_name_decl("_CCA", aml_int(1))); 225 crs = aml_resource_template(); 226 aml_append(crs, 227 aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, 228 AML_NON_CACHEABLE, AML_READ_WRITE, 229 0, VIRT_UART_BASE, VIRT_UART_BASE + VIRT_UART_SIZE - 1, 230 0, VIRT_UART_SIZE)); 231 aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, 232 AML_SHARED, &uart_irq, 1)); 233 aml_append(dev, aml_name_decl("_CRS", crs)); 234 pkg0 = aml_package(0x2); 235 aml_append(pkg0, aml_int(0x05F5E100)); 236 aml_append(pkg0, aml_string("clock-frenquency")); 237 pkg1 = aml_package(0x1); 238 aml_append(pkg1, pkg0); 239 pkg2 = aml_package(0x2); 240 aml_append(pkg2, aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301")); 241 aml_append(pkg2, pkg1); 242 aml_append(dev, aml_name_decl("_DSD", pkg2)); 243 aml_append(scope, dev); 244 aml_append(table, scope); 245 } 246 247 static void 248 build_la_ged_aml(Aml *dsdt, MachineState *machine) 249 { 250 uint32_t event; 251 LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); 252 253 build_ged_aml(dsdt, "\\_SB."GED_DEVICE, 254 HOTPLUG_HANDLER(lams->acpi_ged), 255 VIRT_SCI_IRQ, AML_SYSTEM_MEMORY, 256 VIRT_GED_EVT_ADDR); 257 event = object_property_get_uint(OBJECT(lams->acpi_ged), 258 "ged-event", &error_abort); 259 if (event & ACPI_GED_MEM_HOTPLUG_EVT) { 260 build_memory_hotplug_aml(dsdt, machine->ram_slots, "\\_SB", NULL, 261 AML_SYSTEM_MEMORY, 262 VIRT_GED_MEM_ADDR); 263 } 264 acpi_dsdt_add_power_button(dsdt); 265 } 266 267 static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams) 268 { 269 struct GPEXConfig cfg = { 270 .mmio64.base = VIRT_PCI_MEM_BASE, 271 .mmio64.size = VIRT_PCI_MEM_SIZE, 272 .pio.base = VIRT_PCI_IO_BASE, 273 .pio.size = VIRT_PCI_IO_SIZE, 274 .ecam.base = VIRT_PCI_CFG_BASE, 275 .ecam.size = VIRT_PCI_CFG_SIZE, 276 .irq = VIRT_GSI_BASE + VIRT_DEVICE_IRQS, 277 .bus = lams->pci_bus, 278 }; 279 280 acpi_dsdt_add_gpex(scope, &cfg); 281 } 282 283 static void build_flash_aml(Aml *scope, LoongArchMachineState *lams) 284 { 285 Aml *dev, *crs; 286 287 hwaddr flash_base = VIRT_FLASH_BASE; 288 hwaddr flash_size = VIRT_FLASH_SIZE; 289 290 dev = aml_device("FLS0"); 291 aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0015"))); 292 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 293 294 crs = aml_resource_template(); 295 aml_append(crs, aml_memory32_fixed(flash_base, flash_size, AML_READ_WRITE)); 296 aml_append(dev, aml_name_decl("_CRS", crs)); 297 aml_append(scope, dev); 298 } 299 300 #ifdef CONFIG_TPM 301 static void acpi_dsdt_add_tpm(Aml *scope, LoongArchMachineState *vms) 302 { 303 PlatformBusDevice *pbus = PLATFORM_BUS_DEVICE(vms->platform_bus_dev); 304 hwaddr pbus_base = VIRT_PLATFORM_BUS_BASEADDRESS; 305 SysBusDevice *sbdev = SYS_BUS_DEVICE(tpm_find()); 306 MemoryRegion *sbdev_mr; 307 hwaddr tpm_base; 308 309 if (!sbdev) { 310 return; 311 } 312 313 tpm_base = platform_bus_get_mmio_addr(pbus, sbdev, 0); 314 assert(tpm_base != -1); 315 316 tpm_base += pbus_base; 317 318 sbdev_mr = sysbus_mmio_get_region(sbdev, 0); 319 320 Aml *dev = aml_device("TPM0"); 321 aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101"))); 322 aml_append(dev, aml_name_decl("_STR", aml_string("TPM 2.0 Device"))); 323 aml_append(dev, aml_name_decl("_UID", aml_int(0))); 324 325 Aml *crs = aml_resource_template(); 326 aml_append(crs, 327 aml_memory32_fixed(tpm_base, 328 (uint32_t)memory_region_size(sbdev_mr), 329 AML_READ_WRITE)); 330 aml_append(dev, aml_name_decl("_CRS", crs)); 331 aml_append(scope, dev); 332 } 333 #endif 334 335 /* build DSDT */ 336 static void 337 build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) 338 { 339 Aml *dsdt, *scope, *pkg; 340 LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); 341 AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lams->oem_id, 342 .oem_table_id = lams->oem_table_id }; 343 344 acpi_table_begin(&table, table_data); 345 dsdt = init_aml_allocator(); 346 build_uart_device_aml(dsdt); 347 build_pci_device_aml(dsdt, lams); 348 build_la_ged_aml(dsdt, machine); 349 build_flash_aml(dsdt, lams); 350 #ifdef CONFIG_TPM 351 acpi_dsdt_add_tpm(dsdt, lams); 352 #endif 353 /* System State Package */ 354 scope = aml_scope("\\"); 355 pkg = aml_package(4); 356 aml_append(pkg, aml_int(ACPI_GED_SLP_TYP_S5)); 357 aml_append(pkg, aml_int(0)); /* ignored */ 358 aml_append(pkg, aml_int(0)); /* reserved */ 359 aml_append(pkg, aml_int(0)); /* reserved */ 360 aml_append(scope, aml_name_decl("_S5", pkg)); 361 aml_append(dsdt, scope); 362 /* Copy AML table into ACPI tables blob and patch header there */ 363 g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len); 364 acpi_table_end(linker, &table); 365 free_aml_allocator(); 366 } 367 368 static void acpi_build(AcpiBuildTables *tables, MachineState *machine) 369 { 370 LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); 371 GArray *table_offsets; 372 AcpiFadtData fadt_data; 373 unsigned facs, rsdt, dsdt; 374 uint8_t *u; 375 GArray *tables_blob = tables->table_data; 376 377 init_common_fadt_data(&fadt_data); 378 379 table_offsets = g_array_new(false, true, sizeof(uint32_t)); 380 ACPI_BUILD_DPRINTF("init ACPI tables\n"); 381 382 bios_linker_loader_alloc(tables->linker, 383 ACPI_BUILD_TABLE_FILE, tables_blob, 384 64, false); 385 386 /* 387 * FACS is pointed to by FADT. 388 * We place it first since it's the only table that has alignment 389 * requirements. 390 */ 391 facs = tables_blob->len; 392 build_facs(tables_blob); 393 394 /* DSDT is pointed to by FADT */ 395 dsdt = tables_blob->len; 396 build_dsdt(tables_blob, tables->linker, machine); 397 398 /* ACPI tables pointed to by RSDT */ 399 acpi_add_table(table_offsets, tables_blob); 400 fadt_data.facs_tbl_offset = &facs; 401 fadt_data.dsdt_tbl_offset = &dsdt; 402 fadt_data.xdsdt_tbl_offset = &dsdt; 403 build_fadt(tables_blob, tables->linker, &fadt_data, 404 lams->oem_id, lams->oem_table_id); 405 406 acpi_add_table(table_offsets, tables_blob); 407 build_madt(tables_blob, tables->linker, lams); 408 409 acpi_add_table(table_offsets, tables_blob); 410 build_srat(tables_blob, tables->linker, machine); 411 412 acpi_add_table(table_offsets, tables_blob); 413 { 414 AcpiMcfgInfo mcfg = { 415 .base = cpu_to_le64(VIRT_PCI_CFG_BASE), 416 .size = cpu_to_le64(VIRT_PCI_CFG_SIZE), 417 }; 418 build_mcfg(tables_blob, tables->linker, &mcfg, lams->oem_id, 419 lams->oem_table_id); 420 } 421 422 #ifdef CONFIG_TPM 423 /* TPM info */ 424 if (tpm_get_version(tpm_find()) == TPM_VERSION_2_0) { 425 acpi_add_table(table_offsets, tables_blob); 426 build_tpm2(tables_blob, tables->linker, 427 tables->tcpalog, lams->oem_id, 428 lams->oem_table_id); 429 } 430 #endif 431 /* Add tables supplied by user (if any) */ 432 for (u = acpi_table_first(); u; u = acpi_table_next(u)) { 433 unsigned len = acpi_table_len(u); 434 435 acpi_add_table(table_offsets, tables_blob); 436 g_array_append_vals(tables_blob, u, len); 437 } 438 439 /* RSDT is pointed to by RSDP */ 440 rsdt = tables_blob->len; 441 build_rsdt(tables_blob, tables->linker, table_offsets, 442 lams->oem_id, lams->oem_table_id); 443 444 /* RSDP is in FSEG memory, so allocate it separately */ 445 { 446 AcpiRsdpData rsdp_data = { 447 .revision = 0, 448 .oem_id = lams->oem_id, 449 .xsdt_tbl_offset = NULL, 450 .rsdt_tbl_offset = &rsdt, 451 }; 452 build_rsdp(tables->rsdp, tables->linker, &rsdp_data); 453 } 454 455 /* 456 * The align size is 128, warn if 64k is not enough therefore 457 * the align size could be resized. 458 */ 459 if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) { 460 warn_report("ACPI table size %u exceeds %d bytes," 461 " migration may not work", 462 tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2); 463 error_printf("Try removing CPUs, NUMA nodes, memory slots" 464 " or PCI bridges."); 465 } 466 467 acpi_align_size(tables->linker->cmd_blob, ACPI_BUILD_ALIGN_SIZE); 468 469 /* Cleanup memory that's no longer used. */ 470 g_array_free(table_offsets, true); 471 } 472 473 static void acpi_ram_update(MemoryRegion *mr, GArray *data) 474 { 475 uint32_t size = acpi_data_len(data); 476 477 /* 478 * Make sure RAM size is correct - in case it got changed 479 * e.g. by migration 480 */ 481 memory_region_ram_resize(mr, size, &error_abort); 482 483 memcpy(memory_region_get_ram_ptr(mr), data->data, size); 484 memory_region_set_dirty(mr, 0, size); 485 } 486 487 static void acpi_build_update(void *build_opaque) 488 { 489 AcpiBuildState *build_state = build_opaque; 490 AcpiBuildTables tables; 491 492 /* No state to update or already patched? Nothing to do. */ 493 if (!build_state || build_state->patched) { 494 return; 495 } 496 build_state->patched = 1; 497 498 acpi_build_tables_init(&tables); 499 500 acpi_build(&tables, MACHINE(qdev_get_machine())); 501 502 acpi_ram_update(build_state->table_mr, tables.table_data); 503 acpi_ram_update(build_state->rsdp_mr, tables.rsdp); 504 acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob); 505 506 acpi_build_tables_cleanup(&tables, true); 507 } 508 509 static void acpi_build_reset(void *build_opaque) 510 { 511 AcpiBuildState *build_state = build_opaque; 512 build_state->patched = 0; 513 } 514 515 static const VMStateDescription vmstate_acpi_build = { 516 .name = "acpi_build", 517 .version_id = 1, 518 .minimum_version_id = 1, 519 .fields = (VMStateField[]) { 520 VMSTATE_UINT8(patched, AcpiBuildState), 521 VMSTATE_END_OF_LIST() 522 }, 523 }; 524 525 void loongarch_acpi_setup(LoongArchMachineState *lams) 526 { 527 AcpiBuildTables tables; 528 AcpiBuildState *build_state; 529 530 if (!lams->fw_cfg) { 531 ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n"); 532 return; 533 } 534 535 if (!loongarch_is_acpi_enabled(lams)) { 536 ACPI_BUILD_DPRINTF("ACPI disabled. Bailing out.\n"); 537 return; 538 } 539 540 build_state = g_malloc0(sizeof *build_state); 541 542 acpi_build_tables_init(&tables); 543 acpi_build(&tables, MACHINE(lams)); 544 545 /* Now expose it all to Guest */ 546 build_state->table_mr = acpi_add_rom_blob(acpi_build_update, 547 build_state, tables.table_data, 548 ACPI_BUILD_TABLE_FILE); 549 assert(build_state->table_mr != NULL); 550 551 build_state->linker_mr = 552 acpi_add_rom_blob(acpi_build_update, build_state, 553 tables.linker->cmd_blob, ACPI_BUILD_LOADER_FILE); 554 555 build_state->rsdp_mr = acpi_add_rom_blob(acpi_build_update, 556 build_state, tables.rsdp, 557 ACPI_BUILD_RSDP_FILE); 558 559 qemu_register_reset(acpi_build_reset, build_state); 560 acpi_build_reset(build_state); 561 vmstate_register(NULL, 0, &vmstate_acpi_build, build_state); 562 563 /* 564 * Cleanup tables but don't free the memory: we track it 565 * in build_state. 566 */ 567 acpi_build_tables_cleanup(&tables, false); 568 } 569