ACPI reorganization for hardware-reduced support
v2 cover ACPI reorganization for hardware-reduced support
This patch set provides an ACPI code reorganization in preparation for adding hardware-reduced support to QEMU.
The changes are coming from the NEMU [1] project where we're defining a new x86 machine type: i386/virt. This is an EFI only, ACPI hardware-reduced platform and as such we had to implement support for the latter.
As a preliminary for adding hardware-reduced support to QEMU, we did some ACPI code reorganization with the following goals:
* Share as much as possible of the current ACPI build APIs between legacy and hardware-reduced ACPI.
* Share the ACPI build code across machine types and architectures and remove the typical PC machine type dependency.
Eventually we hope to see arm/virt also re-use much of that code.
The patches are also available in their own git branch [2].
[1] https://github.com/intel/nemu
[2] https://github.com/intel/nemu/tree/topic/upstream/acpi
v1 -> v2:
* Drop the hardware-reduced implementation for now. Our next patch set will add hardware-reduced and convert arm/virt to it.
* Implement the ACPI build methods as a QOM Interface Class and convert the PC machine type to it.
Samuel Ortiz (10):
hw: i386: Decouple the ACPI build from the PC machine type
hw: acpi: Export ACPI build alignment API
hw: acpi: Export the RSDP build API
hw: acpi: Implement XSDT support for RSDP
hw: arm: Switch to the AML build RSDP building routine
hw: acpi: Do not create hotplug method when handler is not defined
hw: i386: Make the hotpluggable memory size property more generic
hw: acpi: Define ACPI tables builder interface
hw: i386: Export the MADT build method
hw: i386: Implement the ACPI builder interface for PC
Sebastien Boeuf (2):
hw: acpi: Export the PCI hotplug API
hw: acpi: Retrieve the PCI bus from AcpiPciHpState
Yang Zhong (7):
hw: acpi: Generalize AML build routines
hw: acpi: Factorize _OSC AML across architectures
hw: i386: Refactor PCI host getter
hw: acpi: Export and generalize the PCI host AML API
hw: acpi: Export the MCFG getter
hw: acpi: Export the SRAT AML build API
hw: acpi: Fix memory hotplug AML generation error
hw/acpi/Makefile.objs | 1 + hw/acpi/aml-build.c | 1129 ++++++++++++++++++++++++++++++ hw/acpi/builder.c | 97 +++ hw/acpi/cpu.c | 8 +- hw/acpi/cpu_hotplug.c | 9 +- hw/acpi/memory_hotplug.c | 21 +- hw/acpi/pcihp.c | 10 +- hw/arm/virt-acpi-build.c | 98 +-- hw/i386/acpi-build.c | 1174 ++------------------------------ hw/i386/acpi-build.h | 4 +- hw/i386/pc.c | 198 ++++-- hw/i386/pc_piix.c | 21 +- hw/i386/pc_q35.c | 21 +- hw/i386/xen/xen-hvm.c | 19 +- hw/pci-host/piix.c | 8 - include/hw/acpi/acpi-defs.h | 14 + include/hw/acpi/acpi.h | 43 ++ include/hw/acpi/aml-build.h | 50 ++ include/hw/acpi/builder.h | 97 +++ include/hw/i386/acpi.h | 27 + include/hw/i386/pc.h | 21 +- include/hw/mem/memory-device.h | 2 + stubs/Makefile.objs | 1 - stubs/pci-host-piix.c | 6 - 24 files changed, 1735 insertions(+), 1344 deletions(-) create mode 100644 hw/acpi/builder.c create mode 100644 include/hw/acpi/builder.h create mode 100644 include/hw/i386/acpi.h delete mode 100644 stubs/pci-host-piix.c
Signature · 1 line
2.17.2
PATCH v2 1/19 hw: i386: Decouple the ACPI build from the PC machine type
ACPI tables are platform and machine type and even architecture agnostic, and as such we want to provide an internal ACPI API that only depends on platform agnostic information.
For the x86 architecture, in order to build ACPI tables independently from the PC or Q35 machine types, we are moving a few MachineState structure fields into a machine type agnostic structure called AcpiConfiguration. The structure fields we move are:
HotplugHandler *acpi_dev AcpiNVDIMMState acpi_nvdimm_state; FWCfgState *fw_cfg
ram_addr_t below_4g_mem_size, above_4g_mem_size bool apic_xrupt_override
unsigned apic_id_limit
uint64_t numa_nodes
uint64_t numa_mem
--- hw/acpi/cpu_hotplug.c | 9 +- hw/arm/virt-acpi-build.c | 10 --- hw/i386/acpi-build.c | 135 ++++++++++++++---------------- hw/i386/acpi-build.h | 4 +- hw/i386/pc.c | 175 ++++++++++++++++++++++++--------------- hw/i386/pc_piix.c | 21 ++--- hw/i386/pc_q35.c | 21 ++--- hw/i386/xen/xen-hvm.c | 19 +++-- include/hw/acpi/acpi.h | 43 ++++++++++ include/hw/i386/pc.h | 19 ++--- 10 files changed, 254 insertions(+), 202 deletions(-)
hw/acpi/cpu_hotplug.c +5 -4
@@ -237,9 +237,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,/* The current AML generator can cover the APIC ID range [0..255], * inclusive, for VCPU hotplug. */ QEMU_BUILD_BUG_ON (ACPI_CPU_HOTPLUG_ID_LIMIT >256 ); -if (pcms->apic_id_limit >ACPI_CPU_HOTPLUG_ID_LIMIT ) { +if (pcms->acpi_configuration.apic_id_limit >ACPI_CPU_HOTPLUG_ID_LIMIT ) {error_report ("max_cpus is too large. APIC ID of last CPU is %u" , - pcms->apic_id_limit -1 ); + pcms->acpi_configuration.apic_id_limit -1 );exit (1 ); }
@@ -316,8 +316,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,* ith up to 255 elements. Windows guests up to win2k8 fail when * VarPackageOp is used. */ - pkg = pcms->apic_id_limit <=255 ?aml_package (pcms->apic_id_limit) : -aml_varpackage (pcms->apic_id_limit); + pkg = pcms->acpi_configuration.apic_id_limit <=255 ? +aml_package (pcms->acpi_configuration.apic_id_limit) : +aml_varpackage (pcms->acpi_configuration.apic_id_limit);for (i =0 , apic_idx =0 ; i < apic_ids->len; i++) {int apic_id = apic_ids->cpus[i].arch_id;
hw/arm/virt-acpi-build.c +0 -10
@@ -790,16 +790,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)free_aml_allocator (); } -typedef -struct AcpiBuildState { -/* Copy of table in RAM (for patching). */ -MemoryRegion *table_mr; -MemoryRegion *rsdp_mr; -MemoryRegion *linker_mr; -/* Is table patched? */ -bool patched; -}AcpiBuildState ; -static void virt_acpi_build (VirtMachineState *vms,AcpiBuildTables *tables) {
hw/i386/acpi-build.c +60 -75
341 lines not on this page · raw message
hw/i386/acpi-build.h +3 -1
@@ -2,6 +2,8 @@#ifndef HW_I386_ACPI_BUILD_H #define HW_I386_ACPI_BUILD_H -void acpi_setup (void ); +#include "hw/acpi/acpi.h" + +void acpi_setup (MachineState *machine,AcpiConfiguration *conf);#endif
hw/i386/pc.c +106 -69
477 lines not on this page · raw message
hw/i386/pc_piix.c +11 -10
@@ -71,6 +71,7 @@ static void pc_init1(MachineState *machine, {PCMachineState *pcms =PC_MACHINE (machine);PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (pcms); +AcpiConfiguration *conf = &pcms->acpi_configuration;MemoryRegion *system_memory =get_system_memory ();MemoryRegion *system_io =get_system_io ();int i;
@@ -142,11 +143,11 @@ static void pc_init1(MachineState *machine, }if (machine->ram_size >= lowmem) { - pcms->above_4g_mem_size = machine->ram_size - lowmem; - pcms->below_4g_mem_size = lowmem; + conf->above_4g_mem_size = machine->ram_size - lowmem; + conf->below_4g_mem_size = lowmem; }else { - pcms->above_4g_mem_size =0 ; - pcms->below_4g_mem_size = machine->ram_size; + conf->above_4g_mem_size =0 ; + conf->below_4g_mem_size = machine->ram_size; } }
@@ -199,8 +200,8 @@ static void pc_init1(MachineState *machine, pci_type, &i440fx_state, &piix3_devfn, &isa_bus, pcms->gsi, system_memory, system_io, machine->ram_size, - pcms->below_4g_mem_size, - pcms->above_4g_mem_size, + conf->below_4g_mem_size, + conf->above_4g_mem_size, pci_memory, ram_memory); pcms->bus = pci_bus; }else {
@@ -289,16 +290,16 @@ static void pc_init1(MachineState *machine,object_property_add_link (OBJECT (machine),PC_MACHINE_ACPI_DEVICE_PROP ,TYPE_HOTPLUG_HANDLER , - (Object **)&pcms->acpi_dev, + (Object **)&conf->acpi_dev, object_property_allow_set_link,OBJ_PROP_LINK_STRONG , &error_abort);object_property_set_link (OBJECT (machine),OBJECT (piix4_pm),PC_MACHINE_ACPI_DEVICE_PROP , &error_abort); } -if (pcms->acpi_nvdimm_state.is_enabled) { -nvdimm_init_acpi_state (&pcms->acpi_nvdimm_state, system_io, - pcms->fw_cfg,OBJECT (pcms)); +if (conf->acpi_nvdimm_state.is_enabled) { +nvdimm_init_acpi_state (&conf->acpi_nvdimm_state, system_io, + conf->fw_cfg,OBJECT (pcms)); } }
hw/i386/pc_q35.c +11 -10
@@ -63,6 +63,7 @@ static void pc_q35_init(MachineState *machine) {PCMachineState *pcms =PC_MACHINE (machine);PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (pcms); +AcpiConfiguration *conf = &pcms->acpi_configuration;Q35PCIHost *q35_host;PCIHostState *phb;PCIBus *host_bus;
@@ -116,11 +117,11 @@ static void pc_q35_init(MachineState *machine) }if (machine->ram_size >= lowmem) { - pcms->above_4g_mem_size = machine->ram_size - lowmem; - pcms->below_4g_mem_size = lowmem; + conf->above_4g_mem_size = machine->ram_size - lowmem; + conf->below_4g_mem_size = lowmem; }else { - pcms->above_4g_mem_size =0 ; - pcms->below_4g_mem_size = machine->ram_size; + conf->above_4g_mem_size =0 ; + conf->below_4g_mem_size = machine->ram_size; }if (xen_enabled ()) {
@@ -179,9 +180,9 @@ static void pc_q35_init(MachineState *machine) MCH_HOST_PROP_SYSTEM_MEM, NULL);object_property_set_link (OBJECT (q35_host),OBJECT (system_io),MCH_HOST_PROP_IO_MEM ,NULL ); -object_property_set_int (OBJECT (q35_host), pcms->below_4g_mem_size, +object_property_set_int (OBJECT (q35_host), conf->below_4g_mem_size,PCI_HOST_BELOW_4G_MEM_SIZE ,NULL ); -object_property_set_int (OBJECT (q35_host), pcms->above_4g_mem_size, +object_property_set_int (OBJECT (q35_host), conf->above_4g_mem_size,PCI_HOST_ABOVE_4G_MEM_SIZE ,NULL );/* pci */ qdev_init_nofail (DEVICE (q35_host));
@@ -194,7 +195,7 @@ static void pc_q35_init(MachineState *machine)object_property_add_link (OBJECT (machine),PC_MACHINE_ACPI_DEVICE_PROP ,TYPE_HOTPLUG_HANDLER , - (Object **)&pcms->acpi_dev, + (Object **)&conf->acpi_dev, object_property_allow_set_link,OBJ_PROP_LINK_STRONG , &error_abort); object_property_set_link(OBJECT(machine), OBJECT(lpc),
@@ -276,9 +277,9 @@ static void pc_q35_init(MachineState *machine)pc_vga_init (isa_bus, host_bus);pc_nic_init (pcmc, isa_bus, host_bus); -if (pcms->acpi_nvdimm_state.is_enabled) { -nvdimm_init_acpi_state (&pcms->acpi_nvdimm_state, system_io, - pcms->fw_cfg,OBJECT (pcms)); +if (conf->acpi_nvdimm_state.is_enabled) { +nvdimm_init_acpi_state (&conf->acpi_nvdimm_state, system_io, + conf->fw_cfg,OBJECT (pcms)); } }
hw/i386/xen/xen-hvm.c +10 -9
@@ -190,6 +190,7 @@ qemu_irq *xen_interrupt_controller_init(void)static void xen_ram_init (PCMachineState *pcms,ram_addr_t ram_size,MemoryRegion **ram_memory_p) { +AcpiConfiguration *conf = &pcms->acpi_configuration;MemoryRegion *sysmem =get_system_memory ();ram_addr_t block_len; uint64_t user_lowmem = object_property_get_uint(qdev_get_machine(),
@@ -207,20 +208,20 @@ static void xen_ram_init(PCMachineState *pcms, }if (ram_size >= user_lowmem) { - pcms->above_4g_mem_size = ram_size - user_lowmem; - pcms->below_4g_mem_size = user_lowmem; + conf->above_4g_mem_size = ram_size - user_lowmem; + conf->below_4g_mem_size = user_lowmem; }else { - pcms->above_4g_mem_size =0 ; - pcms->below_4g_mem_size = ram_size; + conf->above_4g_mem_size =0 ; + conf->below_4g_mem_size = ram_size; } -if (!pcms->above_4g_mem_size) { +if (!conf->above_4g_mem_size) { block_len = ram_size; }else {/* * Xen does not allocate the memory continuously, it keeps a * hole of the size computed above or passed in. */ - block_len = (1ULL <<32 ) + pcms->above_4g_mem_size; + block_len = (1ULL <<32 ) + conf->above_4g_mem_size; }memory_region_init_ram (&ram_memory,NULL ,"xen.ram" , block_len, &error_fatal);
@@ -237,12 +238,12 @@ static void xen_ram_init(PCMachineState *pcms,*/ memory_region_init_alias (&ram_lo,NULL ,"xen.ram.lo" , &ram_memory,0xc0000 , - pcms->below_4g_mem_size -0xc0000 ); + conf->below_4g_mem_size -0xc0000 );memory_region_add_subregion (sysmem,0xc0000 , &ram_lo); -if (pcms->above_4g_mem_size >0 ) { +if (conf->above_4g_mem_size >0 ) {memory_region_init_alias (&ram_hi,NULL ,"xen.ram.hi" , &ram_memory,0x100000000ULL , - pcms->above_4g_mem_size); + conf->above_4g_mem_size);memory_region_add_subregion (sysmem,0x100000000ULL , &ram_hi); } }
include/hw/acpi/acpi.h +43 -0
55 lines not on this page · raw message
include/hw/i386/pc.h +5 -14
@@ -12,6 +12,7 @@#include "qemu/range.h" #include "qemu/bitmap.h" #include "sysemu/sysemu.h" +#include "hw/acpi/acpi.h" #include "hw/pci/pci.h" #include "hw/compat.h" #include "hw/mem/pc-dimm.h"
@@ -35,10 +36,8 @@ struct PCMachineState {Notifier machine_done;/* Pointers to devices and objects: */ -HotplugHandler *acpi_dev;ISADevice *rtc;PCIBus *bus; -FWCfgState *fw_cfg;qemu_irq *gsi;/* Configuration options: */
@@ -46,28 +45,20 @@ struct PCMachineState {OnOffAuto vmport;OnOffAuto smm; -AcpiNVDIMMState acpi_nvdimm_state; -bool acpi_build_enabled;bool smbus;bool sata;bool pit; -/* RAM information (sizes, addresses, configuration): */ -ram_addr_t below_4g_mem_size, above_4g_mem_size; - -/* CPU and apic information: */ -bool apic_xrupt_override; -unsigned apic_id_limit; +/* CPU information */ uint16_t boot_cpus; -/* NUMA information: */ -uint64_t numa_nodes; -uint64_t *node_mem; -/* Address space used by IOAPIC device. All IOAPIC interrupts * will be translated to MSI messages in the address space. */ AddressSpace *ioapic_as; + +/* ACPI configuration */ +AcpiConfiguration acpi_configuration; };#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
Signature · 1 line
2.17.2
PATCH v2 2/19 hw: acpi: Export ACPI build alignment API
In reply to Samuel OrtizThis is going to be needed by the Hardware-reduced ACPI routines.
--- hw/acpi/aml-build.c | 8 ++++++++ hw/i386/acpi-build.c | 8 -------- include/hw/acpi/aml-build.h | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-)
hw/acpi/aml-build.c +8 -0
@@ -1565,6 +1565,14 @@ unsigned acpi_data_len(GArray *table)return table->len; } +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)); +} +void acpi_add_table (GArray *table_offsets,GArray *table_data) {uint32_t offset = table_data->len;
hw/i386/acpi-build.c +0 -8
@@ -282,14 +282,6 @@ static void acpi_get_pci_holes(Range *hole, Range *hole64) NULL)); } -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)); -} -/* FACS */ static void build_facs (GArray *table_data,BIOSLinker *linker)
include/hw/acpi/aml-build.h +2 -0
@@ -6,6 +6,7 @@/* Reserve RAM space for tables: add another order of magnitude. */ #define ACPI_BUILD_TABLE_MAX_SIZE 0x200000 +#define ACPI_BUILD_ALIGN_SIZE 0x1000#define ACPI_BUILD_APPNAME6 "BOCHS "#define ACPI_BUILD_APPNAME4 "BXPC"
@@ -384,6 +385,7 @@ build_header(BIOSLinker *linker, GArray *table_data, const char *oem_id, const char *oem_table_id);void *acpi_data_push (GArray *table_data,unsigned size);unsigned acpi_data_len (GArray *table); +void acpi_align_size (GArray *blob,unsigned align);void acpi_add_table (GArray *table_offsets,GArray *table_data);void acpi_build_tables_init (AcpiBuildTables *tables);void acpi_build_tables_cleanup (AcpiBuildTables *tables,bool mfre);
Signature · 1 line
2.17.2
PATCH v2 3/19 hw: acpi: Export the RSDP build API
In reply to Samuel OrtizThe hardware-reduced API will need to build RSDP as well, so we should export this routine. While doing so, we also slightly change the function prototype. Since no caller needs it, and to make it more consistent with the rest of the AML build API, the function no longer returns its RSDP table.
--- hw/acpi/aml-build.c | 24 ++++++++++++++++++++++++ hw/i386/acpi-build.c | 26 -------------------------- include/hw/acpi/aml-build.h | 3 +++ 3 files changed, 27 insertions(+), 26 deletions(-)
hw/acpi/aml-build.c +24 -0
@@ -1651,6 +1651,30 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id); } +void +build_rsdp (GArray *rsdp_table,BIOSLinker *linker,unsigned rsdt_tbl_offset) +{ +AcpiRsdpDescriptor *rsdp =acpi_data_push (rsdp_table,sizeof *rsdp); +unsigned rsdt_pa_size =sizeof (rsdp->rsdt_physical_address); +unsigned rsdt_pa_offset = + (char *)&rsdp->rsdt_physical_address - rsdp_table->data; + +bios_linker_loader_alloc (linker,ACPI_BUILD_RSDP_FILE , rsdp_table,16 , + true/* fseg memory */ ); + +memcpy (&rsdp->signature,"RSD PTR " ,8 ); +memcpy (rsdp->oem_id,ACPI_BUILD_APPNAME6 ,6 ); +/* Address to be filled by Guest linker */ +bios_linker_loader_add_pointer (linker, +ACPI_BUILD_RSDP_FILE , rsdt_pa_offset, rsdt_pa_size, +ACPI_BUILD_TABLE_FILE , rsdt_tbl_offset); + +/* Checksum to be filled by Guest linker */ +bios_linker_loader_add_checksum (linker,ACPI_BUILD_RSDP_FILE , + (char *)rsdp - rsdp_table->data,sizeof *rsdp, + (char *)&rsdp->checksum - rsdp_table->data); +} +void build_srat_memory (AcpiSratMemoryAffinity *numamem,uint64_t base,uint64_t len,int node,MemoryAffinityFlags flags) {
hw/i386/acpi-build.c +0 -26
@@ -2512,32 +2512,6 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker) "IVRS", table_data->len - iommu_start, 1, NULL, NULL); } -static GArray * -build_rsdp (GArray *rsdp_table,BIOSLinker *linker,unsigned rsdt_tbl_offset) -{ -AcpiRsdpDescriptor *rsdp =acpi_data_push (rsdp_table,sizeof *rsdp); -unsigned rsdt_pa_size =sizeof (rsdp->rsdt_physical_address); -unsigned rsdt_pa_offset = - (char *)&rsdp->rsdt_physical_address - rsdp_table->data; - -bios_linker_loader_alloc (linker,ACPI_BUILD_RSDP_FILE , rsdp_table,16 , - true/* fseg memory */ ); - -memcpy (&rsdp->signature,"RSD PTR " ,8 ); -memcpy (rsdp->oem_id,ACPI_BUILD_APPNAME6 ,6 ); -/* Address to be filled by Guest linker */ -bios_linker_loader_add_pointer (linker, -ACPI_BUILD_RSDP_FILE , rsdt_pa_offset, rsdt_pa_size, -ACPI_BUILD_TABLE_FILE , rsdt_tbl_offset); - -/* Checksum to be filled by Guest linker */ -bios_linker_loader_add_checksum (linker,ACPI_BUILD_RSDP_FILE , - (char *)rsdp - rsdp_table->data,sizeof *rsdp, - (char *)&rsdp->checksum - rsdp_table->data); - -return rsdp_table; -} -static bool acpi_get_mcfg (AcpiMcfgInfo *mcfg) {Object *pci_host;
include/hw/acpi/aml-build.h +3 -0
@@ -390,6 +390,9 @@ void acpi_add_table(GArray *table_offsets, GArray *table_data);void acpi_build_tables_init (AcpiBuildTables *tables);void acpi_build_tables_cleanup (AcpiBuildTables *tables,bool mfre);void +build_rsdp (GArray *table_data, +BIOSLinker *linker,unsigned rsdt_tbl_offset); +void build_rsdt (GArray *table_data,BIOSLinker *linker,GArray *table_offsets,const char *oem_id,const char *oem_table_id);void
Signature · 1 line
2.17.2
PATCH v2 4/19 hw: acpi: Implement XSDT support for RSDP
In reply to Samuel OrtizXSDT is the 64-bit version of the legacy ACPI RSDT (Root System Description Table). RSDT only allow for 32-bit addressses and have thus been deprecated. Since ACPI version 2.0, RSDPs should point at XSDTs and no longer RSDTs, although RSDTs are still supported for backward compatibility.
Since version 2.0, RSDPs should add an extended checksum, a complete table length and a version field to the table.
Here we provide a legacy API (RSDP points at RSDTs) for backward compatibility purpose and a default, XSDT pointing API.
--- hw/acpi/aml-build.c | 41 ++++++++++++++++++++++++++++++++++++- hw/i386/acpi-build.c | 2 +- include/hw/acpi/aml-build.h | 5 ++++- 3 files changed, 45 insertions(+), 3 deletions(-)
hw/acpi/aml-build.c +40 -1
@@ -1651,8 +1651,10 @@ build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets, (void *)xsdt, "XSDT", xsdt_len, 1, oem_id, oem_table_id); } +/* Legacy RSDP pointing at an RSDT. This is deprecated */ void -build_rsdp (GArray *rsdp_table,BIOSLinker *linker,unsigned rsdt_tbl_offset) +build_rsdp_rsdt (GArray *rsdp_table, +BIOSLinker *linker,unsigned rsdt_tbl_offset) {AcpiRsdpDescriptor *rsdp =acpi_data_push (rsdp_table,sizeof *rsdp);unsigned rsdt_pa_size =sizeof (rsdp->rsdt_physical_address);
@@ -1675,6 +1677,43 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset) (char *)&rsdp->checksum - rsdp_table->data); } +/* RSDP pointing at an XSDT */ +void +build_rsdp (GArray *rsdp_table, +BIOSLinker *linker,unsigned xsdt_tbl_offset) +{ +AcpiRsdpDescriptor *rsdp =acpi_data_push (rsdp_table,sizeof *rsdp); +unsigned xsdt_pa_size =sizeof (rsdp->xsdt_physical_address); +unsigned xsdt_pa_offset = + (char *)&rsdp->xsdt_physical_address - rsdp_table->data; +unsigned xsdt_offset = + (char *)&rsdp->length - rsdp_table->data; + +bios_linker_loader_alloc (linker,ACPI_BUILD_RSDP_FILE , rsdp_table,16 , + true/* fseg memory */ ); + +memcpy (&rsdp->signature,"RSD PTR " ,8 ); +memcpy (rsdp->oem_id,ACPI_BUILD_APPNAME6 ,6 ); + rsdp->length =cpu_to_le32 (sizeof (*rsdp)); +/* version 2, we will use the XSDT pointer */ + rsdp->revision =0x02 ; + +/* Address to be filled by Guest linker */ +bios_linker_loader_add_pointer (linker, +ACPI_BUILD_RSDP_FILE , xsdt_pa_offset, xsdt_pa_size, +ACPI_BUILD_TABLE_FILE , xsdt_tbl_offset); + +/* Legacy checksum to be filled by Guest linker */ +bios_linker_loader_add_checksum (linker,ACPI_BUILD_RSDP_FILE , + (char *)rsdp - rsdp_table->data, xsdt_offset, + (char *)&rsdp->checksum - rsdp_table->data); + +/* Extended checksum to be filled by Guest linker */ +bios_linker_loader_add_checksum (linker,ACPI_BUILD_RSDP_FILE , + (char *)rsdp - rsdp_table->data,sizeof *rsdp, + (char *)&rsdp->extended_checksum - rsdp_table->data); +} +void build_srat_memory (AcpiSratMemoryAffinity *numamem,uint64_t base,uint64_t len,int node,MemoryAffinityFlags flags) {
hw/i386/acpi-build.c +1 -1
@@ -2656,7 +2656,7 @@ void acpi_build(AcpiBuildTables *tables, slic_oem.id, slic_oem.table_id);/* RSDP is in FSEG memory, so allocate it separately */ -build_rsdp (tables->rsdp, tables->linker, rsdt); +build_rsdp_rsdt (tables->rsdp, tables->linker, rsdt);/* We'll expose it all to Guest so we want to reduce * chance of size changes.
include/hw/acpi/aml-build.h +4 -1
@@ -390,8 +390,11 @@ void acpi_add_table(GArray *table_offsets, GArray *table_data);void acpi_build_tables_init (AcpiBuildTables *tables);void acpi_build_tables_cleanup (AcpiBuildTables *tables,bool mfre);void +build_rsdp_rsdt (GArray *table_data, +BIOSLinker *linker,unsigned rsdt_tbl_offset); +void build_rsdp (GArray *table_data, -BIOSLinker *linker,unsigned rsdt_tbl_offset); +BIOSLinker *linker,unsigned xsdt_tbl_offset);void build_rsdt (GArray *table_data,BIOSLinker *linker,GArray *table_offsets,const char *oem_id,const char *oem_table_id);
Signature · 1 line
2.17.2
PATCH v2 5/19 hw: arm: Switch to the AML build RSDP building routine
In reply to Samuel OrtizWe make the ARM virt ACPI code use the now shared build_rsdp() API from aml-build.c. By doing so we fix a bug where the ARM implementation was missing adding both the legacy and extended checksums, which was building an invalid RSDP table.
--- hw/arm/virt-acpi-build.c | 31 +------------------------------ 1 file changed, 1 insertion(+), 30 deletions(-)
hw/arm/virt-acpi-build.c +1 -30
@@ -35,6 +35,7 @@#include "target/arm/cpu.h" #include "hw/acpi/acpi-defs.h" #include "hw/acpi/acpi.h" +#include "hw/acpi/aml-build.h" #include "hw/nvram/fw_cfg.h" #include "hw/acpi/bios-linker-loader.h" #include "hw/loader.h"
@@ -366,36 +367,6 @@ static void acpi_dsdt_add_power_button(Aml *scope)aml_append (scope, dev); } -/* RSDP */ -static GArray * -build_rsdp (GArray *rsdp_table,BIOSLinker *linker,unsigned xsdt_tbl_offset) -{ -AcpiRsdpDescriptor *rsdp =acpi_data_push (rsdp_table,sizeof *rsdp); -unsigned xsdt_pa_size =sizeof (rsdp->xsdt_physical_address); -unsigned xsdt_pa_offset = - (char *)&rsdp->xsdt_physical_address - rsdp_table->data; - -bios_linker_loader_alloc (linker,ACPI_BUILD_RSDP_FILE , rsdp_table,16 , - true/* fseg memory */ ); - -memcpy (&rsdp->signature,"RSD PTR " ,sizeof (rsdp->signature)); -memcpy (rsdp->oem_id,ACPI_BUILD_APPNAME6 ,sizeof (rsdp->oem_id)); - rsdp->length =cpu_to_le32 (sizeof (*rsdp)); - rsdp->revision =0x02 ; - -/* Address to be filled by Guest linker */ -bios_linker_loader_add_pointer (linker, -ACPI_BUILD_RSDP_FILE , xsdt_pa_offset, xsdt_pa_size, -ACPI_BUILD_TABLE_FILE , xsdt_tbl_offset); - -/* Checksum to be filled by Guest linker */ -bios_linker_loader_add_checksum (linker,ACPI_BUILD_RSDP_FILE , - (char *)rsdp - rsdp_table->data,sizeof *rsdp, - (char *)&rsdp->checksum - rsdp_table->data); - -return rsdp_table; -} -static void build_iort (GArray *table_data,BIOSLinker *linker,VirtMachineState *vms) {
Signature · 1 line
2.17.2
PATCH v2 6/19 hw: acpi: Generalize AML build routines
In reply to Samuel OrtizFrom: Yang Zhong <[email protected]>
Most of the AML build routines under acpi-build are not even architecture specific. They can be moved to the more generic hw/acpi folder where they could be shared across machine types and architectures.
--- hw/acpi/aml-build.c | 498 ++++++++++++++++++++++++++++++++++ hw/arm/virt-acpi-build.c | 4 +- hw/i386/acpi-build.c | 516 +----------------------------------- include/hw/acpi/aml-build.h | 25 ++ 4 files changed, 528 insertions(+), 515 deletions(-)
hw/acpi/aml-build.c +498 -0
@@ -25,6 +25,10 @@#include "qemu/bswap.h" #include "qemu/bitops.h" #include "sysemu/numa.h" +#include "hw/pci/pci.h" +#include "hw/pci/pci_bus.h" +#include "qemu/range.h" +#include "hw/pci/pci_bridge.h" static GArray *build_alloc_array (void ) {
@@ -1597,6 +1601,500 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)g_array_free (tables->vmgenid, mfre); } +static void crs_range_insert (GPtrArray *ranges,uint64_t base,uint64_t limit) +{ +CrsRangeEntry *entry; + + entry =g_malloc (sizeof (*entry)); + entry->base = base; + entry->limit = limit; + +g_ptr_array_add (ranges, entry); +} + +static void crs_range_free (gpointer data) +{ +CrsRangeEntry *entry = (CrsRangeEntry *)data; +g_free (entry); +} + +void crs_range_set_init (CrsRangeSet *range_set) +{ + range_set->io_ranges =g_ptr_array_new_with_free_func (crs_range_free); + range_set->mem_ranges =g_ptr_array_new_with_free_func (crs_range_free); + range_set->mem_64bit_ranges = +g_ptr_array_new_with_free_func (crs_range_free); +} + +void crs_range_set_free (CrsRangeSet *range_set) +{ +g_ptr_array_free (range_set->io_ranges, true); +g_ptr_array_free (range_set->mem_ranges, true); +g_ptr_array_free (range_set->mem_64bit_ranges, true); +} + +static gint crs_range_compare (gconstpointer a,gconstpointer b) +{ +CrsRangeEntry *entry_a = *(CrsRangeEntry **)a; +CrsRangeEntry *entry_b = *(CrsRangeEntry **)b; + +return (int64_t )entry_a->base - (int64_t )entry_b->base; +} + +/* +* crs_replace_with_free_ranges - given the 'used' ranges within [start - end] +* interval, computes the 'free' ranges from the same interval. +* Example: If the input array is { [a1 - a2],[b1 - b2] }, the function +* will return { [base - a1], [a2 - b1], [b2 - limit] }. +*/ +void crs_replace_with_free_ranges (GPtrArray *ranges, +uint64_t start,uint64_t end) +{ +GPtrArray *free_ranges =g_ptr_array_new (); +uint64_t free_base = start; +int i; + +g_ptr_array_sort (ranges, crs_range_compare); +for (i =0 ; i < ranges->len; i++) { +CrsRangeEntry *used =g_ptr_array_index (ranges, i); + +if (free_base < used->base) { +crs_range_insert (free_ranges, free_base, used->base -1 ); + } + + free_base = used->limit +1 ; + } + +if (free_base < end) { +crs_range_insert (free_ranges, free_base, end); + } + +g_ptr_array_set_size (ranges,0 ); +for (i =0 ; i < free_ranges->len; i++) { +g_ptr_array_add (ranges,g_ptr_array_index (free_ranges, i)); + } + +g_ptr_array_free (free_ranges, true); +} + +/* +* crs_range_merge - merges adjacent ranges in the given array. +* Array elements are deleted and replaced with the merged ranges. +*/ +static void crs_range_merge (GPtrArray *range) +{ +GPtrArray *tmp =g_ptr_array_new_with_free_func (crs_range_free); +CrsRangeEntry *entry; +uint64_t range_base, range_limit; +int i; + +if (!range->len) { +return ; + } + +g_ptr_array_sort (range, crs_range_compare); + + entry =g_ptr_array_index (range,0 ); + range_base = entry->base; + range_limit = entry->limit; +for (i =1 ; i < range->len; i++) { + entry =g_ptr_array_index (range, i); +if (entry->base -1 == range_limit) { + range_limit = entry->limit; + }else { +crs_range_insert (tmp, range_base, range_limit); + range_base = entry->base; + range_limit = entry->limit; + } + } +crs_range_insert (tmp, range_base, range_limit); + +g_ptr_array_set_size (range,0 ); +for (i =0 ; i < tmp->len; i++) { + entry =g_ptr_array_index (tmp, i); +crs_range_insert (range, entry->base, entry->limit); + } +g_ptr_array_free (tmp, true); +} + +Aml *build_crs (PCIHostState *host,CrsRangeSet *range_set) +{ +Aml *crs =aml_resource_template (); +CrsRangeSet temp_range_set; +CrsRangeEntry *entry; +uint8_t max_bus =pci_bus_num (host->bus); +uint8_t type; +int devfn; +int i; + +crs_range_set_init (&temp_range_set); +for (devfn =0 ; devfn <ARRAY_SIZE (host->bus->devices); devfn++) { +uint64_t range_base, range_limit; +PCIDevice *dev = host->bus->devices[devfn]; + +if (!dev) { +continue ; + } + +for (i =0 ; i <PCI_NUM_REGIONS ; i++) { +PCIIORegion *r = &dev->io_regions[i]; + + range_base = r->addr; + range_limit = r->addr + r->size -1 ; + +/* +* Work-around for old bioses +* that do not support multiple root buses +*/ +if (!range_base || range_base > range_limit) { +continue ; + } + +if (r->type &PCI_BASE_ADDRESS_SPACE_IO ) { +crs_range_insert (temp_range_set.io_ranges, + range_base, range_limit); + }else {/* "memory" */ +crs_range_insert (temp_range_set.mem_ranges, + range_base, range_limit); + } + } + + type = dev->config[PCI_HEADER_TYPE ] & ~PCI_HEADER_TYPE_MULTI_FUNCTION ; +if (type ==PCI_HEADER_TYPE_BRIDGE ) { +uint8_t subordinate = dev->config[PCI_SUBORDINATE_BUS ]; +if (subordinate > max_bus) { + max_bus = subordinate; + } + + range_base =pci_bridge_get_base (dev,PCI_BASE_ADDRESS_SPACE_IO ); + range_limit =pci_bridge_get_limit (dev,PCI_BASE_ADDRESS_SPACE_IO ); + +/* +* Work-around for old bioses +* that do not support multiple root buses +*/ +if (range_base && range_base <= range_limit) { +crs_range_insert (temp_range_set.io_ranges, + range_base, range_limit); + } + + range_base = +pci_bridge_get_base (dev,PCI_BASE_ADDRESS_SPACE_MEMORY ); + range_limit = +pci_bridge_get_limit (dev,PCI_BASE_ADDRESS_SPACE_MEMORY ); + +/* +* Work-around for old bioses +* that do not support multiple root buses +*/ +if (range_base && range_base <= range_limit) { +uint64_t length = range_limit - range_base +1 ; +if (range_limit <=UINT32_MAX && length <=UINT32_MAX ) { +crs_range_insert (temp_range_set.mem_ranges, + range_base, range_limit); + }else { +crs_range_insert (temp_range_set.mem_64bit_ranges, + range_base, range_limit); + } + } + + range_base = +pci_bridge_get_base (dev,PCI_BASE_ADDRESS_MEM_PREFETCH ); + range_limit = +pci_bridge_get_limit (dev,PCI_BASE_ADDRESS_MEM_PREFETCH ); + +/* +* Work-around for old bioses +* that do not support multiple root buses +*/ +if (range_base && range_base <= range_limit) { +uint64_t length = range_limit - range_base +1 ; +if (range_limit <=UINT32_MAX && length <=UINT32_MAX ) { +crs_range_insert (temp_range_set.mem_ranges, + range_base, range_limit); + }else { +crs_range_insert (temp_range_set.mem_64bit_ranges, + range_base, range_limit); + } + } + } + } + +crs_range_merge (temp_range_set.io_ranges); +for (i =0 ; i < temp_range_set.io_ranges->len; i++) { + entry =g_ptr_array_index (temp_range_set.io_ranges, i); +aml_append (crs, +aml_word_io (AML_MIN_FIXED ,AML_MAX_FIXED , +AML_POS_DECODE ,AML_ENTIRE_RANGE , +0 , entry->base, entry->limit,0 , + entry->limit - entry->base +1 )); +crs_range_insert (range_set->io_ranges, entry->base, entry->limit); + } + +crs_range_merge (temp_range_set.mem_ranges); +for (i =0 ; i < temp_range_set.mem_ranges->len; i++) { + entry =g_ptr_array_index (temp_range_set.mem_ranges, i); +aml_append (crs, +aml_dword_memory (AML_POS_DECODE ,AML_MIN_FIXED , +AML_MAX_FIXED ,AML_NON_CACHEABLE , +AML_READ_WRITE , +0 , entry->base, entry->limit,0 , + entry->limit - entry->base +1 )); +crs_range_insert (range_set->mem_ranges, entry->base, entry->limit); + } + +crs_range_merge (temp_range_set.mem_64bit_ranges); +for (i =0 ; i < temp_range_set.mem_64bit_ranges->len; i++) { + entry =g_ptr_array_index (temp_range_set.mem_64bit_ranges, i); +aml_append (crs, +aml_qword_memory (AML_POS_DECODE ,AML_MIN_FIXED , +AML_MAX_FIXED ,AML_NON_CACHEABLE , +AML_READ_WRITE , +0 , entry->base, entry->limit,0 , + entry->limit - entry->base +1 )); +crs_range_insert (range_set->mem_64bit_ranges, + entry->base, entry->limit); + } + +crs_range_set_free (&temp_range_set); + +aml_append (crs, +aml_word_bus_number (AML_MIN_FIXED ,AML_MAX_FIXED ,AML_POS_DECODE , +0 , +pci_bus_num (host->bus), + max_bus, +0 , + max_bus -pci_bus_num (host->bus) +1 )); + +return crs; +} + +Aml *build_osc_method (void ) +{ +Aml *if_ctx; +Aml *if_ctx2; +Aml *else_ctx; +Aml *method; +Aml *a_cwd1 =aml_name ("CDW1" ); +Aml *a_ctrl =aml_local (0 ); + + method =aml_method ("_OSC" ,4 ,AML_NOTSERIALIZED ); +aml_append (method,aml_create_dword_field (aml_arg (3 ),aml_int (0 ),"CDW1" )); + + if_ctx =aml_if (aml_equal ( +aml_arg (0 ),aml_touuid ("33DB4D5B-1FF7-401C-9657-7441C03DD766" ))); +aml_append (if_ctx,aml_create_dword_field (aml_arg (3 ),aml_int (4 ),"CDW2" )); +aml_append (if_ctx,aml_create_dword_field (aml_arg (3 ),aml_int (8 ),"CDW3" )); + +aml_append (if_ctx,aml_store (aml_name ("CDW3" ), a_ctrl)); + +/* +* Always allow native PME, AER (no dependencies) +* Allow SHPC (PCI bridges can have SHPC controller) +*/ +aml_append (if_ctx,aml_and (a_ctrl,aml_int (0x1F ), a_ctrl)); + + if_ctx2 =aml_if (aml_lnot (aml_equal (aml_arg (1 ),aml_int (1 )))); +/* Unknown revision */ +aml_append (if_ctx2,aml_or (a_cwd1,aml_int (0x08 ), a_cwd1)); +aml_append (if_ctx, if_ctx2); + + if_ctx2 =aml_if (aml_lnot (aml_equal (aml_name ("CDW3" ), a_ctrl))); +/* Capabilities bits were masked */ +aml_append (if_ctx2,aml_or (a_cwd1,aml_int (0x10 ), a_cwd1)); +aml_append (if_ctx, if_ctx2); + +/* Update DWORD3 in the buffer */ +aml_append (if_ctx,aml_store (a_ctrl,aml_name ("CDW3" ))); +aml_append (method, if_ctx); + + else_ctx =aml_else (); +/* Unrecognized UUID */ +aml_append (else_ctx,aml_or (a_cwd1,aml_int (4 ), a_cwd1)); +aml_append (method, else_ctx); + +aml_append (method,aml_return (aml_arg (3 ))); +return method; +} + +void +build_mcfg (GArray *table_data,BIOSLinker *linker,AcpiMcfgInfo *info) +{ +AcpiTableMcfg *mcfg; +const char *sig; +int len =sizeof (*mcfg) +1 *sizeof (mcfg->allocation[0 ]); + + mcfg =acpi_data_push (table_data, len); + mcfg->allocation[0 ].address =cpu_to_le64 (info->mcfg_base); +/* Only a single allocation so no need to play with segments */ + mcfg->allocation[0 ].pci_segment =cpu_to_le16 (0 ); + mcfg->allocation[0 ].start_bus_number =0 ; + mcfg->allocation[0 ].end_bus_number =PCIE_MMCFG_BUS (info->mcfg_size -1 ); + +/* MCFG is used for ECAM which can be enabled or disabled by guest. +* To avoid table size changes (which create migration issues), +* always create the table even if there are no allocations, +* but set the signature to a reserved value in this case. +* ACPI spec requires OSPMs to ignore such tables. +*/ +if (info->mcfg_base ==PCIE_BASE_ADDR_UNMAPPED ) { +/* Reserved signature: ignored by OSPM */ + sig ="QEMU" ; + }else { + sig ="MCFG" ; + } +build_header (linker, table_data, (void *)mcfg, sig, len,1 ,NULL ,NULL ); +} + +Aml *build_gsi_link_dev (const char *name,uint8_t uid,uint8_t gsi) +{ +Aml *dev; +Aml *crs; +Aml *method; +uint32_t irqs; + + dev =aml_device ("%s" , name); +aml_append (dev,aml_name_decl ("_HID" ,aml_eisaid ("PNP0C0F" ))); +aml_append (dev,aml_name_decl ("_UID" ,aml_int (uid))); + + crs =aml_resource_template (); + irqs = gsi; +aml_append (crs,aml_interrupt (AML_CONSUMER ,AML_LEVEL ,AML_ACTIVE_HIGH , +AML_SHARED , &irqs,1 )); +aml_append (dev,aml_name_decl ("_PRS" , crs)); + +aml_append (dev,aml_name_decl ("_CRS" , crs)); + +/* +* _DIS can be no-op because the interrupt cannot be disabled. +*/ + method =aml_method ("_DIS" ,0 ,AML_NOTSERIALIZED ); +aml_append (dev, method); + + method =aml_method ("_SRS" ,1 ,AML_NOTSERIALIZED ); +aml_append (dev, method); + +return dev; +} + +/** +* build_prt_entry: +* @link_name: link name for PCI route entry +* +* build AML package containing a PCI route entry for @link_name +*/ +static Aml *build_prt_entry (const char *link_name) +{ +Aml *a_zero =aml_int (0 ); +Aml *pkg =aml_package (4 ); +aml_append (pkg, a_zero); +aml_append (pkg, a_zero); +aml_append (pkg,aml_name ("%s" , link_name)); +aml_append (pkg, a_zero); +return pkg; +} + +/* +* initialize_route - Initialize the interrupt routing rule +* through a specific LINK: +* if (lnk_idx == idx) +* route using link 'link_name' +*/ +static Aml *initialize_route (Aml *route,const char *link_name, +Aml *lnk_idx,int idx) +{ +Aml *if_ctx =aml_if (aml_equal (lnk_idx,aml_int (idx))); +Aml *pkg =build_prt_entry (link_name); + +aml_append (if_ctx,aml_store (pkg, route)); + +return if_ctx; +} + +/* +* build_prt - Define interrupt rounting rules +* +* Returns an array of 128 routes, one for each device, +* based on device location. +* The main goal is to equaly distribute the interrupts +* over the 4 existing ACPI links (works only for i440fx). +* The hash function is (slot + pin) & 3 -> "LNK[D|A|B|C]". +* +*/ +Aml *build_prt (bool is_pci0_prt) +{ +Aml *method, *while_ctx, *pin, *res; + + method =aml_method ("_PRT" ,0 ,AML_NOTSERIALIZED ); + res =aml_local (0 ); + pin =aml_local (1 ); +aml_append (method,aml_store (aml_package (128 ), res)); +aml_append (method,aml_store (aml_int (0 ), pin)); + +/* while (pin < 128) */ + while_ctx =aml_while (aml_lless (pin,aml_int (128 ))); + { +Aml *slot =aml_local (2 ); +Aml *lnk_idx =aml_local (3 ); +Aml *route =aml_local (4 ); + +/* slot = pin >> 2 */ +aml_append (while_ctx, +aml_store (aml_shiftright (pin,aml_int (2 ),NULL ), slot)); +/* lnk_idx = (slot + pin) & 3 */ +aml_append (while_ctx, +aml_store (aml_and (aml_add (pin, slot,NULL ),aml_int (3 ),NULL ), + lnk_idx)); + +/* route[2] = "LNK[D|A|B|C]", selection based on pin % 3 */ +aml_append (while_ctx,initialize_route (route,"LNKD" , lnk_idx,0 )); +if (is_pci0_prt) { +Aml *if_device_1, *if_pin_4, *else_pin_4; + +/* device 1 is the power-management device, needs SCI */ + if_device_1 =aml_if (aml_equal (lnk_idx,aml_int (1 ))); + { + if_pin_4 =aml_if (aml_equal (pin,aml_int (4 ))); + { +aml_append (if_pin_4, +aml_store (build_prt_entry ("LNKS" ), route)); + } +aml_append (if_device_1, if_pin_4); + else_pin_4 =aml_else (); + { +aml_append (else_pin_4, +aml_store (build_prt_entry ("LNKA" ), route)); + } +aml_append (if_device_1, else_pin_4); + } +aml_append (while_ctx, if_device_1); + }else { +aml_append (while_ctx,initialize_route (route,"LNKA" , lnk_idx,1 )); + } +aml_append (while_ctx,initialize_route (route,"LNKB" , lnk_idx,2 )); +aml_append (while_ctx,initialize_route (route,"LNKC" , lnk_idx,3 )); + +/* route[0] = 0x[slot]FFFF */ +aml_append (while_ctx, +aml_store (aml_or (aml_shiftleft (slot,aml_int (16 )),aml_int (0xFFFF ), +NULL ), +aml_index (route,aml_int (0 )))); +/* route[1] = pin & 3 */ +aml_append (while_ctx, +aml_store (aml_and (pin,aml_int (3 ),NULL ), +aml_index (route,aml_int (1 )))); +/* res[pin] = route */ +aml_append (while_ctx,aml_store (route,aml_index (res, pin))); +/* pin++ */ +aml_append (while_ctx,aml_increment (pin)); + } +aml_append (method, while_ctx); +/* return res*/ +aml_append (method,aml_return (res)); + +return method; +} +/* Build rsdt table */ void build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
hw/arm/virt-acpi-build.c +2 -2
@@ -546,7 +546,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) }static void -build_mcfg (GArray *table_data,BIOSLinker *linker,VirtMachineState *vms) +virt_build_mcfg (GArray *table_data,BIOSLinker *linker,VirtMachineState *vms) {AcpiTableMcfg *mcfg;const MemMapEntry *memmap = vms->memmap;
@@ -791,7 +791,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)build_gtdt (tables_blob, tables->linker, vms);acpi_add_table (table_offsets, tables_blob); -build_mcfg (tables_blob, tables->linker, vms); +virt_build_mcfg (tables_blob, tables->linker, vms);acpi_add_table (table_offsets, tables_blob);build_spcr (tables_blob, tables->linker, vms);
hw/i386/acpi-build.c +3 -513
564 lines not on this page · raw message
include/hw/acpi/aml-build.h +25 -0
@@ -3,6 +3,7 @@#include "hw/acpi/acpi-defs.h" #include "hw/acpi/bios-linker-loader.h" +#include "hw/pci/pcie_host.h" /* Reserve RAM space for tables: add another order of magnitude. */ #define ACPI_BUILD_TABLE_MAX_SIZE 0x200000
@@ -224,6 +225,21 @@ struct AcpiBuildTables {BIOSLinker *linker; } AcpiBuildTables; +typedef struct AcpiMcfgInfo { +uint64_t mcfg_base; +uint32_t mcfg_size; +}AcpiMcfgInfo ; + +typedef struct CrsRangeEntry { +uint64_t base; +uint64_t limit; +}CrsRangeEntry ; + +typedef struct CrsRangeSet { +GPtrArray *io_ranges; +GPtrArray *mem_ranges; +GPtrArray *mem_64bit_ranges; +}CrsRangeSet ;/** * init_aml_allocator: *
@@ -389,6 +405,15 @@ void acpi_align_size(GArray *blob, unsigned align);void acpi_add_table (GArray *table_offsets,GArray *table_data);void acpi_build_tables_init (AcpiBuildTables *tables);void acpi_build_tables_cleanup (AcpiBuildTables *tables,bool mfre); +Aml *build_osc_method (void ); +void build_mcfg (GArray *table_data,BIOSLinker *linker,AcpiMcfgInfo *info); +Aml *build_gsi_link_dev (const char *name,uint8_t uid,uint8_t gsi); +Aml *build_prt (bool is_pci0_prt); +void crs_range_set_init (CrsRangeSet *range_set); +Aml *build_crs (PCIHostState *host,CrsRangeSet *range_set); +void crs_replace_with_free_ranges (GPtrArray *ranges, +uint64_t start,uint64_t end); +void crs_range_set_free (CrsRangeSet *range_set);void build_rsdp_rsdt (GArray *table_data,BIOSLinker *linker,unsigned rsdt_tbl_offset);
Signature · 1 line
2.17.2
PATCH v2 7/19 hw: acpi: Factorize _OSC AML across architectures
In reply to Samuel OrtizFrom: Yang Zhong <[email protected]>
The _OSC AML table is almost identical between the i386 Q35 and arm virt machine types. We can make it slightly more generic and share it across all PCIe architectures.
--- hw/acpi/aml-build.c | 84 +++++++++++++++++++------------------ hw/arm/virt-acpi-build.c | 45 ++------------------ hw/i386/acpi-build.c | 6 ++- include/hw/acpi/acpi-defs.h | 14 +++++++ include/hw/acpi/aml-build.h | 2 +- 5 files changed, 66 insertions(+), 85 deletions(-)
hw/acpi/aml-build.c +44 -40
@@ -1869,51 +1869,55 @@ Aml *build_crs(PCIHostState *host, CrsRangeSet *range_set)return crs; } -Aml *build_osc_method (void ) +/* +* ctrl_mask is the _OSC capabilities buffer control field mask. +*/ +Aml *build_osc_method (uint32_t ctrl_mask) { -Aml *if_ctx; -Aml *if_ctx2; -Aml *else_ctx; -Aml *method; -Aml *a_cwd1 =aml_name ("CDW1" ); -Aml *a_ctrl =aml_local (0 ); +Aml *ifctx, *ifctx1, *elsectx, *method, *UUID ; method =aml_method ("_OSC" ,4 ,AML_NOTSERIALIZED ); -aml_append (method,aml_create_dword_field (aml_arg (3 ),aml_int (0 ),"CDW1" )); - - if_ctx =aml_if (aml_equal ( -aml_arg (0 ),aml_touuid ("33DB4D5B-1FF7-401C-9657-7441C03DD766" ))); -aml_append (if_ctx,aml_create_dword_field (aml_arg (3 ),aml_int (4 ),"CDW2" )); -aml_append (if_ctx,aml_create_dword_field (aml_arg (3 ),aml_int (8 ),"CDW3" )); - -aml_append (if_ctx,aml_store (aml_name ("CDW3" ), a_ctrl)); - -/* -* Always allow native PME, AER (no dependencies) -* Allow SHPC (PCI bridges can have SHPC controller) +aml_append (method, +aml_create_dword_field (aml_arg (3 ),aml_int (0 ),"CDW1" )); + +/* PCI Firmware Specification 3.0 +* 4.5.1. _OSC Interface for PCI Host Bridge Devices +* The _OSC interface for a PCI/PCI-X/PCI Express hierarchy is +* identified by the Universal Unique IDentifier (UUID) +* 33DB4D5B-1FF7-401C-9657-7441C03DD766 */ -aml_append (if_ctx,aml_and (a_ctrl,aml_int (0x1F ), a_ctrl)); - - if_ctx2 =aml_if (aml_lnot (aml_equal (aml_arg (1 ),aml_int (1 )))); -/* Unknown revision */ -aml_append (if_ctx2,aml_or (a_cwd1,aml_int (0x08 ), a_cwd1)); -aml_append (if_ctx, if_ctx2); - - if_ctx2 =aml_if (aml_lnot (aml_equal (aml_name ("CDW3" ), a_ctrl))); -/* Capabilities bits were masked */ -aml_append (if_ctx2,aml_or (a_cwd1,aml_int (0x10 ), a_cwd1)); -aml_append (if_ctx, if_ctx2); - -/* Update DWORD3 in the buffer */ -aml_append (if_ctx,aml_store (a_ctrl,aml_name ("CDW3" ))); -aml_append (method, if_ctx); - - else_ctx =aml_else (); -/* Unrecognized UUID */ -aml_append (else_ctx,aml_or (a_cwd1,aml_int (4 ), a_cwd1)); -aml_append (method, else_ctx); +UUID =aml_touuid ("33DB4D5B-1FF7-401C-9657-7441C03DD766" ); + ifctx =aml_if (aml_equal (aml_arg (0 ),UUID )); +aml_append (ifctx, +aml_create_dword_field (aml_arg (3 ),aml_int (4 ),"CDW2" )); +aml_append (ifctx, +aml_create_dword_field (aml_arg (3 ),aml_int (8 ),"CDW3" )); +aml_append (ifctx,aml_store (aml_name ("CDW2" ),aml_name ("SUPP" ))); +aml_append (ifctx,aml_store (aml_name ("CDW3" ),aml_name ("CTRL" ))); +aml_append (ifctx,aml_store (aml_and (aml_name ("CTRL" ), +aml_int (ctrl_mask),NULL ), +aml_name ("CTRL" ))); + + ifctx1 =aml_if (aml_lnot (aml_equal (aml_arg (1 ),aml_int (0x1 )))); +aml_append (ifctx1,aml_store (aml_or (aml_name ("CDW1" ),aml_int (0x08 ),NULL ), +aml_name ("CDW1" ))); +aml_append (ifctx, ifctx1); + + ifctx1 =aml_if (aml_lnot (aml_equal (aml_name ("CDW3" ),aml_name ("CTRL" )))); +aml_append (ifctx1,aml_store (aml_or (aml_name ("CDW1" ),aml_int (0x10 ),NULL ), +aml_name ("CDW1" ))); +aml_append (ifctx, ifctx1); + +aml_append (ifctx,aml_store (aml_name ("CTRL" ),aml_name ("CDW3" ))); +aml_append (ifctx,aml_return (aml_arg (3 ))); +aml_append (method, ifctx); + + elsectx =aml_else (); +aml_append (elsectx,aml_store (aml_or (aml_name ("CDW1" ),aml_int (4 ),NULL ), +aml_name ("CDW1" ))); +aml_append (elsectx,aml_return (aml_arg (3 ))); +aml_append (method, elsectx); -aml_append (method,aml_return (aml_arg (3 )));return method; }
hw/arm/virt-acpi-build.c +3 -42
57 lines not on this page · raw message
hw/i386/acpi-build.c +4 -2
@@ -1337,7 +1337,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,aml_append (dev,aml_name_decl ("_CID" ,aml_eisaid ("PNP0A03" )));aml_append (dev,aml_name_decl ("_ADR" ,aml_int (0 )));aml_append (dev,aml_name_decl ("_UID" ,aml_int (1 ))); -aml_append (dev,build_osc_method ()); +aml_append (dev,aml_name_decl ("SUPP" ,aml_int (0 ))); +aml_append (dev,aml_name_decl ("CTRL" ,aml_int (0 ))); +aml_append (dev,build_osc_method (ACPI_OSC_CTRL_PCI_ALL ));aml_append (sb_scope, dev);aml_append (dsdt, sb_scope);
@@ -1402,7 +1404,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,aml_append (dev,aml_name_decl ("_HID" ,aml_eisaid ("PNP0A03" )));aml_append (dev,aml_name_decl ("_BBN" ,aml_int (bus_num)));if (pci_bus_is_express (bus)) { -aml_append (dev,build_osc_method ()); +aml_append (dev,build_osc_method (ACPI_OSC_CTRL_PCI_ALL )); }if (numa_node !=NUMA_NODE_UNASSIGNED ) {
include/hw/acpi/acpi-defs.h +14 -0
@@ -652,4 +652,18 @@ struct AcpiIortRC { } QEMU_PACKED;typedef struct AcpiIortRC AcpiIortRC ; +/* _OSC */ + +#define ACPI_OSC_CTRL_PCIE_NATIVE_HP (1 << 0) +#define ACPI_OSC_CTRL_SHPC_NATIVE_HP (1 << 1) +#define ACPI_OSC_CTRL_PCIE_PM_EVT (1 << 2) +#define ACPI_OSC_CTRL_PCIE_AER (1 << 3) +#define ACPI_OSC_CTRL_PCIE_CAP_CTRL (1 << 4) +#define ACPI_OSC_CTRL_PCI_ALL \ + (ACPI_OSC_CTRL_PCIE_NATIVE_HP | \ + ACPI_OSC_CTRL_SHPC_NATIVE_HP | \ + ACPI_OSC_CTRL_PCIE_PM_EVT | \ + ACPI_OSC_CTRL_PCIE_AER | \ + ACPI_OSC_CTRL_PCIE_CAP_CTRL) +#endif
include/hw/acpi/aml-build.h +1 -1
@@ -405,7 +405,7 @@ void acpi_align_size(GArray *blob, unsigned align);void acpi_add_table (GArray *table_offsets,GArray *table_data);void acpi_build_tables_init (AcpiBuildTables *tables);void acpi_build_tables_cleanup (AcpiBuildTables *tables,bool mfre); -Aml *build_osc_method (void ); +Aml *build_osc_method (uint32_t value);void build_mcfg (GArray *table_data,BIOSLinker *linker,AcpiMcfgInfo *info);Aml *build_gsi_link_dev (const char *name,uint8_t uid,uint8_t gsi);Aml *build_prt (bool is_pci0_prt);
Signature · 1 line
2.17.2
PATCH v2 8/19 hw: i386: Refactor PCI host getter
In reply to Samuel OrtizFrom: Yang Zhong <[email protected]>
Make it more flexible by having it parsing a PCI host paths array instead of open coding those paths deep down into the code logic itself. This will be needed for PCI machine types that are neither emulatiing the ich9 nor the i440fx chipsets.
--- hw/i386/acpi-build.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-)
hw/i386/acpi-build.c +19 -10
@@ -114,6 +114,12 @@ typedef struct AcpiBuildPciBusHotplugState {bool pcihp_bridge_en; } AcpiBuildPciBusHotplugState; +static const char *pci_hosts[] = { +"/machine/i440fx" , +"/machine/q35" , +NULL , +}; +static void init_common_fadt_data (Object *o,AcpiFadtData *data) {uint32_t io =object_property_get_uint (o,ACPI_PM_PROP_PM_IO_BASE ,NULL );
@@ -238,27 +244,30 @@ static void acpi_get_misc_info(AcpiMiscInfo *info)* Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE. * On i386 arch we only have two pci hosts, so we can look only for them. */ -static Object *acpi_get_i386_pci_host (void ) +static Object *acpi_get_pci_host (void ) {PCIHostState *host; +int i =0 ; - host =OBJECT_CHECK (PCIHostState, -object_resolve_path ("/machine/i440fx" ,NULL ), -TYPE_PCI_HOST_BRIDGE ); -if (!host) { +while (pci_hosts[i]) { host =OBJECT_CHECK (PCIHostState, -object_resolve_path ("/machine/q35" ,NULL ), +object_resolve_path (pci_hosts[i],NULL ),TYPE_PCI_HOST_BRIDGE ); +if (host) { +return OBJECT (host); + } + + i++; } -return OBJECT (host); +return NULL ; }static void acpi_get_pci_holes (Range *hole,Range *hole64) {Object *pci_host; - pci_host =acpi_get_i386_pci_host (); + pci_host =acpi_get_pci_host ();g_assert (pci_host); range_set_bounds1(hole,
@@ -1636,7 +1645,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,Object *pci_host;PCIBus *bus =NULL ; - pci_host =acpi_get_i386_pci_host (); + pci_host =acpi_get_pci_host ();if (pci_host) { bus =PCI_HOST_BRIDGE (pci_host)->bus; }
@@ -2009,7 +2018,7 @@ static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)Object *pci_host;QObject *o; - pci_host =acpi_get_i386_pci_host (); + pci_host =acpi_get_pci_host ();g_assert (pci_host); o =object_property_get_qobject (pci_host,PCIE_HOST_MCFG_BASE ,NULL );
Signature · 1 line
2.17.2
PATCH v2 9/19 hw: acpi: Export and generalize the PCI host AML API
In reply to Samuel OrtizFrom: Yang Zhong <[email protected]>
The AML build routines for the PCI host bridge and the corresponding DSDT addition are neither x86 nor PC machine type specific. We can move them to the architecture agnostic hw/acpi folder, and by carrying all the needed information through a new AcpiPciBus structure, we can make them PC machine type independent.
--- hw/acpi/aml-build.c | 208 ++++++++++++++++++++++++++++++++++++ hw/i386/acpi-build.c | 167 ++--------------------------- include/hw/acpi/aml-build.h | 10 ++ 3 files changed, 226 insertions(+), 159 deletions(-)
hw/acpi/aml-build.c +208 -0
@@ -29,6 +29,25 @@#include "hw/pci/pci_bus.h" #include "qemu/range.h" #include "hw/pci/pci_bridge.h" +#include "hw/i386/pc.h" +#include "sysemu/tpm.h" +#include "hw/acpi/tpm.h" + +#define PCI_HOST_BRIDGE_CONFIG_ADDR 0xcf8 +#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR 0x0000 +#define PCI_HOST_BRIDGE_IO_0_MAX_ADDR 0x0cf7 +#define PCI_HOST_BRIDGE_IO_1_MIN_ADDR 0x0d00 +#define PCI_HOST_BRIDGE_IO_1_MAX_ADDR 0xffff +#define PCI_VGA_MEM_BASE_ADDR 0x000a0000 +#define PCI_VGA_MEM_MAX_ADDR 0x000bffff +#define IO_0_LEN 0xcf8 +#define VGA_MEM_LEN 0x20000 + +static const char *pci_hosts[] = { +"/machine/i440fx" , +"/machine/q35" , +NULL , +};static GArray *build_alloc_array (void ) {
@@ -1601,6 +1620,51 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)g_array_free (tables->vmgenid, mfre); } +/* +* Because of the PXB hosts we cannot simply query TYPE_PCI_HOST_BRIDGE. +*/ +Object *acpi_get_pci_host (void ) +{ +PCIHostState *host; +int i =0 ; + +while (pci_hosts[i]) { + host =OBJECT_CHECK (PCIHostState, +object_resolve_path (pci_hosts[i],NULL ), +TYPE_PCI_HOST_BRIDGE ); +if (host) { +return OBJECT (host); + } + + i++; + } + +return NULL ; +} + +void acpi_get_pci_holes (Range *hole,Range *hole64) +{ +Object *pci_host; + + pci_host =acpi_get_pci_host (); +g_assert (pci_host); + +range_set_bounds1 (hole, +object_property_get_uint (pci_host, +PCI_HOST_PROP_PCI_HOLE_START , +NULL ), +object_property_get_uint (pci_host, +PCI_HOST_PROP_PCI_HOLE_END , +NULL )); +range_set_bounds1 (hole64, +object_property_get_uint (pci_host, +PCI_HOST_PROP_PCI_HOLE64_START , +NULL ), +object_property_get_uint (pci_host, +PCI_HOST_PROP_PCI_HOLE64_END , +NULL )); +} +static void crs_range_insert (GPtrArray *ranges,uint64_t base,uint64_t limit) {CrsRangeEntry *entry;
@@ -2099,6 +2163,150 @@ Aml *build_prt(bool is_pci0_prt)return method; } +Aml *build_pci_host_bridge (Aml *table,AcpiPciBus *pci_host) +{ +CrsRangeEntry *entry; +Aml *scope, *dev, *crs; +CrsRangeSet crs_range_set; +Range *pci_hole =NULL ; +Range *pci_hole64 =NULL ; +PCIBus *bus =NULL ; +int root_bus_limit =0xFF ; +int i; + + bus = pci_host->pci_bus; +assert (bus); + pci_hole = pci_host->pci_hole; + pci_hole64 = pci_host->pci_hole64; + +crs_range_set_init (&crs_range_set); + QLIST_FOREACH(bus, &bus->child, sibling) { +uint8_t bus_num =pci_bus_num (bus); +uint8_t numa_node =pci_bus_numa_node (bus); + +/* look only for expander root buses */ +if (!pci_bus_is_root (bus)) { +continue ; + } + +if (bus_num < root_bus_limit) { + root_bus_limit = bus_num -1 ; + } + + scope =aml_scope ("\\_SB" ); + dev =aml_device ("PC%.02X" , bus_num); +aml_append (dev,aml_name_decl ("_UID" ,aml_int (bus_num))); +aml_append (dev,aml_name_decl ("_HID" ,aml_eisaid ("PNP0A03" ))); +aml_append (dev,aml_name_decl ("_BBN" ,aml_int (bus_num))); +if (pci_bus_is_express (bus)) { +aml_append (dev,aml_name_decl ("SUPP" ,aml_int (0 ))); +aml_append (dev,aml_name_decl ("CTRL" ,aml_int (0 ))); +aml_append (dev,build_osc_method (0x1F )); + } +if (numa_node !=NUMA_NODE_UNASSIGNED ) { +aml_append (dev,aml_name_decl ("_PXM" ,aml_int (numa_node))); + } + +aml_append (dev,build_prt (false)); + crs =build_crs (PCI_HOST_BRIDGE (BUS (bus)->parent), &crs_range_set); +aml_append (dev,aml_name_decl ("_CRS" , crs)); +aml_append (scope, dev); +aml_append (table, scope); + } + scope =aml_scope ("\\_SB.PCI0" ); +/* build PCI0._CRS */ + crs =aml_resource_template (); +/* set the pcie bus num */ +aml_append (crs, +aml_word_bus_number (AML_MIN_FIXED ,AML_MAX_FIXED ,AML_POS_DECODE , +0x0000 ,0x0 , root_bus_limit, +0x0000 , root_bus_limit +1 )); +aml_append (crs,aml_io (AML_DECODE16 ,PCI_HOST_BRIDGE_CONFIG_ADDR , +PCI_HOST_BRIDGE_CONFIG_ADDR ,0x01 ,0x08 )); +/* set the io region 0 in pci host bridge */ +aml_append (crs, +aml_word_io (AML_MIN_FIXED ,AML_MAX_FIXED , +AML_POS_DECODE ,AML_ENTIRE_RANGE , +0x0000 ,PCI_HOST_BRIDGE_IO_0_MIN_ADDR , +PCI_HOST_BRIDGE_IO_0_MAX_ADDR ,0x0000 ,IO_0_LEN )); + +/* set the io region 1 in pci host bridge */ +crs_replace_with_free_ranges (crs_range_set.io_ranges, +PCI_HOST_BRIDGE_IO_1_MIN_ADDR , +PCI_HOST_BRIDGE_IO_1_MAX_ADDR ); +for (i =0 ; i < crs_range_set.io_ranges->len; i++) { + entry =g_ptr_array_index (crs_range_set.io_ranges, i); +aml_append (crs, +aml_word_io (AML_MIN_FIXED ,AML_MAX_FIXED , +AML_POS_DECODE ,AML_ENTIRE_RANGE , +0x0000 , entry->base, entry->limit, +0x0000 , entry->limit - entry->base +1 )); + } + +/* set the vga mem region(0) in pci host bridge */ +aml_append (crs, +aml_dword_memory (AML_POS_DECODE ,AML_MIN_FIXED ,AML_MAX_FIXED , +AML_CACHEABLE ,AML_READ_WRITE , +0 ,PCI_VGA_MEM_BASE_ADDR ,PCI_VGA_MEM_MAX_ADDR , +0 ,VGA_MEM_LEN )); + +/* set the mem region 1 in pci host bridge */ +crs_replace_with_free_ranges (crs_range_set.mem_ranges, +range_lob (pci_hole), +range_upb (pci_hole)); +for (i =0 ; i < crs_range_set.mem_ranges->len; i++) { + entry =g_ptr_array_index (crs_range_set.mem_ranges, i); +aml_append (crs, +aml_dword_memory (AML_POS_DECODE ,AML_MIN_FIXED ,AML_MAX_FIXED , +AML_NON_CACHEABLE ,AML_READ_WRITE , +0 , entry->base, entry->limit, +0 , entry->limit - entry->base +1 )); + } + +/* set the mem region 2 in pci host bridge */ +if (!range_is_empty (pci_hole64)) { +crs_replace_with_free_ranges (crs_range_set.mem_64bit_ranges, +range_lob (pci_hole64), +range_upb (pci_hole64)); +for (i =0 ; i < crs_range_set.mem_64bit_ranges->len; i++) { + entry =g_ptr_array_index (crs_range_set.mem_64bit_ranges, i); +aml_append (crs, +aml_qword_memory (AML_POS_DECODE ,AML_MIN_FIXED , +AML_MAX_FIXED , +AML_CACHEABLE ,AML_READ_WRITE , +0 , entry->base, entry->limit, +0 , entry->limit - entry->base +1 )); + } + } + +if (TPM_IS_TIS (tpm_find ())) { +aml_append (crs,aml_memory32_fixed (TPM_TIS_ADDR_BASE , +TPM_TIS_ADDR_SIZE ,AML_READ_WRITE )); + } + +aml_append (scope,aml_name_decl ("_CRS" , crs)); +crs_range_set_free (&crs_range_set); +return scope; +} + +void acpi_dsdt_add_pci_bus (Aml *dsdt,AcpiPciBus *pci_host) +{ +Aml *dev, *pci_scope; + + dev =aml_device ("\\_SB.PCI0" ); +aml_append (dev,aml_name_decl ("_HID" ,aml_eisaid ("PNP0A08" ))); +aml_append (dev,aml_name_decl ("_CID" ,aml_eisaid ("PNP0A03" ))); +aml_append (dev,aml_name_decl ("_ADR" ,aml_int (0 ))); +aml_append (dev,aml_name_decl ("_UID" ,aml_int (1 ))); +aml_append (dev,aml_name_decl ("SUPP" ,aml_int (0 ))); +aml_append (dev,aml_name_decl ("CTRL" ,aml_int (0 ))); +aml_append (dev,build_osc_method (0x1F )); +aml_append (dsdt, dev); + + pci_scope =build_pci_host_bridge (dsdt, pci_host); +aml_append (dsdt, pci_scope); +} +/* Build rsdt table */ void build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
hw/i386/acpi-build.c +8 -159
213 lines not on this page · raw message
include/hw/acpi/aml-build.h +10 -0
@@ -230,6 +230,12 @@ typedef struct AcpiMcfgInfo {uint32_t mcfg_size; } AcpiMcfgInfo; +typedef struct AcpiPciBus { +PCIBus *pci_bus; +Range *pci_hole; +Range *pci_hole64; +}AcpiPciBus ; + typedef struct CrsRangeEntry { uint64_t base; uint64_t limit;
@@ -401,6 +407,8 @@ build_header(BIOSLinker *linker, GArray *table_data, const char *oem_id, const char *oem_table_id);void *acpi_data_push (GArray *table_data,unsigned size);unsigned acpi_data_len (GArray *table); +Object *acpi_get_pci_host (void ); +void acpi_get_pci_holes (Range *hole,Range *hole64);void acpi_align_size (GArray *blob,unsigned align);void acpi_add_table (GArray *table_offsets,GArray *table_data);void acpi_build_tables_init (AcpiBuildTables *tables);
@@ -409,6 +417,8 @@ Aml *build_osc_method(uint32_t value);void build_mcfg (GArray *table_data,BIOSLinker *linker,AcpiMcfgInfo *info);Aml *build_gsi_link_dev (const char *name,uint8_t uid,uint8_t gsi);Aml *build_prt (bool is_pci0_prt); +void acpi_dsdt_add_pci_bus (Aml *dsdt,AcpiPciBus *pci_host); +Aml *build_pci_host_bridge (Aml *table,AcpiPciBus *pci_host);void crs_range_set_init (CrsRangeSet *range_set);Aml *build_crs (PCIHostState *host,CrsRangeSet *range_set); void crs_replace_with_free_ranges(GPtrArray *ranges,
Signature · 1 line
2.17.2
PATCH v2 10/19 hw: acpi: Export the MCFG getter
In reply to Samuel OrtizFrom: Yang Zhong <[email protected]>
The ACPI MCFG getter is not x86 specific and could be called from anywhere within generic ACPI API, so let's export it.
--- hw/acpi/aml-build.c | 24 ++++++++++++++++++++++++ hw/i386/acpi-build.c | 22 ---------------------- include/hw/acpi/aml-build.h | 1 + 3 files changed, 25 insertions(+), 22 deletions(-)
hw/acpi/aml-build.c +24 -0
@@ -32,6 +32,8 @@#include "hw/i386/pc.h" #include "sysemu/tpm.h" #include "hw/acpi/tpm.h" +#include "qom/qom-qobject.h" +#include "qapi/qmp/qnum.h" #define PCI_HOST_BRIDGE_CONFIG_ADDR 0xcf8#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR 0x0000
@@ -1665,6 +1667,28 @@ void acpi_get_pci_holes(Range *hole, Range *hole64) NULL)); } +bool acpi_get_mcfg (AcpiMcfgInfo *mcfg) +{ +Object *pci_host; +QObject *o; + + pci_host =acpi_get_pci_host (); +g_assert (pci_host); + + o =object_property_get_qobject (pci_host,PCIE_HOST_MCFG_BASE ,NULL ); +if (!o) { +return false; + } + mcfg->mcfg_base =qnum_get_uint (qobject_to (QNum, o)); +qobject_unref (o); + + o =object_property_get_qobject (pci_host,PCIE_HOST_MCFG_SIZE ,NULL ); +assert (o); + mcfg->mcfg_size =qnum_get_uint (qobject_to (QNum, o)); +qobject_unref (o); +return true; +} +static void crs_range_insert (GPtrArray *ranges,uint64_t base,uint64_t limit) {CrsRangeEntry *entry;
hw/i386/acpi-build.c +0 -22
@@ -1857,28 +1857,6 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker) "IVRS", table_data->len - iommu_start, 1, NULL, NULL); } -static bool acpi_get_mcfg (AcpiMcfgInfo *mcfg) -{ -Object *pci_host; -QObject *o; - - pci_host =acpi_get_pci_host (); -g_assert (pci_host); - - o =object_property_get_qobject (pci_host,PCIE_HOST_MCFG_BASE ,NULL ); -if (!o) { -return false; - } - mcfg->mcfg_base =qnum_get_uint (qobject_to (QNum, o)); -qobject_unref (o); - - o =object_property_get_qobject (pci_host,PCIE_HOST_MCFG_SIZE ,NULL ); -assert (o); - mcfg->mcfg_size =qnum_get_uint (qobject_to (QNum, o)); -qobject_unref (o); -return true; -} -static void acpi_build (AcpiBuildTables *tables,MachineState *machine,AcpiConfiguration *conf)
include/hw/acpi/aml-build.h +1 -0
@@ -409,6 +409,7 @@ void *acpi_data_push(GArray *table_data, unsigned size);unsigned acpi_data_len (GArray *table);Object *acpi_get_pci_host (void );void acpi_get_pci_holes (Range *hole,Range *hole64); +bool acpi_get_mcfg (AcpiMcfgInfo *mcfg);void acpi_align_size (GArray *blob,unsigned align);void acpi_add_table (GArray *table_offsets,GArray *table_data);void acpi_build_tables_init (AcpiBuildTables *tables);
Signature · 1 line
2.17.2
PATCH v2 11/19 hw: acpi: Do not create hotplug method when handler is not defined
In reply to Samuel OrtizCPU and memory ACPI hotplug are not necessarily handled through SCI events. For example, with Hardware-reduced ACPI, the GED device will manage ACPI hotplug entirely.
As a consequence, we make the CPU and memory specific events AML generation optional. The code will only be added when the method name is not NULL.
--- hw/acpi/cpu.c | 8 +++++--- hw/acpi/memory_hotplug.c | 11 +++++++---- 2 files changed, 12 insertions(+), 7 deletions(-)
hw/acpi/cpu.c +5 -3
@@ -569,9 +569,11 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,aml_append (sb_scope, cpus_dev);aml_append (table, sb_scope); - method =aml_method (event_handler_method,0 ,AML_NOTSERIALIZED ); -aml_append (method,aml_call0 ("\\_SB.CPUS." CPU_SCAN_METHOD )); -aml_append (table, method); +if (event_handler_method) { + method =aml_method (event_handler_method,0 ,AML_NOTSERIALIZED ); +aml_append (method,aml_call0 ("\\_SB.CPUS." CPU_SCAN_METHOD )); +aml_append (table, method); + }g_free (cphp_res_path); }
hw/acpi/memory_hotplug.c +7 -4
@@ -715,10 +715,13 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, }aml_append (table, dev_container); - method =aml_method (event_handler_method,0 ,AML_NOTSERIALIZED ); -aml_append (method, -aml_call0 (MEMORY_DEVICES_CONTAINER "." MEMORY_SLOT_SCAN_METHOD )); -aml_append (table, method); +if (event_handler_method) { + method =aml_method (event_handler_method,0 ,AML_NOTSERIALIZED ); +aml_append (method, +aml_call0 (MEMORY_DEVICES_CONTAINER "." +MEMORY_SLOT_SCAN_METHOD )); +aml_append (table, method); + }g_free (mhp_res_path); }
Signature · 1 line
2.17.2
PATCH v2 12/19 hw: i386: Make the hotpluggable memory size property more generic
In reply to Samuel OrtizThis property is currently defined under i386/pc while it only describes a region size that's eventually fetched from the AML ACPI code.
We can make it more generic and shareable across machine types by moving it to memory-device.h instead.
--- hw/i386/acpi-build.c | 2 +- hw/i386/pc.c | 3 ++- include/hw/i386/pc.h | 1 - include/hw/mem/memory-device.h | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-)
hw/i386/acpi-build.c +1 -1
@@ -1630,7 +1630,7 @@ build_srat(GArray *table_data, BIOSLinker *linker,MachineClass *mc =MACHINE_GET_CLASS (machine);const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids (machine);ram_addr_t hotplugabble_address_space_size = -object_property_get_int (OBJECT (machine),PC_MACHINE_DEVMEM_REGION_SIZE , +object_property_get_int (OBJECT (machine),MEMORY_DEVICE_REGION_SIZE ,NULL ); srat_start = table_data->len;
hw/i386/pc.c +2 -1
@@ -67,6 +67,7 @@#include "hw/boards.h" #include "acpi-build.h" #include "hw/mem/pc-dimm.h" +#include "hw/mem/memory-device.h" #include "qapi/error.h" #include "qapi/qapi-visit-common.h" #include "qapi/visitor.h"
@@ -2442,7 +2443,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) nc->nmi_monitor_handler = x86_nmi; mc->default_cpu_type =TARGET_DEFAULT_CPU_TYPE ; -object_class_property_add (oc,PC_MACHINE_DEVMEM_REGION_SIZE ,"int" , +object_class_property_add (oc,MEMORY_DEVICE_REGION_SIZE ,"int" , pc_machine_get_device_memory_region_size,NULL ,NULL ,NULL , &error_abort);
include/hw/i386/pc.h +0 -1
@@ -62,7 +62,6 @@ struct PCMachineState { };#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device" -#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size"#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"#define PC_MACHINE_VMPORT "vmport"#define PC_MACHINE_SMM "smm"
include/hw/mem/memory-device.h +2 -0
@@ -97,6 +97,8 @@ typedef struct MemoryDeviceClass { MemoryDeviceInfo *info); } MemoryDeviceClass; +#define MEMORY_DEVICE_REGION_SIZE "memory-device-region-size" +MemoryDeviceInfoList *qmp_memory_device_list (void );uint64_t get_plugged_memory_size (void ); void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
Signature · 1 line
2.17.2
PATCH v2 13/19 hw: acpi: Export the SRAT AML build API
In reply to Samuel OrtizFrom: Yang Zhong <[email protected]>
The SRAT ACPI table is not x86 specific and will be needed for the Hardware-reduced ACPI implementation. So we should export it through the architecture independent hw/acpi folder.
Also, now that the generic build_srat() API is exported, we have to rename the ARM static one in order to avoid build time conflicts.
--- hw/acpi/aml-build.c | 130 ++++++++++++++++++++++++++++++++++++ hw/arm/virt-acpi-build.c | 4 +- hw/i386/acpi-build.c | 129 ----------------------------------- include/hw/acpi/aml-build.h | 3 + 4 files changed, 135 insertions(+), 131 deletions(-)
hw/acpi/aml-build.c +130 -0
@@ -22,6 +22,7 @@#include "qemu/osdep.h" #include <glib/gprintf.h> #include "hw/acpi/aml-build.h" +#include "hw/mem/memory-device.h" #include "qemu/bswap.h" #include "qemu/bitops.h" #include "sysemu/numa.h"
@@ -2459,6 +2460,135 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base, numamem->range_length =cpu_to_le64 (len); } +#define HOLE_640K_START (640 * KiB) +#define HOLE_640K_END (1 * MiB) + +void +build_srat (GArray *table_data,BIOSLinker *linker, +MachineState *machine,AcpiConfiguration *conf) +{ +AcpiSystemResourceAffinityTable *srat; +AcpiSratMemoryAffinity *numamem; + +int i; +int srat_start, numa_start, slots; +uint64_t mem_len, mem_base, next_base; +MachineClass *mc =MACHINE_GET_CLASS (machine); +const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids (machine); +ram_addr_t hotplugabble_address_space_size = +object_property_get_int (OBJECT (machine),MEMORY_DEVICE_REGION_SIZE , +NULL ); + + srat_start = table_data->len; + + srat =acpi_data_push (table_data,sizeof *srat); + srat->reserved1 =cpu_to_le32 (1 ); + +for (i =0 ; i < apic_ids->len; i++) { +int node_id = apic_ids->cpus[i].props.node_id; +uint32_t apic_id = apic_ids->cpus[i].arch_id; + +if (apic_id <255 ) { +AcpiSratProcessorAffinity *core; + + core =acpi_data_push (table_data,sizeof *core); + core->type =ACPI_SRAT_PROCESSOR_APIC ; + core->length =sizeof (*core); + core->local_apic_id = apic_id; + core->proximity_lo = node_id; +memset (core->proximity_hi,0 ,3 ); + core->local_sapic_eid =0 ; + core->flags =cpu_to_le32 (1 ); + }else { +AcpiSratProcessorX2ApicAffinity *core; + + core =acpi_data_push (table_data,sizeof *core); + core->type = ACPI_SRAT_PROCESSOR_x2APIC; + core->length =sizeof (*core); + core->x2apic_id =cpu_to_le32 (apic_id); + core->proximity_domain =cpu_to_le32 (node_id); + core->flags =cpu_to_le32 (1 ); + } + } + + +/* the memory map is a bit tricky, it contains at least one hole +* from 640k-1M and possibly another one from 3.5G-4G. +*/ + next_base =0 ; + numa_start = table_data->len; + +for (i =1 ; i < conf->numa_nodes +1 ; ++i) { + mem_base = next_base; + mem_len = conf->node_mem[i -1 ]; + next_base = mem_base + mem_len; + +/* Cut out the 640K hole */ +if (mem_base <=HOLE_640K_START && + next_base >HOLE_640K_START ) { + mem_len -= next_base -HOLE_640K_START ; +if (mem_len >0 ) { + numamem =acpi_data_push (table_data,sizeof *numamem); +build_srat_memory (numamem, mem_base, mem_len, i -1 , +MEM_AFFINITY_ENABLED ); + } + +/* Check for the rare case: 640K < RAM < 1M */ +if (next_base <=HOLE_640K_END ) { + next_base =HOLE_640K_END ; +continue ; + } + mem_base =HOLE_640K_END ; + mem_len = next_base -HOLE_640K_END ; + } + +/* Cut out the ACPI_PCI hole */ +if (mem_base <= conf->below_4g_mem_size && + next_base > conf->below_4g_mem_size) { + mem_len -= next_base - conf->below_4g_mem_size; +if (mem_len >0 ) { + numamem =acpi_data_push (table_data,sizeof *numamem); +build_srat_memory (numamem, mem_base, mem_len, i -1 , +MEM_AFFINITY_ENABLED ); + } + mem_base =1ULL <<32 ; + mem_len = next_base - conf->below_4g_mem_size; + next_base = mem_base + mem_len; + } + +if (mem_len >0 ) { + numamem =acpi_data_push (table_data,sizeof *numamem); +build_srat_memory (numamem, mem_base, mem_len, i -1 , +MEM_AFFINITY_ENABLED ); + } + } + slots = (table_data->len - numa_start) /sizeof *numamem; +for (; slots < conf->numa_nodes +2 ; slots++) { + numamem =acpi_data_push (table_data,sizeof *numamem); +build_srat_memory (numamem,0 ,0 ,0 ,MEM_AFFINITY_NOFLAGS ); + } + +/* +* Entry is required for Windows to enable memory hotplug in OS +* and for Linux to enable SWIOTLB when booted with less than +* 4G of RAM. Windows works better if the entry sets proximity +* to the highest NUMA node in the machine. +* Memory devices may override proximity set by this entry, +* providing _PXM method if necessary. +*/ +if (hotplugabble_address_space_size) { + numamem =acpi_data_push (table_data,sizeof *numamem); +build_srat_memory (numamem, machine->device_memory->base, + hotplugabble_address_space_size, conf->numa_nodes -1 , +MEM_AFFINITY_HOTPLUGGABLE |MEM_AFFINITY_ENABLED ); + } + +build_header (linker, table_data, + (void *)(table_data->data + srat_start), +"SRAT" , + table_data->len - srat_start,1 ,NULL ,NULL ); +} +/* * ACPI spec 5.2.17 System Locality Distance Information Table * (Revision 2.0 or later)
hw/arm/virt-acpi-build.c +2 -2
@@ -469,7 +469,7 @@ build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) }static void -build_srat (GArray *table_data,BIOSLinker *linker,VirtMachineState *vms) +virt_build_srat (GArray *table_data,BIOSLinker *linker,VirtMachineState *vms) {AcpiSystemResourceAffinityTable *srat;AcpiSratProcessorGiccAffinity *core;
@@ -759,7 +759,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)if (nb_numa_nodes >0 ) {acpi_add_table (table_offsets, tables_blob); -build_srat (tables_blob, tables->linker, vms); +virt_build_srat (tables_blob, tables->linker, vms);if (have_numa_distance) {acpi_add_table (table_offsets, tables_blob);build_slit (tables_blob, tables->linker);
hw/i386/acpi-build.c +0 -129
135 lines not on this page · raw message
include/hw/acpi/aml-build.h +3 -0
@@ -1,6 +1,7 @@#ifndef HW_ACPI_AML_BUILD_H #define HW_ACPI_AML_BUILD_H +#include "hw/acpi/acpi.h" #include "hw/acpi/acpi-defs.h" #include "hw/acpi/bios-linker-loader.h" #include "hw/pci/pcie_host.h"
@@ -438,6 +439,8 @@ voidbuild_xsdt (GArray *table_data, BIOSLinker *linker, GArray *table_offsets, const char *oem_id, const char *oem_table_id); +void build_srat (GArray *table_data,BIOSLinker *linker, +MachineState *machine,AcpiConfiguration *conf); int build_append_named_dword(GArray *array, const char *name_format, ...) GCC_FMT_ATTR(2, 3);
Signature · 1 line
2.17.2
PATCH v2 14/19 hw: acpi: Fix memory hotplug AML generation error
In reply to Samuel OrtizFrom: Yang Zhong <[email protected]>
When using the generated memory hotplug AML, the iasl compiler would give the following error:
dsdt.dsl 266: Return (MOST (_UID, Arg0, Arg1, Arg2)) Error 6080 - Called method returns no value ^
--- hw/acpi/memory_hotplug.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
hw/acpi/memory_hotplug.c +5 -5
@@ -686,15 +686,15 @@ void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem, method =aml_method ("_OST" ,3 ,AML_NOTSERIALIZED ); s =MEMORY_SLOT_OST_METHOD ; -aml_append (method,aml_return (aml_call4 ( - s,aml_name ("_UID" ),aml_arg (0 ),aml_arg (1 ),aml_arg (2 ) - ))); +aml_append (method, +aml_call4 (s,aml_name ("_UID" ),aml_arg (0 ), +aml_arg (1 ),aml_arg (2 )));aml_append (dev, method); method =aml_method ("_EJ0" ,1 ,AML_NOTSERIALIZED ); s =MEMORY_SLOT_EJECT_METHOD ; -aml_append (method,aml_return (aml_call2 ( - s,aml_name ("_UID" ),aml_arg (0 )))); +aml_append (method, +aml_call2 (s,aml_name ("_UID" ),aml_arg (0 )));aml_append (dev, method);aml_append (dev_container, dev);
Signature · 1 line
2.17.2
PATCH v2 15/19 hw: acpi: Export the PCI hotplug API
In reply to Samuel OrtizFrom: Sebastien Boeuf <[email protected]>
The ACPI hotplug support for PCI devices APIs are not x86 or even machine type specific. In order for future machine types to be able to re-use that code, we export it through the architecture agnostic hw/acpi folder.
--- hw/acpi/aml-build.c | 194 ++++++++++++++++++++++++++++++++++++ hw/i386/acpi-build.c | 192 +---------------------------------- include/hw/acpi/aml-build.h | 3 + 3 files changed, 199 insertions(+), 190 deletions(-)
hw/acpi/aml-build.c +194 -0
@@ -35,6 +35,7 @@#include "hw/acpi/tpm.h" #include "qom/qom-qobject.h" #include "qapi/qmp/qnum.h" +#include "hw/acpi/pcihp.h" #define PCI_HOST_BRIDGE_CONFIG_ADDR 0xcf8#define PCI_HOST_BRIDGE_IO_0_MIN_ADDR 0x0000
@@ -2314,6 +2315,199 @@ Aml *build_pci_host_bridge(Aml *table, AcpiPciBus *pci_host)return scope; } +void build_acpi_pci_hotplug (Aml *scope) +{ +Aml *field; +Aml *method; + +aml_append (scope, +aml_operation_region ("PCST" ,AML_SYSTEM_IO ,aml_int (0xae00 ),0x08 )); + field =aml_field ("PCST" ,AML_DWORD_ACC ,AML_NOLOCK ,AML_WRITE_AS_ZEROS ); +aml_append (field,aml_named_field ("PCIU" ,32 )); +aml_append (field,aml_named_field ("PCID" ,32 )); +aml_append (scope, field); + +aml_append (scope, +aml_operation_region ("SEJ" ,AML_SYSTEM_IO ,aml_int (0xae08 ),0x04 )); + field =aml_field ("SEJ" ,AML_DWORD_ACC ,AML_NOLOCK ,AML_WRITE_AS_ZEROS ); +aml_append (field,aml_named_field ("B0EJ" ,32 )); +aml_append (scope, field); + +aml_append (scope, +aml_operation_region ("BNMR" ,AML_SYSTEM_IO ,aml_int (0xae10 ),0x04 )); + field =aml_field ("BNMR" ,AML_DWORD_ACC ,AML_NOLOCK ,AML_WRITE_AS_ZEROS ); +aml_append (field,aml_named_field ("BNUM" ,32 )); +aml_append (scope, field); + +aml_append (scope,aml_mutex ("BLCK" ,0 )); + + method =aml_method ("PCEJ" ,2 ,AML_NOTSERIALIZED ); +aml_append (method,aml_acquire (aml_name ("BLCK" ),0xFFFF )); +aml_append (method,aml_store (aml_arg (0 ),aml_name ("BNUM" ))); +aml_append (method, +aml_store (aml_shiftleft (aml_int (1 ),aml_arg (1 )),aml_name ("B0EJ" ))); +aml_append (method,aml_release (aml_name ("BLCK" ))); +aml_append (method,aml_return (aml_int (0 ))); +aml_append (scope, method); +} + +static void build_append_pcihp_notify_entry (Aml *method,int slot) +{ +Aml *if_ctx; +int32_t devfn =PCI_DEVFN (slot,0 ); + + if_ctx =aml_if (aml_and (aml_arg (0 ),aml_int (0x1U << slot),NULL )); +aml_append (if_ctx,aml_notify (aml_name ("S%.02X" , devfn),aml_arg (1 ))); +aml_append (method, if_ctx); +} + +void build_append_pci_bus_devices (Aml *parent_scope,PCIBus *bus, +bool pcihp_bridge_en) +{ +Aml *dev, *notify_method =NULL , *method; +QObject *bsel; +PCIBus *sec; +int i; + + bsel =object_property_get_qobject (OBJECT (bus),ACPI_PCIHP_PROP_BSEL ,NULL ); +if (bsel) { +uint64_t bsel_val =qnum_get_uint (qobject_to (QNum, bsel)); + +aml_append (parent_scope,aml_name_decl ("BSEL" ,aml_int (bsel_val))); + notify_method =aml_method ("DVNT" ,2 ,AML_NOTSERIALIZED ); + } + +for (i =0 ; i <ARRAY_SIZE (bus->devices); i +=PCI_FUNC_MAX ) { +DeviceClass *dc; +PCIDeviceClass *pc; +PCIDevice *pdev = bus->devices[i]; +int slot =PCI_SLOT (i); +bool hotplug_enabled_dev; +bool bridge_in_acpi; + +if (!pdev) { +if (bsel) {/* add hotplug slots for non present devices */ + dev =aml_device ("S%.02X" ,PCI_DEVFN (slot,0 )); +aml_append (dev,aml_name_decl ("_SUN" ,aml_int (slot))); +aml_append (dev,aml_name_decl ("_ADR" ,aml_int (slot <<16 ))); + method =aml_method ("_EJ0" ,1 ,AML_NOTSERIALIZED ); +aml_append (method, +aml_call2 ("PCEJ" ,aml_name ("BSEL" ),aml_name ("_SUN" )) + ); +aml_append (dev, method); +aml_append (parent_scope, dev); + +build_append_pcihp_notify_entry (notify_method, slot); + } +continue ; + } + + pc =PCI_DEVICE_GET_CLASS (pdev); + dc =DEVICE_GET_CLASS (pdev); + +/* When hotplug for bridges is enabled, bridges are +* described in ACPI separately (see build_pci_bus_end). +* In this case they aren't themselves hot-pluggable. +* Hotplugged bridges *are* hot-pluggable. +*/ + bridge_in_acpi = pc->is_bridge && pcihp_bridge_en && + !DEVICE (pdev)->hotplugged; + + hotplug_enabled_dev = bsel && dc->hotpluggable && !bridge_in_acpi; + +if (pc->class_id ==PCI_CLASS_BRIDGE_ISA ) { +continue ; + } + +/* start to compose PCI slot descriptor */ + dev =aml_device ("S%.02X" ,PCI_DEVFN (slot,0 )); +aml_append (dev,aml_name_decl ("_ADR" ,aml_int (slot <<16 ))); + +if (pc->class_id ==PCI_CLASS_DISPLAY_VGA ) { +/* add VGA specific AML methods */ +int s3d; + +if (object_dynamic_cast (OBJECT (pdev),"qxl-vga" )) { + s3d =3 ; + }else { + s3d =0 ; + } + + method =aml_method ("_S1D" ,0 ,AML_NOTSERIALIZED ); +aml_append (method,aml_return (aml_int (0 ))); +aml_append (dev, method); + + method =aml_method ("_S2D" ,0 ,AML_NOTSERIALIZED ); +aml_append (method,aml_return (aml_int (0 ))); +aml_append (dev, method); + + method =aml_method ("_S3D" ,0 ,AML_NOTSERIALIZED ); +aml_append (method,aml_return (aml_int (s3d))); +aml_append (dev, method); + }else if (hotplug_enabled_dev) { +/* add _SUN/_EJ0 to make slot hotpluggable */ +aml_append (dev,aml_name_decl ("_SUN" ,aml_int (slot))); + + method =aml_method ("_EJ0" ,1 ,AML_NOTSERIALIZED ); +aml_append (method, +aml_call2 ("PCEJ" ,aml_name ("BSEL" ),aml_name ("_SUN" )) + ); +aml_append (dev, method); + +if (bsel) { +build_append_pcihp_notify_entry (notify_method, slot); + } + }else if (bridge_in_acpi) { +/* +* device is coldplugged bridge, +* add child device descriptions into its scope +*/ +PCIBus *sec_bus =pci_bridge_get_sec_bus (PCI_BRIDGE (pdev)); + +build_append_pci_bus_devices (dev, sec_bus, pcihp_bridge_en); + } +/* slot descriptor has been composed, add it into parent context */ +aml_append (parent_scope, dev); + } + +if (bsel) { +aml_append (parent_scope, notify_method); + } + +/* Append PCNT method to notify about events on local and child buses. +* Add unconditionally for root since DSDT expects it. +*/ + method =aml_method ("PCNT" ,0 ,AML_NOTSERIALIZED ); + +/* If bus supports hotplug select it and notify about local events */ +if (bsel) { +uint64_t bsel_val =qnum_get_uint (qobject_to (QNum, bsel)); + +aml_append (method,aml_store (aml_int (bsel_val),aml_name ("BNUM" ))); +aml_append (method, +aml_call2 ("DVNT" ,aml_name ("PCIU" ),aml_int (1 )/* Device Check */ ) + ); +aml_append (method, +aml_call2 ("DVNT" ,aml_name ("PCID" ),aml_int (3 )/* Eject Request */ ) + ); + } + +/* Notify about child bus events in any case */ +if (pcihp_bridge_en) { + QLIST_FOREACH(sec, &bus->child, sibling) { +int32_t devfn = sec->parent_dev->devfn; + +if (pci_bus_is_root (sec) ||pci_bus_is_express (sec)) { +continue ; + } + +aml_append (method,aml_name ("^S%.02X.PCNT" , devfn)); + } + } +aml_append (parent_scope, method); +qobject_unref (bsel); +} +void acpi_dsdt_add_pci_bus (Aml *dsdt,AcpiPciBus *pci_host) {Aml *dev, *pci_scope;
hw/i386/acpi-build.c +2 -190
206 lines not on this page · raw message
include/hw/acpi/aml-build.h +3 -0
@@ -419,6 +419,9 @@ Aml *build_osc_method(uint32_t value);void build_mcfg (GArray *table_data,BIOSLinker *linker,AcpiMcfgInfo *info);Aml *build_gsi_link_dev (const char *name,uint8_t uid,uint8_t gsi);Aml *build_prt (bool is_pci0_prt); +void build_acpi_pci_hotplug (Aml *scope); +void build_append_pci_bus_devices (Aml *parent_scope,PCIBus *bus, +bool pcihp_bridge_en);void acpi_dsdt_add_pci_bus (Aml *dsdt,AcpiPciBus *pci_host);Aml *build_pci_host_bridge (Aml *table,AcpiPciBus *pci_host);void crs_range_set_init (CrsRangeSet *range_set);
Signature · 1 line
2.17.2
PATCH v2 16/19 hw: acpi: Retrieve the PCI bus from AcpiPciHpState
In reply to Samuel OrtizFrom: Sebastien Boeuf <[email protected]>
Instead of using the machine type specific method find_i440fx() to retrieve the PCI bus, this commit aims to rely on the fact that the PCI bus is known by the structure AcpiPciHpState.
When the structure is initialized through acpi_pcihp_init() call, it saves the PCI bus, which means there is no need to invoke a special function later on.
Based on the fact that find_i440fx() was only used there, this patch also removes the function find_i440fx() itself from the entire codebase.
--- hw/acpi/pcihp.c | 10 ++++------ hw/pci-host/piix.c | 8 -------- include/hw/i386/pc.h | 1 - stubs/Makefile.objs | 1 - stubs/pci-host-piix.c | 6 ------ 5 files changed, 4 insertions(+), 22 deletions(-) delete mode 100644 stubs/pci-host-piix.c
hw/acpi/pcihp.c +4 -6
@@ -93,10 +93,9 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque)return bsel_alloc; } -static void acpi_set_pci_info (void ) +static void acpi_set_pci_info (AcpiPciHpState *s) {static bool bsel_is_set; -PCIBus *bus;unsigned bsel_alloc =ACPI_PCIHP_BSEL_DEFAULT ;if (bsel_is_set) {
@@ -104,10 +103,9 @@ static void acpi_set_pci_info(void) } bsel_is_set = true; - bus =find_i440fx ();/* TODO: Q35 support */ -if (bus) { +if (s->root) {/* Scan all PCI buses. Set property to enable acpi based hotplug. */ -pci_for_each_bus_depth_first (bus, acpi_set_bsel,NULL , &bsel_alloc); +pci_for_each_bus_depth_first (s->root, acpi_set_bsel,NULL , &bsel_alloc); } }
@@ -213,7 +211,7 @@ static void acpi_pcihp_update(AcpiPciHpState *s)void acpi_pcihp_reset (AcpiPciHpState *s) { -acpi_set_pci_info (); +acpi_set_pci_info (s);acpi_pcihp_update (s); }
hw/pci-host/piix.c +0 -8
@@ -445,14 +445,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type,return b; } -PCIBus *find_i440fx (void ) -{ -PCIHostState *s =OBJECT_CHECK (PCIHostState, -object_resolve_path ("/machine/i440fx" ,NULL ), -TYPE_PCI_HOST_BRIDGE ); -return s ? s->bus :NULL ; -} -/* PIIX3 PCI to ISA bridge */ static void piix3_set_irq_pic (PIIX3State *piix3,int pic_irq) {
include/hw/i386/pc.h +0 -1
@@ -260,7 +260,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type, MemoryRegion *pci_memory, MemoryRegion *ram_memory); -PCIBus *find_i440fx (void );/* piix4.c */ extern PCIDevice *piix4_dev;int piix4_init (PCIBus *bus,ISABus **isa_bus,int devfn);
stubs/Makefile.objs +0 -1
@@ -41,6 +41,5 @@ stub-obj-y += pc_madt_cpu_entry.o stub-obj-y += vmgenid.o stub-obj-y += xen-common.o stub-obj-y += xen-hvm.o -stub-obj-y += pci-host-piix.o stub-obj-y += ram-block.o stub-obj-y += ramfb.o
stubs/pci-host-piix.c deleted +0 -6
@@ -1,6 +0,0 @@ -#include "qemu/osdep.h" -#include "hw/i386/pc.h" -PCIBus *find_i440fx (void ) -{ -return NULL ; -}
Signature · 1 line
2.17.2
PATCH v2 17/19 hw: acpi: Define ACPI tables builder interface
In reply to Samuel OrtizIn order to decouple ACPI APIs from specific machine types, we are creating an ACPI builder interface that each ACPI platform can choose to implement.
This way, a new machine type can re-use the high level ACPI APIs and define some custom table build methods, without having to duplicate most of the existing implementation only to add small variations to it.
--- hw/acpi/Makefile.objs | 1 + hw/acpi/builder.c | 97 +++++++++++++++++++++++++++++++++++++++ include/hw/acpi/builder.h | 97 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 195 insertions(+) create mode 100644 hw/acpi/builder.c create mode 100644 include/hw/acpi/builder.h
hw/acpi/Makefile.objs +1 -0
@@ -11,6 +11,7 @@ common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o common-obj-y += acpi_interface.o common-obj-y += bios-linker-loader.o common-obj-y += aml-build.o +common-obj-y += builder.o common-obj-$(CONFIG_IPMI) += ipmi.o common-obj-$(call lnot,$(CONFIG_IPMI)) += ipmi-stub.o
hw/acpi/builder.c new file +97 -0
97 lines not on this page · raw message
include/hw/acpi/builder.h new file +97 -0
97 lines not on this page · raw message
Signature · 1 line
2.17.2
PATCH v2 18/19 hw: i386: Export the MADT build method
In reply to Samuel OrtizIt is going to be used by the PC machine type as the MADT table builder method and thus needs to be exported outside of acpi-build.c
Also, now that the generic build_madt() API is exported, we have to rename the ARM static one in order to avoid build time conflicts.
--- hw/arm/virt-acpi-build.c | 4 ++-- hw/i386/acpi-build.c | 3 ++- include/hw/i386/acpi.h | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 include/hw/i386/acpi.h
hw/arm/virt-acpi-build.c +2 -2
@@ -565,7 +565,7 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)/* MADT */ static void -build_madt (GArray *table_data,BIOSLinker *linker,VirtMachineState *vms) +virt_build_madt (GArray *table_data,BIOSLinker *linker,VirtMachineState *vms) {VirtMachineClass *vmc =VIRT_MACHINE_GET_CLASS (vms);int madt_start = table_data->len;
@@ -746,7 +746,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)build_fadt_rev5 (tables_blob, tables->linker, vms, dsdt);acpi_add_table (table_offsets, tables_blob); -build_madt (tables_blob, tables->linker, vms); +virt_build_madt (tables_blob, tables->linker, vms);acpi_add_table (table_offsets, tables_blob);build_gtdt (tables_blob, tables->linker, vms);
hw/i386/acpi-build.c +2 -1
@@ -62,6 +62,7 @@#include "qom/qom-qobject.h" #include "hw/i386/amd_iommu.h" #include "hw/i386/intel_iommu.h" +#include "hw/i386/acpi.h" #include "hw/acpi/ipmi.h"
@@ -281,7 +282,7 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, } } -static void +void build_madt (GArray *table_data,BIOSLinker *linker,MachineState *ms,AcpiConfiguration *conf) {
include/hw/i386/acpi.h new file +27 -0
@@ -0,0 +1,27 @@ +/* +* +* Copyright (c) 2018 Intel Corportation +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2 or later, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef QEMU_I386_ACPI_H +#define QEMU_I386_ACPI_H + +#include "hw/acpi/acpi.h" + +/* Build methods */ +void build_madt (GArray *table_data,BIOSLinker *linker, +MachineState *ms,AcpiConfiguration *conf); + +#endif
Signature · 1 line
2.17.2
PATCH v2 19/19 hw: i386: Implement the ACPI builder interface for PC
In reply to Samuel OrtizAll PC machine type derivatives will use the same ACPI table build methods. But with that change in place, any new x86 machine type will be able to re-use the acpi-build API and customize part of it by defining its own ACPI table build methods.
--- hw/i386/acpi-build.c | 15 ++++++++++----- hw/i386/pc.c | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-)
hw/i386/acpi-build.c +10 -5
@@ -35,6 +35,7 @@#include "hw/acpi/acpi-defs.h" #include "hw/acpi/acpi.h" #include "hw/acpi/cpu.h" +#include "hw/acpi/builder.h" #include "hw/nvram/fw_cfg.h" #include "hw/acpi/bios-linker-loader.h" #include "hw/loader.h"
@@ -1556,6 +1557,7 @@ void acpi_build(AcpiBuildTables *tables,GArray *tables_blob = tables->table_data;AcpiSlicOem slic_oem = { .id =NULL , .table_id =NULL };Object *vmgenid_dev; +AcpiBuilder *ab =ACPI_BUILDER (machine);acpi_get_pm_info (&pm);acpi_get_misc_info (&misc);
@@ -1605,7 +1607,8 @@ void acpi_build(AcpiBuildTables *tables, aml_len += tables_blob->len - fadt;acpi_add_table (table_offsets, tables_blob); -build_madt (tables_blob, tables->linker, machine, conf); +acpi_builder_madt (ab, tables_blob, tables->linker, + machine, conf); vmgenid_dev =find_vmgenid_dev ();if (vmgenid_dev) {
@@ -1629,15 +1632,17 @@ void acpi_build(AcpiBuildTables *tables, }if (conf->numa_nodes) {acpi_add_table (table_offsets, tables_blob); -build_srat (tables_blob, tables->linker, machine, conf); + +acpi_builder_srat (ab, tables_blob, tables->linker, + machine, conf);if (have_numa_distance) {acpi_add_table (table_offsets, tables_blob); -build_slit (tables_blob, tables->linker); +acpi_builder_slit (ab, tables_blob, tables->linker); } }if (acpi_get_mcfg (&mcfg)) {acpi_add_table (table_offsets, tables_blob); -build_mcfg (tables_blob, tables->linker, &mcfg); +acpi_builder_mcfg (ab, tables_blob, tables->linker, &mcfg); }if (x86_iommu_get_default ()) {IommuType IOMMUType =x86_iommu_get_type ();
@@ -1668,7 +1673,7 @@ void acpi_build(AcpiBuildTables *tables, slic_oem.id, slic_oem.table_id);/* RSDP is in FSEG memory, so allocate it separately */ -build_rsdp_rsdt (tables->rsdp, tables->linker, rsdt); +acpi_builder_rsdp (ab, tables->rsdp, tables->linker, rsdt);/* We'll expose it all to Guest so we want to reduce * chance of size changes.
hw/i386/pc.c +19 -0
@@ -64,6 +64,7 @@#include "qemu/option.h" #include "hw/acpi/acpi.h" #include "hw/acpi/cpu_hotplug.h" +#include "hw/acpi/builder.h" #include "hw/boards.h" #include "acpi-build.h" #include "hw/mem/pc-dimm.h"
@@ -75,6 +76,7 @@#include "hw/nmi.h" #include "hw/i386/intel_iommu.h" #include "hw/net/ne2000-isa.h" +#include "hw/i386/acpi.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ
@@ -2403,12 +2405,20 @@ static void x86_nmi(NMIState *n, int cpu_index, Error **errp) } } +static AcpiConfiguration *pc_acpi_configuration (AcpiBuilder *builder) +{ +PCMachineState *pcms =PC_MACHINE (builder); + +return &pcms->acpi_configuration; +} +static void pc_machine_class_init (ObjectClass *oc,void *data) {MachineClass *mc =MACHINE_CLASS (oc);PCMachineClass *pcmc =PC_MACHINE_CLASS (oc);HotplugHandlerClass *hc =HOTPLUG_HANDLER_CLASS (oc);NMIClass *nc =NMI_CLASS (oc); +AcpiBuilderMethods *abm =ACPI_BUILDER_METHODS (oc); pcmc->pci_enabled = true; pcmc->has_acpi_build = true;
@@ -2443,6 +2453,14 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) nc->nmi_monitor_handler = x86_nmi; mc->default_cpu_type =TARGET_DEFAULT_CPU_TYPE ; +/* ACPI building methods */ + abm->madt = build_madt; + abm->rsdp = build_rsdp_rsdt; + abm->mcfg = build_mcfg; + abm->srat = build_srat; + abm->slit = build_slit; + abm->configuration = pc_acpi_configuration; +object_class_property_add (oc,MEMORY_DEVICE_REGION_SIZE ,"int" , pc_machine_get_device_memory_region_size,NULL ,NULL ,NULL , &error_abort);
@@ -2494,6 +2512,7 @@ static const TypeInfo pc_machine_info = { .interfaces = (InterfaceInfo[]) { {TYPE_HOTPLUG_HANDLER }, {TYPE_NMI }, + {TYPE_ACPI_BUILDER }, { } }, };
Signature · 1 line
2.17.2
Please discard that serie as I forgot to Cc the proper maintainers in many of those patches. Apologies for that, I'm going to send a v3 in a few minutes.
Cheers,
Samuel.
Quoted 87 lines · Samuel Ortiz
This patch set provides an ACPI code reorganization in preparation for adding hardware-reduced support to QEMU.
The changes are coming from the NEMU [1] project where we're defining a new x86 machine type: i386/virt. This is an EFI only, ACPI hardware-reduced platform and as such we had to implement support for the latter.
As a preliminary for adding hardware-reduced support to QEMU, we did some ACPI code reorganization with the following goals:
* Share as much as possible of the current ACPI build APIs between legacy and hardware-reduced ACPI.
* Share the ACPI build code across machine types and architectures and remove the typical PC machine type dependency.
Eventually we hope to see arm/virt also re-use much of that code.The patches are also available in their own git branch [2].
[1] https://github.com/intel/nemu
[2] https://github.com/intel/nemu/tree/topic/upstream/acpiv1 -> v2:
* Drop the hardware-reduced implementation for now. Our next patch set will add hardware-reduced and convert arm/virt to it.
* Implement the ACPI build methods as a QOM Interface Class and convert the PC machine type to it.Samuel Ortiz (10):
hw: i386: Decouple the ACPI build from the PC machine type
hw: acpi: Export ACPI build alignment API
hw: acpi: Export the RSDP build API
hw: acpi: Implement XSDT support for RSDP
hw: arm: Switch to the AML build RSDP building routine
hw: acpi: Do not create hotplug method when handler is not defined
hw: i386: Make the hotpluggable memory size property more generic
hw: acpi: Define ACPI tables builder interface
hw: i386: Export the MADT build method
hw: i386: Implement the ACPI builder interface for PCSebastien Boeuf (2):
hw: acpi: Export the PCI hotplug API
hw: acpi: Retrieve the PCI bus from AcpiPciHpStateYang Zhong (7):
hw: acpi: Generalize AML build routines
hw: acpi: Factorize_OSCAML across architectures
hw: i386: Refactor PCI host getter
hw: acpi: Export and generalize the PCI host AML API
hw: acpi: Export the MCFG getter
hw: acpi: Export the SRAT AML build API
hw: acpi: Fix memory hotplug AML generation errorhw/acpi/Makefile.objs | 1 + hw/acpi/aml-build.c | 1129 ++++++++++++++++++++++++++++++ hw/acpi/builder.c | 97 +++ hw/acpi/cpu.c | 8 +- hw/acpi/cpu_hotplug.c | 9 +- hw/acpi/memory_hotplug.c | 21 +- hw/acpi/pcihp.c | 10 +- hw/arm/virt-acpi-build.c | 98 +-- hw/i386/acpi-build.c | 1174 ++------------------------------ hw/i386/acpi-build.h | 4 +- hw/i386/pc.c | 198 ++++-- hw/i386/pc_piix.c | 21 +- hw/i386/pc_q35.c | 21 +- hw/i386/xen/xen-hvm.c | 19 +- hw/pci-host/piix.c | 8 - include/hw/acpi/acpi-defs.h | 14 + include/hw/acpi/acpi.h | 43 ++ include/hw/acpi/aml-build.h | 50 ++ include/hw/acpi/builder.h | 97 +++ include/hw/i386/acpi.h | 27 + include/hw/i386/pc.h | 21 +- include/hw/mem/memory-device.h | 2 + stubs/Makefile.objs | 1 - stubs/pci-host-piix.c | 6 - 24 files changed, 1735 insertions(+), 1344 deletions(-) create mode 100644 hw/acpi/builder.c create mode 100644 include/hw/acpi/builder.h create mode 100644 include/hw/i386/acpi.h delete mode 100644 stubs/pci-host-piix.cSignature · 1 line
2.17.2
You neglected to cc: maintainers. I'm doing that for you now. scripts/get_maintainer.pl can help you finding maintainers.
Quoted 27 lines · Samuel Ortiz
This patch set provides an ACPI code reorganization in preparation for adding hardware-reduced support to QEMU.
The changes are coming from the NEMU [1] project where we're defining a new x86 machine type: i386/virt. This is an EFI only, ACPI hardware-reduced platform and as such we had to implement support for the latter.
As a preliminary for adding hardware-reduced support to QEMU, we did some ACPI code reorganization with the following goals:
* Share as much as possible of the current ACPI build APIs between legacy and hardware-reduced ACPI.
* Share the ACPI build code across machine types and architectures and remove the typical PC machine type dependency.
Eventually we hope to see arm/virt also re-use much of that code.The patches are also available in their own git branch [2].
[1] https://github.com/intel/nemu
[2] https://github.com/intel/nemu/tree/topic/upstream/acpiv1 -> v2:
* Drop the hardware-reduced implementation for now. Our next patch set will add hardware-reduced and convert arm/virt to it.
* Implement the ACPI build methods as a QOM Interface Class and convert the PC machine type to it.
[...]
Hi Markus,
Quoted 2 lines · Markus Armbruster
You neglected to cc: maintainers. I'm doing that for you now.
scripts/get_maintainer.plcan help you finding maintainers.
Sorry about that. I sent a v3 with all maintainers cc'ed.
Cheers,
Samuel.
Quoted 31 lines
Quoted 27 lines · Samuel Ortiz
This patch set provides an ACPI code reorganization in preparation for adding hardware-reduced support to QEMU.
The changes are coming from the NEMU [1] project where we're defining a new x86 machine type: i386/virt. This is an EFI only, ACPI hardware-reduced platform and as such we had to implement support for the latter.
As a preliminary for adding hardware-reduced support to QEMU, we did some ACPI code reorganization with the following goals:
* Share as much as possible of the current ACPI build APIs between legacy and hardware-reduced ACPI.
* Share the ACPI build code across machine types and architectures and remove the typical PC machine type dependency.
Eventually we hope to see arm/virt also re-use much of that code.The patches are also available in their own git branch [2].
[1] https://github.com/intel/nemu
[2] https://github.com/intel/nemu/tree/topic/upstream/acpiv1 -> v2:
* Drop the hardware-reduced implementation for now. Our next patch set will add hardware-reduced and convert arm/virt to it.
* Implement the ACPI build methods as a QOM Interface Class and convert the PC machine type to it.[...]
Quoted 6 lines · Samuel Ortiz
Hi Markus,
Quoted 2 lines · Markus Armbruster
You neglected to cc: maintainers. I'm doing that for you now.
scripts/get_maintainer.plcan help you finding maintainers.Sorry about that. I sent a v3 with all maintainers cc'ed.
I don't think that's necessary unless you add more people than I did.