qemu/acpi-build: cross migration fixes
cover qemu/acpi-build: cross migration fixes
This patchset, on top of my acpi branch,
fixes the issues with cross-version migration:
- Don't add fw cfg entries when running with -M 1.5 and older
- Future proof against future ACPI table changes:
create a ROM blob so the tables are migrated (together with BIOS)
With these changes the ACPI generation patchset
will become mergeable.
I say *will* since it's only lightly tested,
I intend to test properly and re-post the full patchset with acpi table geneation in QEMU ready for merge, next week.
Posting for early flames/review.
Michael S. Tsirkin (3):
loader: support for unmapped ROM blobs
acpi: add tables as ROM so they are migrated
acpi-build: disable acpi generation for compat
hw/core/loader.c | 32 +++++++++++++++++++++++++++++--- hw/i386/acpi-build.c | 19 +++++++++++++++++++ hw/i386/pc_piix.c | 12 ++++++++++-- hw/i386/pc_q35.c | 12 ++++++++++-- hw/lm32/lm32_hwsetup.h | 2 +- include/hw/i386/pc.h | 1 + include/hw/loader.h | 4 ++-- 7 files changed, 72 insertions(+), 10 deletions(-)
Signature · 1 line
MST
RFC PATCH 1/3 loader: support for unmapped ROM blobs
Support ROM blobs not mapped into guest memory:
let user pass in MR for memory serving as the backing store.
--- hw/core/loader.c | 32 +++++++++++++++++++++++++++++--- hw/lm32/lm32_hwsetup.h | 2 +- include/hw/loader.h | 4 ++-- 3 files changed, 32 insertions(+), 6 deletions(-)
hw/core/loader.c +29 -3
@@ -542,6 +542,7 @@ struct Rom {size_t datasize;uint8_t *data; +MemoryRegion *mr;int isrom;char *fw_dir;char *fw_file;
@@ -641,7 +642,7 @@ err: }int rom_add_blob (const char *name,const void *blob,size_t len, -hwaddr addr) +hwaddr addr,MemoryRegion *mr) {Rom *rom;
@@ -651,6 +652,11 @@ int rom_add_blob(const char *name, const void *blob, size_t len, rom->romsize = len; rom->datasize = len; rom->data =g_malloc0 (rom->datasize); + rom->mr = mr; +if (mr) { +assert (memory_region_is_ram (mr)); + rom->isrom =memory_region_is_rom (mr); + }memcpy (rom->data, blob, len);rom_insert (rom);return 0 ;
@@ -697,7 +703,12 @@ static void rom_reset(void *unused)if (rom->data ==NULL ) {continue ; } -cpu_physical_memory_write_rom (rom->addr, rom->data, rom->datasize); +if (rom->mr) { +void *host =memory_region_get_ram_ptr (rom->mr); +memcpy (host, rom->data, rom->datasize); + }else { +cpu_physical_memory_write_rom (rom->addr, rom->data, rom->datasize); + }if (rom->isrom) {/* rom needs to be written only once */ g_free (rom->data);
@@ -713,6 +724,9 @@ int rom_load_all(void)Rom *rom; QTAILQ_FOREACH(rom, &roms, next) { +if (rom->mr) { +continue ; + }if (rom->fw_file) {continue ; }
@@ -746,6 +760,9 @@ static Rom *find_rom(hwaddr addr)if (rom->fw_file) {continue ; } +if (rom->mr) { +continue ; + }if (rom->addr > addr) {continue ; }
@@ -773,6 +790,9 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size)if (rom->fw_file) {continue ; } +if (rom->mr) { +continue ; + }if (rom->addr + rom->romsize < addr) {continue ; }
@@ -832,7 +852,13 @@ void do_info_roms(Monitor *mon, const QDict *qdict)Rom *rom; QTAILQ_FOREACH(rom, &roms, next) { -if (!rom->fw_file) { +if (rom->mr) { +monitor_printf (mon,"%s" +" size=0x%06zx name=\"%s\"\n" , + rom->mr->name, + rom->romsize, + rom->name); + }else if (!rom->fw_file) { monitor_printf(mon, "addr=" TARGET_FMT_plx " size=0x%06zx mem=%s name=\"%s\"\n", rom->addr, rom->romsize,
hw/lm32/lm32_hwsetup.h +1 -1
@@ -73,7 +73,7 @@ static inline void hwsetup_free(HWSetup *hw)static inline void hwsetup_create_rom (HWSetup *hw,hwaddr base) { -rom_add_blob ("hwsetup" , hw->data,TARGET_PAGE_SIZE , base); +rom_add_blob ("hwsetup" , hw->data,TARGET_PAGE_SIZE , base,NULL ); }static inline void hwsetup_add_u8 (HWSetup *hw,uint8_t u)
include/hw/loader.h +2 -2
@@ -27,7 +27,7 @@ void pstrcpy_targphys(const char *name,int rom_add_file (const char *file,const char *fw_dir,hwaddr addr,int32_t bootindex);int rom_add_blob (const char *name,const void *blob,size_t len, -hwaddr addr); +hwaddr addr,MemoryRegion *mr);int rom_add_elf_program (const char *name,void *data,size_t datasize,size_t romsize,hwaddr addr);int rom_load_all (void );
@@ -39,7 +39,7 @@ void do_info_roms(Monitor *mon, const QDict *qdict);#define rom_add_file_fixed (_f, _a, _i) \ rom_add_file(_f, NULL, _a, _i)#define rom_add_blob_fixed (_f, _b, _l, _a) \ - rom_add_blob(_f, _b, _l, _a) + rom_add_blob(_f, _b, _l, _a, NULL)#define PC_ROM_MIN_VGA 0xc0000#define PC_ROM_MIN_OPTION 0xc8000
Signature · 1 line
MST
RFC PATCH 2/3 acpi: add tables as ROM so they are migrated
In reply to Michael S. TsirkinAs we are going to very likely change ACPI tables across QEMU versions, cross-verion migration will be a pain.
Register the tables as a ROM: this way they are migrated, same as BIOS code.
Since size is going to likely change, too, round it up to a multiple of 1MByte to avoid too much churn there.
--- hw/i386/acpi-build.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-)
hw/i386/acpi-build.c +33 -4
@@ -35,6 +35,7 @@#include "hw/nvram/fw_cfg.h" #include "hw/i386/bios-linker-loader.h" #include "hw/pci/pci_bus.h" +#include "hw/loader.h" #define ACPI_BUILD_APPNAME "Bochs"#define ACPI_BUILD_APPNAME6 "BOCHS "
@@ -933,6 +934,28 @@ build_rsdp(GArray *linker, unsigned rsdt)return rsdp_table; } +static void acpi_add_rom_blob (PcGuestInfo *guest_info,GArray *blob, +const char *name,unsigned align) +{ +MemoryRegion *mr =g_malloc (sizeof (*mr)); + +/* 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) + +g_array_get_element_size (blob) -1 ) / +g_array_get_element_size (blob)); +memory_region_init_ram_ptr (mr,"etc/blob-script" , +acpi_data_len (blob), blob->data); +memory_region_set_readonly (mr, true); +vmstate_register_ram_global (mr); +rom_add_blob (ACPI_BUILD_TABLE_FILE , blob->data,acpi_data_len (blob), +-1 , mr); + +fw_cfg_add_file (guest_info->fw_cfg, name, + blob->data,acpi_data_len (blob)); +} +#define ACPI_MAX_ACPI_TABLES 20void acpi_setup (PcGuestInfo *guest_info) {
@@ -993,12 +1016,18 @@ void acpi_setup(PcGuestInfo *guest_info) rsdp =build_rsdp (linker, rsdt);/* Now expose it all to Guest */ -fw_cfg_add_file (guest_info->fw_cfg,ACPI_BUILD_TABLE_FILE , - table_data->data, table_data->len); +acpi_add_rom_blob (guest_info, table_data, +ACPI_BUILD_TABLE_FILE ,1 <<20 ); + +acpi_add_rom_blob (guest_info, linker, +"etc/linker-script" ,TARGET_PAGE_SIZE ); + +/* +* 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 , rsdp->data,acpi_data_len (rsdp)); -fw_cfg_add_file (guest_info->fw_cfg,"etc/linker-script" , - linker->data,acpi_data_len (linker));/* Cleanup GArray wrappers and memory if no longer used. */ bios_linker_cleanup (linker);
Signature · 1 line
MST
RFC PATCH 3/3 acpi-build: disable acpi generation for compat
In reply to Michael S. TsirkinWhen running with -M 1.5 and older, disable ACPI
table generation, and don't expose ACPI
tables to guest.
--- hw/i386/acpi-build.c | 4 ++++ hw/i386/pc_piix.c | 12 ++++++++++-- hw/i386/pc_q35.c | 12 ++++++++++-- include/hw/i386/pc.h | 1 + 4 files changed, 25 insertions(+), 4 deletions(-)
hw/i386/acpi-build.c +4 -0
@@ -966,6 +966,10 @@ void acpi_setup(PcGuestInfo *guest_info)ACPI_BUILD_DPRINTF (3 ,"No fw cfg. Boiling out.\n" ); } +if (!guest_info->has_acpi_build) { +ACPI_BUILD_DPRINTF (3 ,"ACPI build disabled. Boiling out.\n" ); + } + table_data =g_array_new (false, true/* clear */ ,1 ); table_offsets =g_array_new (false, true/* clear */ ,sizeof (uint32_t ));
hw/i386/pc_piix.c +10 -2
@@ -59,6 +59,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };static const int ide_irq[MAX_IDE_BUS ] = {14 ,15 };static bool has_pvpanic = true; +static bool has_acpi_build = true;/* PC hardware initialisation */ static void pc_init1(MemoryRegion *system_memory,
@@ -124,6 +125,7 @@ static void pc_init1(MemoryRegion *system_memory, guest_info =pc_guest_info_init (below_4g_mem_size, above_4g_mem_size); + guest_info->has_acpi_build = has_acpi_build; guest_info->dsdt_code = AcpiDsdtAmlCode; guest_info->dsdt_size =sizeof AcpiDsdtAmlCode;
@@ -266,12 +268,18 @@ static void pc_init_pci(QEMUMachineInitArgs *args) initrd_filename, cpu_model, 1, 1); } +static void pc_init_pci_1_5 (QEMUMachineInitArgs *args) +{ + has_acpi_build = false; +pc_init_pci (args); +} +static void pc_init_pci_1_4 (QEMUMachineInitArgs *args) { pc_sysfw_flash_vs_rom_bug_compatible = true; has_pvpanic = false;x86_cpu_compat_set_features ("n270" ,FEAT_1_ECX ,0 ,CPUID_EXT_MOVBE ); -pc_init_pci (args); +pc_init_pci_1_5 (args); }static void pc_init_pci_1_3 (QEMUMachineInitArgs *args)
@@ -365,7 +373,7 @@ static QEMUMachine pc_i440fx_machine_v1_6 = {static QEMUMachine pc_i440fx_machine_v1_5 = { .name ="pc-i440fx-1.5" , .desc ="Standard PC (i440FX + PIIX, 1996)" , - .init = pc_init_pci, + .init = pc_init_pci_1_5, .hot_add_cpu = pc_hot_add_cpu, .max_cpus =255 , .compat_props = (GlobalProperty []) {
hw/i386/pc_q35.c +10 -2
@@ -49,6 +49,7 @@#define MAX_SATA_PORTS 6static bool has_pvpanic = true; +static bool has_acpi_build = true;/* PC hardware initialisation */ static void pc_q35_init (QEMUMachineInitArgs *args)
@@ -109,6 +110,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) } guest_info =pc_guest_info_init (below_4g_mem_size, above_4g_mem_size); + guest_info->has_acpi_build = has_acpi_build; guest_info->dsdt_code = Q35AcpiDsdtAmlCode; guest_info->dsdt_size =sizeof Q35AcpiDsdtAmlCode;
@@ -216,12 +218,18 @@ static void pc_q35_init(QEMUMachineInitArgs *args) } } +static void pc_q35_init_1_5 (QEMUMachineInitArgs *args) +{ + has_acpi_build = false; +pc_q35_init (args); +} +static void pc_q35_init_1_4 (QEMUMachineInitArgs *args) { pc_sysfw_flash_vs_rom_bug_compatible = true; has_pvpanic = false;x86_cpu_compat_set_features ("n270" ,FEAT_1_ECX ,0 ,CPUID_EXT_MOVBE ); -pc_q35_init (args); +pc_q35_init_1_5 (args); }static QEMUMachine pc_q35_machine_v1_6 = {
@@ -237,7 +245,7 @@ static QEMUMachine pc_q35_machine_v1_6 = {static QEMUMachine pc_q35_machine_v1_5 = { .name ="pc-q35-1.5" , .desc ="Standard PC (Q35 + ICH9, 2009)" , - .init = pc_q35_init, + .init = pc_q35_init_1_5, .hot_add_cpu = pc_hot_add_cpu, .max_cpus =255 , .compat_props = (GlobalProperty []) {
include/hw/i386/pc.h +1 -0
@@ -51,6 +51,7 @@ struct PcGuestInfo {uint64_t mcfg_base;const unsigned char *dsdt_code;unsigned dsdt_size; +bool has_acpi_build;FWCfgState *fw_cfg; };
Signature · 1 line
MST