Signed-off-by: Dave Jiang <dave.ji...@intel.com> --- hw/acpi/genport.c | 61 +++++++++++++++++++++++++++++++++++++++++++ hw/acpi/meson.build | 1 + hw/i386/acpi-build.c | 32 ++++++++++++++++++----- include/hw/acpi/aml-build.h | 4 +-- softmmu/vl.c | 26 ++++++++++++++++++ 5 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 hw/acpi/genport.c
diff --git a/hw/acpi/genport.c b/hw/acpi/genport.c new file mode 100644 index 000000000000..5738730323c2 --- /dev/null +++ b/hw/acpi/genport.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Generic Port device implementation + * + * Copyright (C) 2023 Intel Corporation + */ +#include "qemu/osdep.h" +#include "hw/qdev-properties.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "qom/object_interfaces.h" +#include "hw/qdev-core.h" + +#define TYPE_GENERIC_PORT_DEVICE "genport" + +#define GENPORT_NUMA_NODE_PROP "node" +#define GENPORT_DEV_PROP "genport" + +typedef struct GenericPortDevice { + /* private */ + DeviceState parent_obj; + + /* public */ + uint32_t node; +} GenericPortDevice; + +typedef struct GenericPortDeviceClass { + DeviceClass parent_class; +} GenericPortDeviceClass; + +static Property genport_properties[] = { + DEFINE_PROP_UINT32(GENPORT_NUMA_NODE_PROP, GenericPortDevice, node, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +OBJECT_DEFINE_TYPE_WITH_INTERFACES(GenericPortDevice, genport_device, + GENERIC_PORT_DEVICE, DEVICE, + { TYPE_USER_CREATABLE }, + { NULL }) + +static void genport_device_init(Object *obj) +{ +} + +static void genport_device_finalize(Object *obj) +{ +} + +static void genport_device_realize(DeviceState *dev, Error **errp) +{ +} + +static void genport_device_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = genport_device_realize; + dc->desc = "Generic Port"; + device_class_set_props(dc, genport_properties); +} + diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build index e0bf39bf4cd6..5247554998b0 100644 --- a/hw/acpi/meson.build +++ b/hw/acpi/meson.build @@ -5,6 +5,7 @@ acpi_ss.add(files( 'bios-linker-loader.c', 'core.c', 'utils.c', + 'genport.c', )) acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_true: files('cpu.c', 'cpu_hotplug.c')) acpi_ss.add(when: 'CONFIG_ACPI_CPU_HOTPLUG', if_false: files('acpi-cpu-hotplug-stub.c')) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0d9e610af12b..db850bfd170d 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1514,12 +1514,22 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, 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_cxl(bus)) { - CxlHBDev *hb_entry; + CxlHBDev *hb_entry, *match; + bool found = false; struct Aml *pkg = aml_package(2); - hb_entry = g_malloc0(sizeof(*hb_entry)); - hb_entry->uid = bus_num; - QSLIST_INSERT_HEAD(&cxl_hb_list_head, hb_entry, entry); + QSLIST_FOREACH(match, &cxl_hb_list_head, entry) + { + if (match->uid == bus_num) { + found = true; + break; + } + } + if (!found) { + hb_entry = g_malloc0(sizeof(*hb_entry)); + hb_entry->uid = bus_num; + QSLIST_INSERT_HEAD(&cxl_hb_list_head, hb_entry, entry); + } aml_append(dev, aml_name_decl("_HID", aml_string("ACPI0016"))); aml_append(pkg, aml_eisaid("PNP0A08")); @@ -1892,6 +1902,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) NULL); AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = x86ms->oem_id, .oem_table_id = x86ms->oem_table_id }; + int pxm_domain; acpi_table_begin(&table, table_data); build_append_int_noprefix(table_data, 1, 4); /* Reserved */ @@ -1986,16 +1997,23 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) sgx_epc_build_srat(table_data); + /* FIXME: this is a hack, need a node property for genport */ + pxm_domain = 6; QSLIST_FOREACH(hb_entry, &cxl_hb_list_head, entry) { ACPIDeviceHandle handle = { .hid = "ACPI0016", - .uid = hb_entry->uid, + .reserved = { 0 }, }; + char uid_str[5]; uint32_t flags = GEN_AFFINITY_ENABLED; - build_srat_generic_port_affinity(table_data, 0, nb_numa_nodes, - &handle, flags); + snprintf(uid_str, 4, "%u", hb_entry->uid); + memcpy(handle.uid, uid_str, 4); + + build_srat_generic_port_affinity(table_data, 0, pxm_domain, &handle, + flags); + pxm_domain++; } /* diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 32a4f574abaa..4ad7f0268f65 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -222,8 +222,8 @@ typedef enum { typedef union ACPIDeviceHandle { struct { uint8_t hid[8]; - uint32_t uid; - uint32_t reserved; + uint8_t uid[4]; + uint8_t reserved[4]; }; uint64_t raw[2]; } ACPIDeviceHandle; diff --git a/softmmu/vl.c b/softmmu/vl.c index 459588aa7d14..1ef1d9e5f383 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2523,6 +2523,31 @@ static void qemu_init_board(void) } } +static int genport_realize_cb(Object *obj, void *opaque) +{ + DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE)); + ObjectClass *klass = object_get_class(obj); + ObjectClass *type_klass = object_class_by_name("genport"); + + if (!dev) + return 0; + + if (dev->realized) + return 0; + + if (klass != type_klass) + return 0; + + qdev_realize(dev, NULL, &error_fatal); + return 0; +} + +static void genports_realize(void) +{ + object_child_foreach_recursive(object_get_root(), + genport_realize_cb, NULL); +} + static void qemu_create_cli_devices(void) { DeviceOption *opt; @@ -2557,6 +2582,7 @@ static void qemu_create_cli_devices(void) loc_pop(&opt->loc); } rom_reset_order_override(); + genports_realize(); } static void qemu_machine_creation_done(void)