void acpi_setup(PcGuestInfo *guest_info) { AcpiBuildTables tables; AcpiBuildState *build_state; if (!guest_info->fw_cfg) { ACPI_BUILD_DPRINTF(3, "No fw cfg. Bailing out.\n"); return; } if (!guest_info->has_acpi_build) { ACPI_BUILD_DPRINTF(3, "ACPI build disabled. Bailing out.\n"); return; } if (!acpi_enabled) { ACPI_BUILD_DPRINTF(3, "ACPI disabled. Bailing out.\n"); return; } build_state = g_malloc0(sizeof *build_state); build_state->guest_info = guest_info; acpi_set_pci_info(); acpi_build_tables_init(&tables); acpi_build(build_state->guest_info, &tables); /* Now expose it all to Guest */ build_state->table_ram = acpi_add_rom_blob(build_state, tables.table_data, ACPI_BUILD_TABLE_FILE); build_state->table_size = acpi_data_len(tables.table_data); acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader"); /* * RSDP is small so it's easy to keep it immutable, no need to * bother with ROM blobs. */ fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE, tables.rsdp->data, acpi_data_len(tables.rsdp)); qemu_register_reset(acpi_build_reset, build_state); acpi_build_reset(build_state); vmstate_register(NULL, 0, &vmstate_acpi_build, build_state); /* Cleanup tables but don't free the memory: we track it * in build_state. */ acpi_build_tables_cleanup(&tables, false); }
static MemoryRegion *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob, const char *name, uint64_t max_size) { return rom_add_blob(name, blob->data, acpi_data_len(blob), max_size, -1, name, virt_acpi_build_update, build_state); }
static void acpi_align_size(GArray *blob, unsigned align) { /* Align size to multiple of given size. This reduces the chance * we need to change size in the future (breaking cross version migration). */ g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align)); }
static void acpi_ram_update(MemoryRegion *mr, GArray *data) { uint32_t size = acpi_data_len(data); /* Make sure RAM size is correct - in case it got changed * e.g. by migration */ memory_region_ram_resize(mr, size, &error_abort); memcpy(memory_region_get_ram_ptr(mr), data->data, size); memory_region_set_dirty(mr, 0, size); }
void virt_acpi_setup(VirtGuestInfo *guest_info) { AcpiBuildTables tables; AcpiBuildState *build_state; if (!guest_info->fw_cfg) { trace_virt_acpi_setup(); return; } if (!acpi_enabled) { trace_virt_acpi_setup(); return; } build_state = g_malloc0(sizeof *build_state); build_state->guest_info = guest_info; acpi_build_tables_init(&tables); virt_acpi_build(build_state->guest_info, &tables); /* Now expose it all to Guest */ build_state->table_mr = acpi_add_rom_blob(build_state, tables.table_data, ACPI_BUILD_TABLE_FILE, ACPI_BUILD_TABLE_MAX_SIZE); assert(build_state->table_mr != NULL); build_state->linker_mr = acpi_add_rom_blob(build_state, tables.linker->cmd_blob, "etc/table-loader", 0); fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data, acpi_data_len(tables.tcpalog)); build_state->rsdp_mr = acpi_add_rom_blob(build_state, tables.rsdp, ACPI_BUILD_RSDP_FILE, 0); qemu_register_reset(virt_acpi_build_reset, build_state); virt_acpi_build_reset(build_state); vmstate_register(NULL, 0, &vmstate_virt_acpi_build, build_state); /* Cleanup tables but don't free the memory: we track it * in build_state. */ acpi_build_tables_cleanup(&tables, false); }
static void acpi_build_update(void *build_opaque, uint32_t offset) { AcpiBuildState *build_state = build_opaque; AcpiBuildTables tables; /* No state to update or already patched? Nothing to do. */ if (!build_state || build_state->patched) { return; } build_state->patched = 1; acpi_build_tables_init(&tables); acpi_build(build_state->guest_info, &tables); assert(acpi_data_len(tables.table_data) == build_state->table_size); memcpy(build_state->table_ram, tables.table_data->data, build_state->table_size); acpi_build_tables_cleanup(&tables, true); }
static void *acpi_add_rom_blob(AcpiBuildState *build_state, GArray *blob, const char *name) { return rom_add_blob(name, blob->data, acpi_data_len(blob), -1, name, acpi_build_update, build_state); }