hw/i386/pc: Do not restrict the fw_cfg functions to the PC machine
v4 cover hw/i386/pc: Do not restrict the fw_cfg functions to the PC machine
Hi,
This is my take at salvaging some NEMU good work.
Samuel worked in adding the fw_cfg device to the x86-virt NEMU machine. This series is inspired by NEMU's commit 3cb92d080835 [0] and adapted to upstream style. The result makes the upstream codebase more modularizable.
There are very little logical changes, this is mostly a cleanup refactor.
Since v3 [3]:
- Addressed Christophe suggestion (patch #8)
- Rebased patch #15 since Eduardo merged Like Xu's work between.
Since v2 [2]:
- Addressed MST comments from v2 (only patch #2 modified)
- do not use unsigned for enum
- do not add unuseful documentation
Since v1 [1]:
- Addressed Li and MST comments
$ git backport-diff -u v3 Key: [----] : patches are identical [####] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively
001/15:[----] [--] 'hw/i386/pc: Use e820_get_num_entries() to access e820_entries' 002/15:[----] [-C] 'hw/i386/pc: Extract e820 memory layout code' 003/15:[----] [--] 'hw/i386/pc: Use address_space_memory in place' 004/15:[----] [-C] 'hw/i386/pc: Rename bochs_bios_init as more generic fw_cfg_arch_create' 005/15:[----] [--] 'hw/i386/pc: Pass the boot_cpus value by argument' 006/15:[----] [--] 'hw/i386/pc: Pass the apic_id_limit value by argument' 007/15:[0002] [FC] 'hw/i386/pc: Pass the CPUArchIdList array by argument' 008/15:[down] 'hw/i386/pc: Remove unused PCMachineState argument in fw_cfg_arch_create' 009/15:[----] [-C] 'hw/i386/pc: Let pc_build_smbios() take a FWCfgState argument' 010/15:[----] [-C] 'hw/i386/pc: Let pc_build_smbios() take a generic MachineState argument' 011/15:[----] [-C] 'hw/i386/pc: Rename pc_build_smbios() as generic fw_cfg_build_smbios()' 012/15:[----] [--] 'hw/i386/pc: Let pc_build_feature_control() take a FWCfgState argument' 013/15:[----] [--] 'hw/i386/pc: Let pc_build_feature_control() take a MachineState argument' 014/15:[----] [--] 'hw/i386/pc: Rename pc_build_feature_control() as generic fw_cfg_build_*' 015/15:[0017] [FC] 'hw/i386/pc: Extract the x86 generic fw_cfg code'
Regards,
Phil.
[0] https://github.com/intel/nemu/commit/3cb92d080835ac8d47c8b713156338afa33cff5c
[1] https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg05759.html
[2] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg02786.html
[3] https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg00193.html
Philippe Mathieu-Daudé (15):
hw/i386/pc: Use e820_get_num_entries() to access e820_entries hw/i386/pc: Extract e820 memory layout code
hw/i386/pc: Use address_space_memory in place
hw/i386/pc: Rename bochs_bios_init as more generic fw_cfg_arch_create hw/i386/pc: Pass the boot_cpus value by argument hw/i386/pc: Pass the apic_id_limit value by argument hw/i386/pc: Pass the CPUArchIdList array by argument hw/i386/pc: Remove unused PCMachineState argument in
fw_cfg_arch_create
hw/i386/pc: Let pc_build_smbios() take a FWCfgState argument hw/i386/pc: Let pc_build_smbios() take a generic MachineState argument hw/i386/pc: Rename pc_build_smbios() as generic fw_cfg_build_smbios() hw/i386/pc: Let pc_build_feature_control() take a FWCfgState argument hw/i386/pc: Let pc_build_feature_control() take a MachineState
argument
hw/i386/pc: Rename pc_build_feature_control() as generic
fw_cfg_build_*
hw/i386/pc: Extract the x86 generic fw_cfg code
hw/i386/Makefile.objs | 2 +- hw/i386/e820_memory_layout.c | 59 ++++++++++ hw/i386/e820_memory_layout.h | 42 ++++++++ hw/i386/fw_cfg.c | 136 +++++++++++++++++++++++ hw/i386/fw_cfg.h | 7 ++ hw/i386/pc.c | 202 ++--------------------------------- include/hw/i386/pc.h | 11 -- target/i386/kvm.c | 1 + 8 files changed, 254 insertions(+), 206 deletions(-) create mode 100644 hw/i386/e820_memory_layout.c create mode 100644 hw/i386/e820_memory_layout.h
Signature · 1 line
2.20.1
PATCH v4 1/15 hw/i386/pc: Use e820_get_num_entries() to access e820_entries
To be able to extract the e820* code out of this file (in the next patch), access e820_entries with its correct helper.
--- hw/i386/pc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/i386/pc.c +1 -1
@@ -1024,7 +1024,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)fw_cfg_add_bytes (fw_cfg,FW_CFG_E820_TABLE , &e820_reserve,sizeof (e820_reserve));fw_cfg_add_file (fw_cfg,"etc/e820" , e820_table, -sizeof (struct e820_entry ) * e820_entries); +sizeof (struct e820_entry ) *e820_get_num_entries ());fw_cfg_add_bytes (fw_cfg,FW_CFG_HPET , &hpet_cfg,sizeof (hpet_cfg));/* allocate memory for the NUMA channel: one (64bit) word for the number
Signature · 1 line
2.20.1
PATCH v4 2/15 hw/i386/pc: Extract e820 memory layout code
In reply to Philippe Mathieu-Daudé---
v3: KISS, do not use unsigned, do not add broken documentation
--- hw/i386/Makefile.objs | 2 +- hw/i386/e820_memory_layout.c | 59 ++++++++++++++++++++++++++++++++++ hw/i386/e820_memory_layout.h | 42 +++++++++++++++++++++++++ hw/i386/pc.c | 61 +----------------------------------- include/hw/i386/pc.h | 11 ------- target/i386/kvm.c | 1 + 6 files changed, 104 insertions(+), 72 deletions(-) create mode 100644 hw/i386/e820_memory_layout.c create mode 100644 hw/i386/e820_memory_layout.h
hw/i386/Makefile.objs +1 -1
@@ -1,5 +1,5 @@ obj-$(CONFIG_KVM) += kvm/ -obj-y += multiboot.o +obj-y += e820_memory_layout.o multiboot.o obj-y += pc.o obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_Q35) += pc_q35.o
hw/i386/e820_memory_layout.c new file +59 -0
59 lines not on this page · raw message
hw/i386/e820_memory_layout.h new file +42 -0
42 lines not on this page · raw message
hw/i386/pc.c +1 -60
79 lines not on this page · raw message
include/hw/i386/pc.h +0 -11
@@ -290,17 +290,6 @@ void pc_system_firmware_init(PCMachineState *pcms, MemoryRegion *rom_memory);void pc_madt_cpu_entry (AcpiDeviceIf *adev,int uid,const CPUArchIdList *apic_ids,GArray *entry); -/* e820 types */ -#define E820_RAM 1 -#define E820_RESERVED 2 -#define E820_ACPI 3 -#define E820_NVS 4 -#define E820_UNUSABLE 5 - -int e820_add_entry (uint64_t ,uint64_t ,uint32_t ); -int e820_get_num_entries (void ); -bool e820_get_entry (int ,uint32_t ,uint64_t *,uint64_t *); -extern GlobalProperty pc_compat_4_0[];extern const size_t pc_compat_4_0_len;
target/i386/kvm.c +1 -0
@@ -41,6 +41,7 @@#include "hw/i386/apic-msidef.h" #include "hw/i386/intel_iommu.h" #include "hw/i386/x86-iommu.h" +#include "hw/i386/e820_memory_layout.h" #include "hw/pci/pci.h" #include "hw/pci/msi.h"
Signature · 1 line
2.20.1
PATCH v4 3/15 hw/i386/pc: Use address_space_memory in place
In reply to Philippe Mathieu-DaudéThe address_space_memory variable is used once. Use it in place and remove the argument.
--- hw/i386/pc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
hw/i386/pc.c +4 -3
@@ -933,7 +933,7 @@ static void pc_build_smbios(PCMachineState *pcms) } } -static FWCfgState *bochs_bios_init (AddressSpace *as,PCMachineState *pcms) +static FWCfgState *bochs_bios_init (PCMachineState *pcms) {FWCfgState *fw_cfg;uint64_t *numa_fw_cfg;
@@ -941,7 +941,8 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms)const CPUArchIdList *cpus;MachineClass *mc =MACHINE_GET_CLASS (pcms); - fw_cfg =fw_cfg_init_io_dma (FW_CFG_IO_BASE ,FW_CFG_IO_BASE +4 , as); + fw_cfg =fw_cfg_init_io_dma (FW_CFG_IO_BASE ,FW_CFG_IO_BASE +4 , + &address_space_memory);fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus);/* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86:
@@ -1853,7 +1854,7 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr, 1); - fw_cfg =bochs_bios_init (&address_space_memory, pcms); + fw_cfg =bochs_bios_init (pcms);rom_set_fw (fw_cfg);
Signature · 1 line
2.20.1
PATCH v4 4/15 hw/i386/pc: Rename bochs_bios_init as more generic fw_cfg_arch_create
In reply to Philippe Mathieu-DaudéThe bochs_bios_init() function is not restricted to the Bochs BIOS and is useful to other BIOS.
Since it is not specific to the PC machine, and can be reused by other machines of the X86 architecture, rename it as fw_cfg_arch_create().
---
v2: Rename x86_create_fw_cfg() -> fw_cfg_arch_create() (MST)
--- hw/i386/pc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
hw/i386/pc.c +3 -3
@@ -933,7 +933,7 @@ static void pc_build_smbios(PCMachineState *pcms) } } -static FWCfgState *bochs_bios_init (PCMachineState *pcms) +static FWCfgState *fw_cfg_arch_create (PCMachineState *pcms) {FWCfgState *fw_cfg;uint64_t *numa_fw_cfg;
@@ -1600,7 +1600,7 @@ void pc_cpus_init(PCMachineState *pcms)* Limit for the APIC ID value, so that all * CPU APIC IDs are < pcms->apic_id_limit. * -* This is used for FW_CFG_MAX_CPUS. See comments on bochs_bios_init(). +* This is used for FW_CFG_MAX_CPUS. See comments on fw_cfg_arch_create(). */ pcms->apic_id_limit =x86_cpu_apic_id_from_index (pcms, ms->smp.max_cpus -1 ) +1 ;
@@ -1854,7 +1854,7 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr, 1); - fw_cfg =bochs_bios_init (pcms); + fw_cfg =fw_cfg_arch_create (pcms);rom_set_fw (fw_cfg);
Signature · 1 line
2.20.1
PATCH v4 5/15 hw/i386/pc: Pass the boot_cpus value by argument
In reply to Philippe Mathieu-DaudéThe boot_cpus is used once. Pass it by argument, this will allow us to remove the PCMachineState argument later.
--- hw/i386/pc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
hw/i386/pc.c +4 -3
@@ -933,7 +933,8 @@ static void pc_build_smbios(PCMachineState *pcms) } } -static FWCfgState *fw_cfg_arch_create (PCMachineState *pcms) +static FWCfgState *fw_cfg_arch_create (PCMachineState *pcms, +uint16_t boot_cpus) {FWCfgState *fw_cfg;uint64_t *numa_fw_cfg;
@@ -943,7 +944,7 @@ static FWCfgState *fw_cfg_arch_create(PCMachineState *pcms) fw_cfg =fw_cfg_init_io_dma (FW_CFG_IO_BASE ,FW_CFG_IO_BASE +4 , &address_space_memory); -fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus); +fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , boot_cpus);/* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86: *
@@ -1854,7 +1855,7 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr, 1); - fw_cfg =fw_cfg_arch_create (pcms); + fw_cfg =fw_cfg_arch_create (pcms, pcms->boot_cpus);rom_set_fw (fw_cfg);
Signature · 1 line
2.20.1
PATCH v4 6/15 hw/i386/pc: Pass the apic_id_limit value by argument
In reply to Philippe Mathieu-DaudéPass the apic_id_limit value by argument, this will allow us to remove the PCMachineState argument later.
--- hw/i386/pc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
hw/i386/pc.c +3 -2
@@ -934,7 +934,8 @@ static void pc_build_smbios(PCMachineState *pcms) }static FWCfgState *fw_cfg_arch_create (PCMachineState *pcms, -uint16_t boot_cpus) +uint16_t boot_cpus, +uint16_t apic_id_limit) {FWCfgState *fw_cfg;uint64_t *numa_fw_cfg;
@@ -1855,7 +1856,7 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr, 1); - fw_cfg =fw_cfg_arch_create (pcms, pcms->boot_cpus); + fw_cfg =fw_cfg_arch_create (pcms, pcms->boot_cpus, pcms->apic_id_limit);rom_set_fw (fw_cfg);
Signature · 1 line
2.20.1
PATCH v4 7/15 hw/i386/pc: Pass the CPUArchIdList array by argument
In reply to Philippe Mathieu-DaudéPass the CPUArchIdList array by argument, this will allow us to remove the PCMachineState argument later.
--- hw/i386/pc.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
hw/i386/pc.c +9 -10
@@ -934,14 +934,13 @@ static void pc_build_smbios(PCMachineState *pcms) }static FWCfgState *fw_cfg_arch_create (PCMachineState *pcms, +const CPUArchIdList *cpus,uint16_t boot_cpus,uint16_t apic_id_limit) {FWCfgState *fw_cfg;uint64_t *numa_fw_cfg;int i; -const CPUArchIdList *cpus; -MachineClass *mc =MACHINE_GET_CLASS (pcms); fw_cfg =fw_cfg_init_io_dma (FW_CFG_IO_BASE ,FW_CFG_IO_BASE +4 , &address_space_memory);
@@ -959,7 +958,7 @@ static FWCfgState *fw_cfg_arch_create(PCMachineState *pcms,* So for compatibility reasons with old BIOSes we are stuck with * "etc/max-cpus" actually being apic_id_limit */ -fw_cfg_add_i16 (fw_cfg,FW_CFG_MAX_CPUS , (uint16_t )pcms->apic_id_limit); +fw_cfg_add_i16 (fw_cfg,FW_CFG_MAX_CPUS , apic_id_limit);fw_cfg_add_i64 (fw_cfg,FW_CFG_RAM_SIZE , (uint64_t )ram_size);fw_cfg_add_bytes (fw_cfg,FW_CFG_ACPI_TABLES , acpi_tables, acpi_tables_len);
@@ -975,20 +974,19 @@ static FWCfgState *fw_cfg_arch_create(PCMachineState *pcms,* of nodes, one word for each VCPU->node and one word for each node to * hold the amount of memory. */ - numa_fw_cfg =g_new0 (uint64_t,1 + pcms->apic_id_limit + nb_numa_nodes); + numa_fw_cfg =g_new0 (uint64_t,1 + apic_id_limit + nb_numa_nodes); numa_fw_cfg[0 ] =cpu_to_le64 (nb_numa_nodes); - cpus = mc->possible_cpu_arch_ids (MACHINE (pcms));for (i =0 ; i < cpus->len; i++) {unsigned int apic_id = cpus->cpus[i].arch_id; -assert (apic_id < pcms->apic_id_limit); +assert (apic_id < apic_id_limit); numa_fw_cfg[apic_id +1 ] =cpu_to_le64 (cpus->cpus[i].props.node_id); }for (i =0 ; i < nb_numa_nodes; i++) { - numa_fw_cfg[pcms->apic_id_limit +1 + i] = + numa_fw_cfg[apic_id_limit +1 + i] =cpu_to_le64 (numa_info[i].node_mem); }fw_cfg_add_bytes (fw_cfg,FW_CFG_NUMA , numa_fw_cfg, - (1 + pcms->apic_id_limit + nb_numa_nodes) * + (1 + apic_id_limit + nb_numa_nodes) *sizeof (*numa_fw_cfg));return fw_cfg;
@@ -1760,6 +1758,7 @@ void pc_memory_init(PCMachineState *pcms,MemoryRegion *ram_below_4g, *ram_above_4g;FWCfgState *fw_cfg;MachineState *machine =MACHINE (pcms); +MachineClass *mc =MACHINE_GET_CLASS (machine);PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (pcms); assert(machine->ram_size == pcms->below_4g_mem_size +
@@ -1793,7 +1792,6 @@ void pc_memory_init(PCMachineState *pcms,if (!pcmc->has_reserved_memory && (machine->ram_slots || (machine->maxram_size > machine->ram_size))) { -MachineClass *mc =MACHINE_GET_CLASS (machine);error_report ("\"-memory 'slots|maxmem'\" is not supported by: %s" , mc->name);
@@ -1856,7 +1854,8 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr, 1); - fw_cfg =fw_cfg_arch_create (pcms, pcms->boot_cpus, pcms->apic_id_limit); + fw_cfg =fw_cfg_arch_create (pcms, mc->possible_cpu_arch_ids (machine), + pcms->boot_cpus, pcms->apic_id_limit);rom_set_fw (fw_cfg);
Signature · 1 line
2.20.1
PATCH v4 8/15 hw/i386/pc: Remove unused PCMachineState argument in fw_cfg_arch_create
In reply to Philippe Mathieu-DaudéIn the previous commit we removed the last access to PCMachineState. It is now an unused argument, remove it from the function prototype.
--- hw/i386/pc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
hw/i386/pc.c +2 -3
@@ -933,8 +933,7 @@ static void pc_build_smbios(PCMachineState *pcms) } } -static FWCfgState *fw_cfg_arch_create (PCMachineState *pcms, -const CPUArchIdList *cpus, +static FWCfgState *fw_cfg_arch_create (const CPUArchIdList *cpus,uint16_t boot_cpus,uint16_t apic_id_limit) {
@@ -1854,7 +1853,7 @@ void pc_memory_init(PCMachineState *pcms, option_rom_mr, 1); - fw_cfg =fw_cfg_arch_create (pcms, mc->possible_cpu_arch_ids (machine), + fw_cfg =fw_cfg_arch_create (mc->possible_cpu_arch_ids (machine), pcms->boot_cpus, pcms->apic_id_limit);rom_set_fw (fw_cfg);
Signature · 1 line
2.20.1
PATCH v4 9/15 hw/i386/pc: Let pc_build_smbios() take a FWCfgState argument
In reply to Philippe Mathieu-DaudéPass the FWCfgState object by argument, this will allow us to remove the PCMachineState argument later.
--- hw/i386/pc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
hw/i386/pc.c +5 -5
@@ -891,7 +891,7 @@ static uint32_t x86_cpu_apic_id_from_index(PCMachineState *pcms, } } -static void pc_build_smbios (PCMachineState *pcms) +static void pc_build_smbios (PCMachineState *pcms,FWCfgState *fw_cfg) {uint8_t *smbios_tables, *smbios_anchor;size_t smbios_tables_len, smbios_anchor_len;
@@ -905,7 +905,7 @@ static void pc_build_smbios(PCMachineState *pcms) smbios_tables =smbios_get_table_legacy (ms, &smbios_tables_len);if (smbios_tables) { -fw_cfg_add_bytes (pcms->fw_cfg,FW_CFG_SMBIOS_ENTRIES , +fw_cfg_add_bytes (fw_cfg,FW_CFG_SMBIOS_ENTRIES , smbios_tables, smbios_tables_len); }
@@ -926,9 +926,9 @@ static void pc_build_smbios(PCMachineState *pcms)g_free (mem_array);if (smbios_anchor) { -fw_cfg_add_file (pcms->fw_cfg,"etc/smbios/smbios-tables" , +fw_cfg_add_file (fw_cfg,"etc/smbios/smbios-tables" , smbios_tables, smbios_tables_len); -fw_cfg_add_file (pcms->fw_cfg,"etc/smbios/smbios-anchor" , +fw_cfg_add_file (fw_cfg,"etc/smbios/smbios-anchor" , smbios_anchor, smbios_anchor_len); } }
@@ -1680,7 +1680,7 @@ void pc_machine_done(Notifier *notifier, void *data)acpi_setup ();if (pcms->fw_cfg) { -pc_build_smbios (pcms); +pc_build_smbios (pcms, pcms->fw_cfg);pc_build_feature_control_file (pcms);/* update FW_CFG_NB_CPUS to account for -device added CPUs */ fw_cfg_modify_i16 (pcms->fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus);
Signature · 1 line
2.20.1
PATCH v4 10/15 hw/i386/pc: Let pc_build_smbios() take a generic MachineState argument
In reply to Philippe Mathieu-DaudéLet the pc_build_smbios() function take a generic MachineState argument.
--- hw/i386/pc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
hw/i386/pc.c +2 -3
@@ -891,13 +891,12 @@ static uint32_t x86_cpu_apic_id_from_index(PCMachineState *pcms, } } -static void pc_build_smbios (PCMachineState *pcms,FWCfgState *fw_cfg) +static void pc_build_smbios (MachineState *ms,FWCfgState *fw_cfg) {uint8_t *smbios_tables, *smbios_anchor;size_t smbios_tables_len, smbios_anchor_len;struct smbios_phys_mem_area *mem_array;unsigned i, array_count; -MachineState *ms =MACHINE (pcms);X86CPU *cpu =X86_CPU (ms->possible_cpus->cpus[0 ].cpu);/* tell smbios about cpuid version and features */
@@ -1680,7 +1679,7 @@ void pc_machine_done(Notifier *notifier, void *data)acpi_setup ();if (pcms->fw_cfg) { -pc_build_smbios (pcms, pcms->fw_cfg); +pc_build_smbios (MACHINE (pcms), pcms->fw_cfg);pc_build_feature_control_file (pcms);/* update FW_CFG_NB_CPUS to account for -device added CPUs */ fw_cfg_modify_i16 (pcms->fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus);
Signature · 1 line
2.20.1
PATCH v4 11/15 hw/i386/pc: Rename pc_build_smbios() as generic fw_cfg_build_smbios()
In reply to Philippe Mathieu-DaudéNow that the pc_build_smbios() function has been refactored to not depend of PC specific types, rename it to a more generic name.
--- hw/i386/pc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
hw/i386/pc.c +2 -2
@@ -891,7 +891,7 @@ static uint32_t x86_cpu_apic_id_from_index(PCMachineState *pcms, } } -static void pc_build_smbios (MachineState *ms,FWCfgState *fw_cfg) +static void fw_cfg_build_smbios (MachineState *ms,FWCfgState *fw_cfg) {uint8_t *smbios_tables, *smbios_anchor;size_t smbios_tables_len, smbios_anchor_len;
@@ -1679,7 +1679,7 @@ void pc_machine_done(Notifier *notifier, void *data)acpi_setup ();if (pcms->fw_cfg) { -pc_build_smbios (MACHINE (pcms), pcms->fw_cfg); +fw_cfg_build_smbios (MACHINE (pcms), pcms->fw_cfg);pc_build_feature_control_file (pcms);/* update FW_CFG_NB_CPUS to account for -device added CPUs */ fw_cfg_modify_i16 (pcms->fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus);
Signature · 1 line
2.20.1
PATCH v4 12/15 hw/i386/pc: Let pc_build_feature_control() take a FWCfgState argument
In reply to Philippe Mathieu-DaudéPass the FWCfgState object by argument, this will allow us to remove the PCMachineState argument later.
--- hw/i386/pc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
hw/i386/pc.c +4 -3
@@ -1608,7 +1608,8 @@ void pc_cpus_init(PCMachineState *pcms) } } -static void pc_build_feature_control_file (PCMachineState *pcms) +static void pc_build_feature_control_file (PCMachineState *pcms, +FWCfgState *fw_cfg) {MachineState *ms =MACHINE (pcms);X86CPU *cpu =X86_CPU (ms->possible_cpus->cpus[0 ].cpu);
@@ -1634,7 +1635,7 @@ static void pc_build_feature_control_file(PCMachineState *pcms) val =g_malloc (sizeof (*val)); *val =cpu_to_le64 (feature_control_bits |FEATURE_CONTROL_LOCKED ); -fw_cfg_add_file (pcms->fw_cfg,"etc/msr_feature_control" , val,sizeof (*val)); +fw_cfg_add_file (fw_cfg,"etc/msr_feature_control" , val,sizeof (*val)); }static void rtc_set_cpus_count (ISADevice *rtc,uint16_t cpus_count)
@@ -1680,7 +1681,7 @@ void pc_machine_done(Notifier *notifier, void *data)acpi_setup ();if (pcms->fw_cfg) {fw_cfg_build_smbios (MACHINE (pcms), pcms->fw_cfg); -pc_build_feature_control_file (pcms); +pc_build_feature_control_file (pcms, pcms->fw_cfg);/* update FW_CFG_NB_CPUS to account for -device added CPUs */ fw_cfg_modify_i16 (pcms->fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus); }
Signature · 1 line
2.20.1
PATCH v4 13/15 hw/i386/pc: Let pc_build_feature_control() take a MachineState argument
In reply to Philippe Mathieu-DaudéLet the pc_build_feature_control_file() function take a generic MachineState argument.
--- hw/i386/pc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
hw/i386/pc.c +2 -3
@@ -1608,10 +1608,9 @@ void pc_cpus_init(PCMachineState *pcms) } } -static void pc_build_feature_control_file (PCMachineState *pcms, +static void pc_build_feature_control_file (MachineState *ms,FWCfgState *fw_cfg) { -MachineState *ms =MACHINE (pcms);X86CPU *cpu =X86_CPU (ms->possible_cpus->cpus[0 ].cpu);CPUX86State *env = &cpu->env;uint32_t unused, ecx, edx;
@@ -1681,7 +1680,7 @@ void pc_machine_done(Notifier *notifier, void *data)acpi_setup ();if (pcms->fw_cfg) {fw_cfg_build_smbios (MACHINE (pcms), pcms->fw_cfg); -pc_build_feature_control_file (pcms, pcms->fw_cfg); +pc_build_feature_control_file (MACHINE (pcms), pcms->fw_cfg);/* update FW_CFG_NB_CPUS to account for -device added CPUs */ fw_cfg_modify_i16 (pcms->fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus); }
Signature · 1 line
2.20.1
PATCH v4 14/15 hw/i386/pc: Rename pc_build_feature_control() as generic fw_cfg_build_*
In reply to Philippe Mathieu-DaudéNow that the pc_build_feature_control_file() function has been refactored to not depend of PC specific types, rename it to a more generic name.
--- hw/i386/pc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
hw/i386/pc.c +3 -3
@@ -1608,8 +1608,8 @@ void pc_cpus_init(PCMachineState *pcms) } } -static void pc_build_feature_control_file (MachineState *ms, -FWCfgState *fw_cfg) +static void fw_cfg_build_feature_control (MachineState *ms, +FWCfgState *fw_cfg) {X86CPU *cpu =X86_CPU (ms->possible_cpus->cpus[0 ].cpu);CPUX86State *env = &cpu->env;
@@ -1680,7 +1680,7 @@ void pc_machine_done(Notifier *notifier, void *data)acpi_setup ();if (pcms->fw_cfg) {fw_cfg_build_smbios (MACHINE (pcms), pcms->fw_cfg); -pc_build_feature_control_file (MACHINE (pcms), pcms->fw_cfg); +fw_cfg_build_feature_control (MACHINE (pcms), pcms->fw_cfg);/* update FW_CFG_NB_CPUS to account for -device added CPUs */ fw_cfg_modify_i16 (pcms->fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus); }
Signature · 1 line
2.20.1
PATCH v4 15/15 hw/i386/pc: Extract the x86 generic fw_cfg code
In reply to Philippe Mathieu-DaudéExtract all the functions that are not PC-machine specific into the (arch-specific) fw_cfg.c file. This will allow other X86-machine to reuse these functions.
---
v4: rebased using MachineState argument with smbios_get_tables*()
calls but not with fw_cfg_arch_create().
--- hw/i386/fw_cfg.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++ hw/i386/fw_cfg.h | 7 +++ hw/i386/pc.c | 129 +------------------------------------------- 3 files changed, 144 insertions(+), 128 deletions(-)
hw/i386/fw_cfg.c +136 -0
@@ -13,8 +13,15 @@*/ #include "qemu/osdep.h" +#include "sysemu/numa.h" +#include "hw/acpi/acpi.h" +#include "hw/firmware/smbios.h" +#include "hw/i386/pc.h" #include "hw/i386/fw_cfg.h" +#include "hw/timer/hpet.h" #include "hw/nvram/fw_cfg.h" +#include "e820_memory_layout.h" +#include "kvm_i386.h" const char *fw_cfg_arch_key_name (uint16_t key) {
@@ -36,3 +43,132 @@ const char *fw_cfg_arch_key_name(uint16_t key) }return NULL ; } + +FWCfgState *fw_cfg_arch_create (const CPUArchIdList *cpus, +uint16_t boot_cpus, +uint16_t apic_id_limit) +{ +FWCfgState *fw_cfg; +uint64_t *numa_fw_cfg; +int i; + + fw_cfg =fw_cfg_init_io_dma (FW_CFG_IO_BASE ,FW_CFG_IO_BASE +4 , + &address_space_memory); +fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , boot_cpus); + +/* +* FW_CFG_MAX_CPUS is a bit confusing/problematic on x86: +* +* For machine types prior to 1.8, SeaBIOS needs FW_CFG_MAX_CPUS for +* building MPTable, ACPI MADT, ACPI CPU hotplug and ACPI SRAT table, +* that tables are based on xAPIC ID and QEMU<->SeaBIOS interface +* for CPU hotplug also uses APIC ID and not "CPU index". +* This means that FW_CFG_MAX_CPUS is not the "maximum number of CPUs", +* but the "limit to the APIC ID values SeaBIOS may see". +* +* So for compatibility reasons with old BIOSes we are stuck with +* "etc/max-cpus" actually being apic_id_limit +*/ +fw_cfg_add_i16 (fw_cfg,FW_CFG_MAX_CPUS , apic_id_limit); +fw_cfg_add_i64 (fw_cfg,FW_CFG_RAM_SIZE , (uint64_t )ram_size); +fw_cfg_add_bytes (fw_cfg,FW_CFG_ACPI_TABLES , + acpi_tables, acpi_tables_len); +fw_cfg_add_i32 (fw_cfg,FW_CFG_IRQ0_OVERRIDE ,kvm_allows_irq0_override ()); + +fw_cfg_add_bytes (fw_cfg,FW_CFG_E820_TABLE , + &e820_reserve,sizeof (e820_reserve)); +fw_cfg_add_file (fw_cfg,"etc/e820" , e820_table, +sizeof (struct e820_entry ) *e820_get_num_entries ()); + +fw_cfg_add_bytes (fw_cfg,FW_CFG_HPET , &hpet_cfg,sizeof (hpet_cfg)); +/* +* allocate memory for the NUMA channel: one (64bit) word for the number +* of nodes, one word for each VCPU->node and one word for each node to +* hold the amount of memory. +*/ + numa_fw_cfg =g_new0 (uint64_t,1 + apic_id_limit + nb_numa_nodes); + numa_fw_cfg[0 ] =cpu_to_le64 (nb_numa_nodes); +for (i =0 ; i < cpus->len; i++) { +unsigned int apic_id = cpus->cpus[i].arch_id; +assert (apic_id < apic_id_limit); + numa_fw_cfg[apic_id +1 ] =cpu_to_le64 (cpus->cpus[i].props.node_id); + } +for (i =0 ; i < nb_numa_nodes; i++) { + numa_fw_cfg[apic_id_limit +1 + i] = +cpu_to_le64 (numa_info[i].node_mem); + } +fw_cfg_add_bytes (fw_cfg,FW_CFG_NUMA , numa_fw_cfg, + (1 + apic_id_limit + nb_numa_nodes) * +sizeof (*numa_fw_cfg)); + +return fw_cfg; +} + +void fw_cfg_build_smbios (MachineState *ms,FWCfgState *fw_cfg) +{ +uint8_t *smbios_tables, *smbios_anchor; +size_t smbios_tables_len, smbios_anchor_len; +struct smbios_phys_mem_area *mem_array; +unsigned i, array_count; +X86CPU *cpu =X86_CPU (ms->possible_cpus->cpus[0 ].cpu); + +/* tell smbios about cpuid version and features */ +smbios_set_cpuid (cpu->env.cpuid_version, cpu->env.features[FEAT_1_EDX ]); + + smbios_tables =smbios_get_table_legacy (ms, &smbios_tables_len); +if (smbios_tables) { +fw_cfg_add_bytes (fw_cfg,FW_CFG_SMBIOS_ENTRIES , + smbios_tables, smbios_tables_len); + } + +/* build the array of physical mem area from e820 table */ + mem_array =g_malloc0 (sizeof (*mem_array) *e820_get_num_entries ()); +for (i =0 , array_count =0 ; i <e820_get_num_entries (); i++) { +uint64_t addr, len; + +if (e820_get_entry (i,E820_RAM , &addr, &len)) { + mem_array[array_count].address = addr; + mem_array[array_count].length = len; + array_count++; + } + } +smbios_get_tables (ms, mem_array, array_count, + &smbios_tables, &smbios_tables_len, + &smbios_anchor, &smbios_anchor_len); +g_free (mem_array); + +if (smbios_anchor) { +fw_cfg_add_file (fw_cfg,"etc/smbios/smbios-tables" , + smbios_tables, smbios_tables_len); +fw_cfg_add_file (fw_cfg,"etc/smbios/smbios-anchor" , + smbios_anchor, smbios_anchor_len); + } +} + +void fw_cfg_build_feature_control (MachineState *ms,FWCfgState *fw_cfg) +{ +X86CPU *cpu =X86_CPU (ms->possible_cpus->cpus[0 ].cpu); +CPUX86State *env = &cpu->env; +uint32_t unused, ecx, edx; +uint64_t feature_control_bits =0 ; +uint64_t *val; + +cpu_x86_cpuid (env,1 ,0 , &unused, &unused, &ecx, &edx); +if (ecx &CPUID_EXT_VMX ) { + feature_control_bits |=FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX ; + } + +if ((edx & (CPUID_EXT2_MCE |CPUID_EXT2_MCA )) == + (CPUID_EXT2_MCE |CPUID_EXT2_MCA ) && + (env->mcg_cap &MCG_LMCE_P )) { + feature_control_bits |=FEATURE_CONTROL_LMCE ; + } + +if (!feature_control_bits) { +return ; + } + + val =g_malloc (sizeof (*val)); + *val =cpu_to_le64 (feature_control_bits |FEATURE_CONTROL_LOCKED ); +fw_cfg_add_file (fw_cfg,"etc/msr_feature_control" , val,sizeof (*val)); +}
hw/i386/fw_cfg.h +7 -0
@@ -9,6 +9,7 @@#ifndef HW_I386_FW_CFG_H #define HW_I386_FW_CFG_H +#include "hw/boards.h" #include "hw/nvram/fw_cfg.h" #define FW_CFG_ACPI_TABLES (FW_CFG_ARCH_LOCAL + 0)
@@ -17,4 +18,10 @@#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) +FWCfgState *fw_cfg_arch_create (const CPUArchIdList *cpus, +uint16_t boot_cpus, +uint16_t apic_id_limit); +void fw_cfg_build_smbios (MachineState *ms,FWCfgState *fw_cfg); +void fw_cfg_build_feature_control (MachineState *ms,FWCfgState *fw_cfg); +#endif
hw/i386/pc.c +1 -128
147 lines not on this page · raw message
Signature · 1 line
2.20.1
Quoted 74 lines · Philippe Mathieu-Daudé
Hi,
This is my take at salvaging some NEMU good work.
Samuel worked in adding thefw_cfgdevice to the x86-virt NEMU machine. This series is inspired by NEMU's commit3cb92d080835[0] and adapted to upstream style. The result makes the upstream codebase more modularizable.
There are very little logical changes, this is mostly a cleanup refactor.Since v3 [3]:
- Addressed Christophe suggestion (patch #8)
- Rebased patch #15 since Eduardo merged Like Xu's work between.Since v2 [2]:
- Addressed MST comments from v2 (only patch #2 modified)
- do not use unsigned for enum
- do not add unuseful documentationSince v1 [1]:
- Addressed Li and MST comments$ git backport-diff -u v3 Key: [----] : patches are identical [####] : number of functional differences between upstream/downstream patch [down] : patch is downstream-only The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively001/15:[----] [--] 'hw/i386/pc: Use
e820_get_num_entries()to accesse820_entries' 002/15:[----] [-C] 'hw/i386/pc: Extract e820 memory layout code' 003/15:[----] [--] 'hw/i386/pc: Useaddress_space_memoryin place' 004/15:[----] [-C] 'hw/i386/pc: Renamebochs_bios_initas more genericfw_cfg_arch_create' 005/15:[----] [--] 'hw/i386/pc: Pass theboot_cpusvalue by argument' 006/15:[----] [--] 'hw/i386/pc: Pass theapic_id_limitvalue by argument' 007/15:[0002] [FC] 'hw/i386/pc: Pass the CPUArchIdList array by argument' 008/15:[down] 'hw/i386/pc: Remove unused PCMachineState argument infw_cfg_arch_create' 009/15:[----] [-C] 'hw/i386/pc: Letpc_build_smbios()take a FWCfgState argument' 010/15:[----] [-C] 'hw/i386/pc: Letpc_build_smbios()take a generic MachineState argument' 011/15:[----] [-C] 'hw/i386/pc: Renamepc_build_smbios()as genericfw_cfg_build_smbios()' 012/15:[----] [--] 'hw/i386/pc: Letpc_build_feature_control()take a FWCfgState argument' 013/15:[----] [--] 'hw/i386/pc: Letpc_build_feature_control()take a MachineState argument' 014/15:[----] [--] 'hw/i386/pc: Renamepc_build_feature_control()as generic fw_cfg_build_*' 015/15:[0017] [FC] 'hw/i386/pc: Extract the x86 genericfw_cfgcode'Regards,
Phil.
[0] https://github.com/intel/nemu/commit/3cb92d080835ac8d47c8b713156338afa33cff5c
[1] https://lists.gnu.org/archive/html/qemu-devel/2019-05/msg05759.html
[2] https://lists.gnu.org/archive/html/qemu-devel/2019-06/msg02786.html
[3] https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg00193.htmlPhilippe Mathieu-Daudé (15):
hw/i386/pc: Usee820_get_num_entries()to accesse820_entrieshw/i386/pc: Extract e820 memory layout code
hw/i386/pc: Useaddress_space_memoryin place
hw/i386/pc: Renamebochs_bios_initas more genericfw_cfg_arch_createhw/i386/pc: Pass theboot_cpusvalue by argument hw/i386/pc: Pass theapic_id_limitvalue by argument hw/i386/pc: Pass the CPUArchIdList array by argument hw/i386/pc: Remove unused PCMachineState argument in
fw_cfg_arch_create
hw/i386/pc: Letpc_build_smbios()take a FWCfgState argument hw/i386/pc: Letpc_build_smbios()take a generic MachineState argument hw/i386/pc: Renamepc_build_smbios()as genericfw_cfg_build_smbios()hw/i386/pc: Letpc_build_feature_control()take a FWCfgState argument hw/i386/pc: Letpc_build_feature_control()take a MachineState
argument
hw/i386/pc: Renamepc_build_feature_control()as genericfw_cfg_build_*hw/i386/pc: Extract the x86 generic
fw_cfgcode
Quoted 12 lines
hw/i386/Makefile.objs | 2 +- hw/i386/e820_memory_layout.c | 59 ++++++++++ hw/i386/e820_memory_layout.h | 42 ++++++++ hw/i386/fw_cfg.c | 136 +++++++++++++++++++++++ hw/i386/fw_cfg.h | 7 ++ hw/i386/pc.c | 202 ++--------------------------------- include/hw/i386/pc.h | 11 -- target/i386/kvm.c | 1 + 8 files changed, 254 insertions(+), 206 deletions(-) create mode 100644 hw/i386/e820_memory_layout.c create mode 100644 hw/i386/e820_memory_layout.h
Queued, thanks.
Paolo