mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 09:13:55 -06:00
hw/acpi: Generic Port Affinity Structure support
These are very similar to the recently added Generic Initiators but instead of representing an initiator of memory traffic they represent an edge point beyond which may lie either targets or initiators. Here we add these ports such that they may be targets of hmat_lb records to describe the latency and bandwidth from host side initiators to the port. A discoverable mechanism such as UEFI CDAT read from CXL devices and switches is used to discover the remainder of the path, and the OS can build up full latency and bandwidth numbers as need for work and data placement decisions. Acked-by: Markus Armbruster <armbru@redhat.com> Tested-by: "Huang, Ying" <ying.huang@intel.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Message-Id: <20240916174122.1843197-1-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
43eb5e1f73
commit
a82fe82916
9 changed files with 202 additions and 5 deletions
116
hw/acpi/pci.c
116
hw/acpi/pci.c
|
@ -30,6 +30,7 @@
|
|||
#include "hw/boards.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/pci.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
#include "hw/pci/pci_device.h"
|
||||
#include "hw/pci/pcie_host.h"
|
||||
|
||||
|
@ -177,9 +178,122 @@ static int build_acpi_generic_initiator(Object *obj, void *opaque)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void build_srat_generic_pci_initiator(GArray *table_data)
|
||||
typedef struct AcpiGenericPort {
|
||||
/* private */
|
||||
Object parent;
|
||||
|
||||
/* public */
|
||||
char *pci_bus;
|
||||
uint32_t node;
|
||||
} AcpiGenericPort;
|
||||
|
||||
typedef struct AcpiGenericPortClass {
|
||||
ObjectClass parent_class;
|
||||
} AcpiGenericPortClass;
|
||||
|
||||
#define TYPE_ACPI_GENERIC_PORT "acpi-generic-port"
|
||||
|
||||
OBJECT_DEFINE_TYPE_WITH_INTERFACES(AcpiGenericPort, acpi_generic_port,
|
||||
ACPI_GENERIC_PORT, OBJECT,
|
||||
{ TYPE_USER_CREATABLE },
|
||||
{ NULL })
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(AcpiGenericPort, ACPI_GENERIC_PORT)
|
||||
|
||||
static void acpi_generic_port_init(Object *obj)
|
||||
{
|
||||
AcpiGenericPort *gp = ACPI_GENERIC_PORT(obj);
|
||||
|
||||
gp->node = MAX_NODES;
|
||||
gp->pci_bus = NULL;
|
||||
}
|
||||
|
||||
static void acpi_generic_port_finalize(Object *obj)
|
||||
{
|
||||
AcpiGenericPort *gp = ACPI_GENERIC_PORT(obj);
|
||||
|
||||
g_free(gp->pci_bus);
|
||||
}
|
||||
|
||||
static void acpi_generic_port_set_pci_bus(Object *obj, const char *val,
|
||||
Error **errp)
|
||||
{
|
||||
AcpiGenericPort *gp = ACPI_GENERIC_PORT(obj);
|
||||
|
||||
gp->pci_bus = g_strdup(val);
|
||||
}
|
||||
|
||||
static void acpi_generic_port_set_node(Object *obj, Visitor *v,
|
||||
const char *name, void *opaque,
|
||||
Error **errp)
|
||||
{
|
||||
AcpiGenericPort *gp = ACPI_GENERIC_PORT(obj);
|
||||
uint32_t value;
|
||||
|
||||
if (!visit_type_uint32(v, name, &value, errp)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value >= MAX_NODES) {
|
||||
error_printf("%s: Invalid NUMA node specified\n",
|
||||
TYPE_ACPI_GENERIC_INITIATOR);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
gp->node = value;
|
||||
}
|
||||
|
||||
static void acpi_generic_port_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
object_class_property_add_str(oc, "pci-bus", NULL,
|
||||
acpi_generic_port_set_pci_bus);
|
||||
object_class_property_set_description(oc, "pci-bus",
|
||||
"PCI Bus of the host bridge associated with this GP affinity structure");
|
||||
object_class_property_add(oc, "node", "int", NULL,
|
||||
acpi_generic_port_set_node, NULL, NULL);
|
||||
object_class_property_set_description(oc, "node",
|
||||
"The NUMA node like ID to index HMAT/SLIT NUMA properties involving GP");
|
||||
}
|
||||
|
||||
static int build_acpi_generic_port(Object *obj, void *opaque)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
const char *hid = "ACPI0016";
|
||||
GArray *table_data = opaque;
|
||||
AcpiGenericPort *gp;
|
||||
uint32_t uid;
|
||||
Object *o;
|
||||
|
||||
if (!object_dynamic_cast(obj, TYPE_ACPI_GENERIC_PORT)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
gp = ACPI_GENERIC_PORT(obj);
|
||||
|
||||
if (gp->node >= ms->numa_state->num_nodes) {
|
||||
error_printf("%s: node %d is invalid.\n",
|
||||
TYPE_ACPI_GENERIC_PORT, gp->node);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
o = object_resolve_path_type(gp->pci_bus, TYPE_PXB_CXL_BUS, NULL);
|
||||
if (!o) {
|
||||
error_printf("%s: device must be a CXL host bridge.\n",
|
||||
TYPE_ACPI_GENERIC_PORT);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uid = object_property_get_uint(o, "acpi_uid", &error_fatal);
|
||||
build_srat_acpi_generic_port(table_data, gp->node, hid, uid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void build_srat_generic_affinity_structures(GArray *table_data)
|
||||
{
|
||||
object_child_foreach_recursive(object_get_root(),
|
||||
build_acpi_generic_initiator,
|
||||
table_data);
|
||||
object_child_foreach_recursive(object_get_root(), build_acpi_generic_port,
|
||||
table_data);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue