Notifiers are called in LIFO order. In our case, we want fw_cfg to use the output of the machine-specific notifier: we will process the -kernel command-line option there, and this will modify the boot order which fw_cfg's notifier processes.
Because fw_cfg's notifier has to run last, we have to create the device early, before pc_guest_info_init registers its own notifier. It turns out that pc_guest_info_init is itself a good place to create fw_cfg. This also makes Xen more similar to native machine types. Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- hw/i386/pc.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b6c9b61..b95ac18 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -104,6 +104,8 @@ static struct e820_entry *e820_table; static unsigned e820_entries; struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX}; +static FWCfgState *bochs_bios_init(void); + void gsi_handler(void *opaque, int n, int level) { GSIState *s = opaque; @@ -1093,6 +1095,9 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, PcGuestInfo *guest_info = &guest_info_state->info; int i, j; + guest_info->fw_cfg = bochs_bios_init(); + rom_set_fw(guest_info->fw_cfg); + guest_info->ram_size_below_4g = below_4g_mem_size; guest_info->ram_size = below_4g_mem_size + above_4g_mem_size; guest_info->apic_id_limit = pc_apic_id_limit(max_cpus); @@ -1173,22 +1178,17 @@ FWCfgState *xen_load_linux(const char *kernel_filename, PcGuestInfo *guest_info) { int i; - FWCfgState *fw_cfg; assert(kernel_filename != NULL); - fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); - rom_set_fw(fw_cfg); - - load_linux(fw_cfg, kernel_filename, initrd_filename, + load_linux(guest_info->fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size); for (i = 0; i < nb_option_roms; i++) { assert(!strcmp(option_rom[i].name, "linuxboot.bin") || !strcmp(option_rom[i].name, "multiboot.bin")); rom_add_option(option_rom[i].name, option_rom[i].bootindex); } - guest_info->fw_cfg = fw_cfg; - return fw_cfg; + return guest_info->fw_cfg; } FWCfgState *pc_memory_init(MachineState *machine, @@ -1202,7 +1202,7 @@ FWCfgState *pc_memory_init(MachineState *machine, int linux_boot, i; MemoryRegion *ram, *option_rom_mr; MemoryRegion *ram_below_4g, *ram_above_4g; - FWCfgState *fw_cfg; + FWCfgState *fw_cfg = guest_info->fw_cfg; PCMachineState *pcms = PC_MACHINE(machine); assert(machine->ram_size == below_4g_mem_size + above_4g_mem_size); @@ -1280,9 +1280,6 @@ FWCfgState *pc_memory_init(MachineState *machine, option_rom_mr, 1); - fw_cfg = bochs_bios_init(); - rom_set_fw(fw_cfg); - if (guest_info->has_reserved_memory && pcms->hotplug_memory_base) { uint64_t *val = g_malloc(sizeof(*val)); *val = cpu_to_le64(ROUND_UP(pcms->hotplug_memory_base, 0x1ULL << 30)); @@ -1297,7 +1294,6 @@ FWCfgState *pc_memory_init(MachineState *machine, for (i = 0; i < nb_option_roms; i++) { rom_add_option(option_rom[i].name, option_rom[i].bootindex); } - guest_info->fw_cfg = fw_cfg; return fw_cfg; } -- 2.1.0