Custom topology will allow machine to skip the default CPU creation and accept user's CPU creation from CLI. Therefore, for microvm, pc-i440fx and pc-q35, split machine initialization from x86_cpus_init(), and place the remaining part into post_init(), which can continue to run after CPU creation from CLI. This addresses the CPU dependency for the remaining initialization steps after x86_cpus_init(). Signed-off-by: Zhao Liu <zhao1.liu@xxxxxxxxx> --- hw/i386/microvm.c | 7 +++++++ hw/i386/pc_piix.c | 40 +++++++++++++++++++++++++--------------- hw/i386/pc_q35.c | 36 ++++++++++++++++++++++-------------- include/hw/i386/pc.h | 3 +++ 4 files changed, 57 insertions(+), 29 deletions(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 49a897db50fc..dc9b21a34230 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -463,6 +463,11 @@ static void microvm_machine_state_init(MachineState *machine) microvm_memory_init(mms); x86_cpus_init(x86ms, CPU_VERSION_LATEST); +} + +static void microvm_machine_state_post_init(MachineState *machine) +{ + MicrovmMachineState *mms = MICROVM_MACHINE(machine); microvm_devices_init(mms); } @@ -665,6 +670,8 @@ static void microvm_class_init(ObjectClass *oc, void *data) /* Machine class handlers */ mc->reset = microvm_machine_reset; + mc->post_init = microvm_machine_state_post_init; + /* hotplug (for cpu coldplug) */ mc->get_hotplug_handler = microvm_get_hotplug_handler; hc->pre_plug = microvm_device_pre_plug_cb; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 2bf6865d405e..c1db2f3129cf 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -105,19 +105,9 @@ static void pc_init1(MachineState *machine, const char *pci_type) PCMachineState *pcms = PC_MACHINE(machine); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); X86MachineState *x86ms = X86_MACHINE(machine); - MemoryRegion *system_memory = get_system_memory(); - MemoryRegion *system_io = get_system_io(); - Object *phb = NULL; - ISABus *isa_bus; - Object *piix4_pm = NULL; - qemu_irq smi_irq; - GSIState *gsi_state; - MemoryRegion *ram_memory; - MemoryRegion *pci_memory = NULL; - MemoryRegion *rom_memory = system_memory; ram_addr_t lowmem; - uint64_t hole64_size = 0; + pcms->pci_type = pci_type; /* * Calculate ram split, for memory below and above 4G. It's a bit * complicated for backward compatibility reasons ... @@ -150,9 +140,9 @@ static void pc_init1(MachineState *machine, const char *pci_type) * qemu -M pc,max-ram-below-4g=4G -m 3968M -> 3968M low (=4G-128M) */ if (xen_enabled()) { - xen_hvm_init_pc(pcms, &ram_memory); + xen_hvm_init_pc(pcms, &pcms->pre_config_ram); } else { - ram_memory = machine->ram; + pcms->pre_config_ram = machine->ram; if (!pcms->max_ram_below_4g) { pcms->max_ram_below_4g = 0xe0000000; /* default: 3.5G */ } @@ -182,6 +172,23 @@ static void pc_init1(MachineState *machine, const char *pci_type) pc_machine_init_sgx_epc(pcms); x86_cpus_init(x86ms, pcmc->default_cpu_version); +} + +static void pc_post_init1(MachineState *machine) +{ + PCMachineState *pcms = PC_MACHINE(machine); + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); + X86MachineState *x86ms = X86_MACHINE(machine); + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *system_io = get_system_io(); + Object *phb = NULL; + ISABus *isa_bus; + Object *piix4_pm = NULL; + qemu_irq smi_irq; + GSIState *gsi_state; + MemoryRegion *pci_memory = NULL; + MemoryRegion *rom_memory = system_memory; + uint64_t hole64_size = 0; if (kvm_enabled()) { kvmclock_create(pcmc->kvmclock_create_always); @@ -195,7 +202,7 @@ static void pc_init1(MachineState *machine, const char *pci_type) phb = OBJECT(qdev_new(TYPE_I440FX_PCI_HOST_BRIDGE)); object_property_add_child(OBJECT(machine), "i440fx", phb); object_property_set_link(phb, PCI_HOST_PROP_RAM_MEM, - OBJECT(ram_memory), &error_fatal); + OBJECT(pcms->pre_config_ram), &error_fatal); object_property_set_link(phb, PCI_HOST_PROP_PCI_MEM, OBJECT(pci_memory), &error_fatal); object_property_set_link(phb, PCI_HOST_PROP_SYSTEM_MEM, @@ -206,7 +213,7 @@ static void pc_init1(MachineState *machine, const char *pci_type) x86ms->below_4g_mem_size, &error_fatal); object_property_set_uint(phb, PCI_HOST_ABOVE_4G_MEM_SIZE, x86ms->above_4g_mem_size, &error_fatal); - object_property_set_str(phb, I440FX_HOST_PROP_PCI_TYPE, pci_type, + object_property_set_str(phb, I440FX_HOST_PROP_PCI_TYPE, pcms->pci_type, &error_fatal); sysbus_realize_and_unref(SYS_BUS_DEVICE(phb), &error_fatal); @@ -413,6 +420,7 @@ static void pc_set_south_bridge(Object *obj, int value, Error **errp) static void pc_init_isa(MachineState *machine) { pc_init1(machine, NULL); + pc_post_init1(machine); } #endif @@ -423,6 +431,7 @@ static void pc_xen_hvm_init_pci(MachineState *machine) TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE : TYPE_I440FX_PCI_DEVICE; pc_init1(machine, pci_type); + pc_post_init1(machine); } static void pc_xen_hvm_init(MachineState *machine) @@ -463,6 +472,7 @@ static void pc_i440fx_machine_options(MachineClass *m) m->default_nic = "e1000"; m->no_floppy = !module_object_class_by_name(TYPE_ISA_FDC); m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); + m->post_init = pc_post_init1; machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 8319b6d45ee3..9ce3e65d7182 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -129,21 +129,7 @@ static void pc_q35_init(MachineState *machine) PCMachineState *pcms = PC_MACHINE(machine); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); X86MachineState *x86ms = X86_MACHINE(machine); - Object *phb; - PCIDevice *lpc; - DeviceState *lpc_dev; - MemoryRegion *system_memory = get_system_memory(); - MemoryRegion *system_io = get_system_io(); - MemoryRegion *pci_memory = g_new(MemoryRegion, 1); - GSIState *gsi_state; - ISABus *isa_bus; - int i; ram_addr_t lowmem; - DriveInfo *hd[MAX_SATA_PORTS]; - MachineClass *mc = MACHINE_GET_CLASS(machine); - bool acpi_pcihp; - bool keep_pci_slot_hpc; - uint64_t pci_hole64_size = 0; assert(pcmc->pci_enabled); @@ -188,6 +174,27 @@ static void pc_q35_init(MachineState *machine) pc_machine_init_sgx_epc(pcms); x86_cpus_init(x86ms, pcmc->default_cpu_version); +} + +static void pc_q35_post_init(MachineState *machine) +{ + PCMachineState *pcms = PC_MACHINE(machine); + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); + X86MachineState *x86ms = X86_MACHINE(machine); + Object *phb; + PCIDevice *lpc; + DeviceState *lpc_dev; + MemoryRegion *system_memory = get_system_memory(); + MemoryRegion *system_io = get_system_io(); + MemoryRegion *pci_memory = g_new(MemoryRegion, 1); + GSIState *gsi_state; + ISABus *isa_bus; + int i; + DriveInfo *hd[MAX_SATA_PORTS]; + MachineClass *mc = MACHINE_GET_CLASS(machine); + bool acpi_pcihp; + bool keep_pci_slot_hpc; + uint64_t pci_hole64_size = 0; if (kvm_enabled()) { kvmclock_create(pcmc->kvmclock_create_always); @@ -348,6 +355,7 @@ static void pc_q35_machine_options(MachineClass *m) m->no_floppy = 1; m->max_cpus = 4096; m->no_parallel = !module_object_class_by_name(TYPE_ISA_PARALLEL); + m->post_init = pc_q35_post_init; machine_class_allow_dynamic_sysbus_dev(m, TYPE_AMD_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_INTEL_IOMMU_DEVICE); machine_class_allow_dynamic_sysbus_dev(m, TYPE_RAMFB_DEVICE); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 14ee06287da3..14534781e8fb 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -58,6 +58,9 @@ typedef struct PCMachineState { SGXEPCState sgx_epc; CXLState cxl_devices_state; + + MemoryRegion *pre_config_ram; + const char *pci_type; } PCMachineState; #define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" -- 2.34.1