summaryrefslogtreecommitdiffstats
path: root/hw/i386
diff options
context:
space:
mode:
authorBen Widawsky2022-04-29 16:40:48 +0200
committerMichael S. Tsirkin2022-05-13 12:13:36 +0200
commit6e4e3ae936e6bc1501fc0d67444738cec7a1e78a (patch)
treea0380b1a23b364b50d9b7a0c49ef8e2f6d4f9a39 /hw/i386
parentqtests/cxl: Add initial root port and CXL type3 tests (diff)
downloadqemu-6e4e3ae936e6bc1501fc0d67444738cec7a1e78a.tar.gz
qemu-6e4e3ae936e6bc1501fc0d67444738cec7a1e78a.tar.xz
qemu-6e4e3ae936e6bc1501fc0d67444738cec7a1e78a.zip
hw/cxl/component: Implement host bridge MMIO (8.2.5, table 142)
CXL host bridges themselves may have MMIO. Since host bridges don't have a BAR they are treated as special for MMIO. This patch includes i386/pc support. Also hook up the device reset now that we have have the MMIO space in which the results are visible. Note that we duplicate the PCI express case for the aml_build but the implementations will diverge when the CXL specific _OSC is introduced. Signed-off-by: Ben Widawsky <ben.widawsky@intel.com> Co-developed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Message-Id: <20220429144110.25167-24-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'hw/i386')
-rw-r--r--hw/i386/acpi-build.c25
-rw-r--r--hw/i386/pc.c27
2 files changed, 49 insertions, 3 deletions
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index dcf6ece3d0..2d81b0f40c 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -28,6 +28,7 @@
#include "qemu/bitmap.h"
#include "qemu/error-report.h"
#include "hw/pci/pci.h"
+#include "hw/cxl/cxl.h"
#include "hw/core/cpu.h"
#include "target/i386/cpu.h"
#include "hw/misc/pvpanic.h"
@@ -1572,10 +1573,21 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
}
scope = aml_scope("\\_SB");
- dev = aml_device("PC%.02X", bus_num);
+
+ if (pci_bus_is_cxl(bus)) {
+ dev = aml_device("CL%.02X", bus_num);
+ } else {
+ dev = aml_device("PC%.02X", bus_num);
+ }
aml_append(dev, aml_name_decl("_UID", aml_int(bus_num)));
aml_append(dev, aml_name_decl("_BBN", aml_int(bus_num)));
- if (pci_bus_is_express(bus)) {
+ if (pci_bus_is_cxl(bus)) {
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
+ aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
+
+ /* Expander bridges do not have ACPI PCI Hot-plug enabled */
+ aml_append(dev, build_q35_osc_method(true));
+ } 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")));
@@ -1595,6 +1607,15 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
aml_append(dev, aml_name_decl("_CRS", crs));
aml_append(scope, dev);
aml_append(dsdt, scope);
+
+ /* Handle the ranges for the PXB expanders */
+ if (pci_bus_is_cxl(bus)) {
+ MemoryRegion *mr = &machine->cxl_devices_state->host_mr;
+ uint64_t base = mr->addr;
+
+ crs_range_insert(crs_range_set.mem_ranges, base,
+ base + memory_region_size(mr) - 1);
+ }
}
}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 45e2d6092f..03d14f6564 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -75,6 +75,7 @@
#include "acpi-build.h"
#include "hw/mem/pc-dimm.h"
#include "hw/mem/nvdimm.h"
+#include "hw/cxl/cxl.h"
#include "qapi/error.h"
#include "qapi/qapi-visit-common.h"
#include "qapi/qapi-visit-machine.h"
@@ -816,6 +817,7 @@ void pc_memory_init(PCMachineState *pcms,
MachineClass *mc = MACHINE_GET_CLASS(machine);
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
X86MachineState *x86ms = X86_MACHINE(pcms);
+ hwaddr cxl_base;
assert(machine->ram_size == x86ms->below_4g_mem_size +
x86ms->above_4g_mem_size);
@@ -905,6 +907,26 @@ void pc_memory_init(PCMachineState *pcms,
&machine->device_memory->mr);
}
+ if (machine->cxl_devices_state->is_enabled) {
+ MemoryRegion *mr = &machine->cxl_devices_state->host_mr;
+ hwaddr cxl_size = MiB;
+
+ if (pcmc->has_reserved_memory && machine->device_memory->base) {
+ cxl_base = machine->device_memory->base;
+ if (!pcmc->broken_reserved_end) {
+ cxl_base += memory_region_size(&machine->device_memory->mr);
+ }
+ } else if (pcms->sgx_epc.size != 0) {
+ cxl_base = sgx_epc_above_4g_end(&pcms->sgx_epc);
+ } else {
+ cxl_base = 0x100000000ULL + x86ms->above_4g_mem_size;
+ }
+
+ e820_add_entry(cxl_base, cxl_size, E820_RESERVED);
+ memory_region_init(mr, OBJECT(machine), "cxl_host_reg", cxl_size);
+ memory_region_add_subregion(system_memory, cxl_base, mr);
+ }
+
/* Initialize PC system firmware */
pc_system_firmware_init(pcms, rom_memory);
@@ -965,7 +987,10 @@ uint64_t pc_pci_hole64_start(void)
X86MachineState *x86ms = X86_MACHINE(pcms);
uint64_t hole64_start = 0;
- if (pcmc->has_reserved_memory && ms->device_memory->base) {
+ if (ms->cxl_devices_state->host_mr.addr) {
+ hole64_start = ms->cxl_devices_state->host_mr.addr +
+ memory_region_size(&ms->cxl_devices_state->host_mr);
+ } else if (pcmc->has_reserved_memory && ms->device_memory->base) {
hole64_start = ms->device_memory->base;
if (!pcmc->broken_reserved_end) {
hole64_start += memory_region_size(&ms->device_memory->mr);