From: Manish Honap <[email protected]> A pxb-cxl host bridge had no PCI host-bridge _DSM method, so it could not emit function 5 (preserve firmware PCI configuration) even when the machine asks OSPM to keep the firmware resource assignments.
That preservation is required by the accelerated SMMUv3 (accel=on), which describes MSI 1:1 mappings through IORT RMR nodes. An RMR reserves a fixed IOVA range, so OSPM must not re-enumerate and reassign the PCI resources underneath it. virt sets pci_preserve_config for that case and expects every host bridge to emit the _DSM; the pxb-cxl bridge was the one that did not, so a CXL topology under an accelerated SMMU lost the guarantee. This is not about the component register BAR moving. vfio-pci marks every BAR dword ALL_VIRT, so a guest BAR write updates the virtual config only and cannot move the host resource, and QEMU's trapped comp-regs region is a subregion of the BAR MemoryRegion, so it follows any guest-visible relocation while the kernel's physical decoder mapping stays fixed. The CXL.mem window is delivered through CEDT/CFMWS and is likewise unaffected by PCI resource assignment. Wire preserve_config through GPEXConfig into the CXL host bridge OSC path so pxb-cxl bridges emit the _DSM function 5. Rename build_cxl_osc_method() to acpi_dsdt_add_cxl_host_bridge_methods() to match the pxb-pcie analogue acpi_dsdt_add_host_bridge_methods(), since it now appends both the _OSC and the _DSM. x86 passes false as it does not use the accelerated SMMU. Signed-off-by: Manish Honap <[email protected]> --- hw/acpi/Kconfig | 1 + hw/acpi/cxl-stub.c | 2 +- hw/acpi/cxl.c | 4 +++- hw/acpi/pci.c | 40 +++++++++++++++++++++++++++++++++++++++ hw/i386/acpi-build.c | 2 +- hw/pci-host/gpex-acpi.c | 42 ++--------------------------------------- include/hw/acpi/cxl.h | 2 +- include/hw/acpi/pci.h | 1 + 8 files changed, 50 insertions(+), 44 deletions(-) diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig index daabbe6cd1..9490b75c94 100644 --- a/hw/acpi/Kconfig +++ b/hw/acpi/Kconfig @@ -88,3 +88,4 @@ config ACPI_ERST config ACPI_CXL bool depends on ACPI + select ACPI_PCI diff --git a/hw/acpi/cxl-stub.c b/hw/acpi/cxl-stub.c index 15bc21076b..d7c6731975 100644 --- a/hw/acpi/cxl-stub.c +++ b/hw/acpi/cxl-stub.c @@ -6,7 +6,7 @@ #include "hw/acpi/aml-build.h" #include "hw/acpi/cxl.h" -void build_cxl_osc_method(Aml *dev) +void acpi_dsdt_add_cxl_host_bridge_methods(Aml *dev, bool preserve_config) { g_assert_not_reached(); } diff --git a/hw/acpi/cxl.c b/hw/acpi/cxl.c index f92f7fa3d5..7607ba500f 100644 --- a/hw/acpi/cxl.c +++ b/hw/acpi/cxl.c @@ -23,6 +23,7 @@ #include "hw/pci/pci_host.h" #include "hw/cxl/cxl.h" #include "hw/cxl/cxl_host.h" +#include "hw/acpi/pci.h" #include "hw/mem/memory-device.h" #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" @@ -320,11 +321,12 @@ static Aml *__build_cxl_osc_method(void) return method; } -void build_cxl_osc_method(Aml *dev) +void acpi_dsdt_add_cxl_host_bridge_methods(Aml *dev, bool preserve_config) { aml_append(dev, aml_name_decl("SUPP", aml_int(0))); aml_append(dev, aml_name_decl("CTRL", aml_int(0))); aml_append(dev, aml_name_decl("SUPC", aml_int(0))); aml_append(dev, aml_name_decl("CTRC", aml_int(0))); aml_append(dev, __build_cxl_osc_method()); + aml_append(dev, build_pci_host_bridge_dsm_method(preserve_config)); } diff --git a/hw/acpi/pci.c b/hw/acpi/pci.c index 8c7ed10479..1a20f8469b 100644 --- a/hw/acpi/pci.c +++ b/hw/acpi/pci.c @@ -351,3 +351,43 @@ Aml *build_pci_host_bridge_osc_method(bool enable_native_pcie_hotplug) aml_append(method, aml_return(aml_arg(3))); return method; } + +Aml *build_pci_host_bridge_dsm_method(bool preserve_config) +{ + Aml *method = aml_method("_DSM", 4, AML_NOTSERIALIZED); + Aml *UUID, *ifctx, *ifctx1, *buf; + uint8_t byte_list[1] = {0}; + + /* + * PCI Firmware Specification 3.0 + * 4.6.1. _DSM for PCI Express Slot Information + * The UUID in _DSM in this context is + * {E5C937D0-3553-4D7A-9117-EA4D19C3434D} + */ + UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); + ifctx = aml_if(aml_equal(aml_arg(0), UUID)); + ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0))); + if (preserve_config) { + /* support functions other than 0, specifically function 5 */ + byte_list[0] = 0x21; + } + buf = aml_buffer(1, byte_list); + aml_append(ifctx1, aml_return(buf)); + aml_append(ifctx, ifctx1); + if (preserve_config) { + Aml *ifctx2 = aml_if(aml_equal(aml_arg(2), aml_int(5))); + /* + * 0 - The operating system must not ignore the PCI configuration that + * firmware has done at boot time. + */ + aml_append(ifctx2, aml_return(aml_int(0))); + aml_append(ifctx, ifctx2); + } + + aml_append(method, ifctx); + + byte_list[0] = 0; + buf = aml_buffer(1, byte_list); + aml_append(method, aml_return(buf)); + return method; +} diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 8837b69687..a24bff8c88 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1019,7 +1019,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(aml_pkg, aml_eisaid("PNP0A08")); aml_append(aml_pkg, aml_eisaid("PNP0A03")); aml_append(dev, aml_name_decl("_CID", aml_pkg)); - build_cxl_osc_method(dev); + acpi_dsdt_add_cxl_host_bridge_methods(dev, false); } else if (pci_bus_is_express(bus)) { aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); diff --git a/hw/pci-host/gpex-acpi.c b/hw/pci-host/gpex-acpi.c index d9820f9b41..014f647c7f 100644 --- a/hw/pci-host/gpex-acpi.c +++ b/hw/pci-host/gpex-acpi.c @@ -51,45 +51,6 @@ static void acpi_dsdt_add_pci_route_table(Aml *dev, uint32_t irq, } } -static Aml *build_pci_host_bridge_dsm_method(bool preserve_config) -{ - Aml *method = aml_method("_DSM", 4, AML_NOTSERIALIZED); - Aml *UUID, *ifctx, *ifctx1, *buf; - uint8_t byte_list[1] = {0}; - - /* PCI Firmware Specification 3.0 - * 4.6.1. _DSM for PCI Express Slot Information - * The UUID in _DSM in this context is - * {E5C937D0-3553-4D7A-9117-EA4D19C3434D} - */ - UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); - ifctx = aml_if(aml_equal(aml_arg(0), UUID)); - ifctx1 = aml_if(aml_equal(aml_arg(2), aml_int(0))); - if (preserve_config) { - /* support functions other than 0, specifically function 5 */ - byte_list[0] = 0x21; - } - buf = aml_buffer(1, byte_list); - aml_append(ifctx1, aml_return(buf)); - aml_append(ifctx, ifctx1); - if (preserve_config) { - Aml *ifctx2 = aml_if(aml_equal(aml_arg(2), aml_int(5))); - /* - * 0 - The operating system must not ignore the PCI configuration that - * firmware has done at boot time. - */ - aml_append(ifctx2, aml_return(aml_int(0))); - aml_append(ifctx, ifctx2); - } - - aml_append(method, ifctx); - - byte_list[0] = 0; - buf = aml_buffer(1, byte_list); - aml_append(method, aml_return(buf)); - return method; -} - static void acpi_dsdt_add_host_bridge_methods(Aml *dev, bool enable_native_pcie_hotplug, bool preserve_config) @@ -164,7 +125,8 @@ void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) aml_append(dev, aml_name_decl("_CRS", crs)); if (is_cxl) { - build_cxl_osc_method(dev); + acpi_dsdt_add_cxl_host_bridge_methods(dev, + cfg->preserve_config); } else { /* pxb bridges do not have ACPI PCI Hot-plug enabled */ acpi_dsdt_add_host_bridge_methods(dev, true, diff --git a/include/hw/acpi/cxl.h b/include/hw/acpi/cxl.h index 8f22c71530..6fe6c9c58d 100644 --- a/include/hw/acpi/cxl.h +++ b/include/hw/acpi/cxl.h @@ -24,7 +24,7 @@ void cxl_build_cedt(GArray *table_offsets, GArray *table_data, BIOSLinker *linker, const char *oem_id, const char *oem_table_id, CXLState *cxl_state); -void build_cxl_osc_method(Aml *dev); +void acpi_dsdt_add_cxl_host_bridge_methods(Aml *dev, bool preserve_config); void build_cxl_dsm_method(Aml *dev); #endif diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h index 20b672575f..c7de33f8cf 100644 --- a/include/hw/acpi/pci.h +++ b/include/hw/acpi/pci.h @@ -42,6 +42,7 @@ void build_pci_bridge_aml(AcpiDevAmlIf *adev, Aml *scope); void build_srat_generic_affinity_structures(GArray *table_data); Aml *build_pci_host_bridge_osc_method(bool enable_native_pcie_hotplug); +Aml *build_pci_host_bridge_dsm_method(bool preserve_config); Aml *build_pci_bridge_edsm(void); #endif -- 2.25.1
