qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v5 10/13] hw/acpi: Generic Port Affinity Structure support


From: Igor Mammedov
Subject: Re: [PATCH v5 10/13] hw/acpi: Generic Port Affinity Structure support
Date: Mon, 15 Jul 2024 16:48:41 +0200

On Fri, 12 Jul 2024 12:08:14 +0100
Jonathan Cameron <Jonathan.Cameron@huawei.com> wrote:

> 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>

ACPI tables generation LGTM
As for the rest my review is perfunctory mostly.

> ---
> v5: Push the definition of TYPE_ACPI_GENERIC_PORT down into the
>     c file (similar to TYPE_ACPI_GENERIC_INITIATOR in earlier patch)
> ---
>  qapi/qom.json                       |  34 +++++++++
>  include/hw/acpi/aml-build.h         |   4 +
>  include/hw/acpi/pci.h               |   2 +-
>  include/hw/pci/pci_bridge.h         |   1 +
>  hw/acpi/aml-build.c                 |  40 ++++++++++
>  hw/acpi/pci.c                       | 112 +++++++++++++++++++++++++++-
>  hw/arm/virt-acpi-build.c            |   2 +-
>  hw/i386/acpi-build.c                |   2 +-
>  hw/pci-bridge/pci_expander_bridge.c |   1 -
>  9 files changed, 193 insertions(+), 5 deletions(-)
> 
> diff --git a/qapi/qom.json b/qapi/qom.json
> index 8e75a419c3..b97c031b73 100644
> --- a/qapi/qom.json
> +++ b/qapi/qom.json
> @@ -838,6 +838,38 @@
>    'data': { 'pci-dev': 'str',
>              'node': 'uint32' } }
>  
> +##
> +# @AcpiGenericPortProperties:
> +#
> +# Properties for acpi-generic-port objects.
> +#
> +# @pci-bus: QOM path of the PCI bus of the hostbridge associated with
> +#     this SRAT Generic Port Affinity Structure.  This is the same as
> +#     the bus parameter for the root ports attached to this host
> +#     bridge.  The resulting SRAT Generic Port Affinity Structure will
> +#     refer to the ACPI object in DSDT that represents the host bridge
> +#     (e.g.  ACPI0016 for CXL host bridges).  See ACPI 6.5 Section
> +#     5.2.16.7 for more information.
> +#

> +# @node: Similar to a NUMA node ID, but instead of providing a
> +#     reference point used for defining NUMA distances and access
> +#     characteristics to memory or from an initiator (e.g. CPU), this
> +#     node defines the boundary point between non-discoverable system
> +#     buses which must be described by firmware, and a discoverable
> +#     bus.  NUMA distances and access characteristics are defined to
> +#     and from that point.  For system software to establish full
> +#     initiator to target characteristics this information must be
> +#     combined with information retrieved from the discoverable part
> +#     of the path.  An example would use CDAT (see UEFI.org)
> +#     information read from devices and switches in conjunction with
> +#     link characteristics read from PCIe Configuration space.

you lost me here (even reading this several time doesn't help).
Perhaps I lack specific domain knowledge, but is there a way to make it
more comprehensible for layman?

> +#
> +# Since: 9.1
> +##
> +{ 'struct': 'AcpiGenericPortProperties',
> +  'data': { 'pci-bus': 'str',
> +            'node': 'uint32' } }
> +
>  ##
>  # @RngProperties:
>  #
> @@ -1031,6 +1063,7 @@
>  { 'enum': 'ObjectType',
>    'data': [
>      'acpi-generic-initiator',
> +    'acpi-generic-port',
>      'authz-list',
>      'authz-listfile',
>      'authz-pam',
> @@ -1106,6 +1139,7 @@
>    'discriminator': 'qom-type',
>    'data': {
>        'acpi-generic-initiator':     'AcpiGenericInitiatorProperties',
> +      'acpi-generic-port':          'AcpiGenericPortProperties',
>        'authz-list':                 'AuthZListProperties',
>        'authz-listfile':             'AuthZListFileProperties',
>        'authz-pam':                  'AuthZPAMProperties',
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index 33eef85791..9e30c735bb 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -490,6 +490,10 @@ void build_srat_pci_generic_initiator(GArray 
> *table_data, int node,
>                                        uint16_t segment, uint8_t bus,
>                                        uint8_t devfn);
>  
> +void build_srat_acpi_generic_port(GArray *table_data, int node,
> +                                  const char *hid,
> +                                  uint32_t uid);
> +
>  void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
>                  const char *oem_id, const char *oem_table_id);
>  
> diff --git a/include/hw/acpi/pci.h b/include/hw/acpi/pci.h
> index 3015a8171c..6359d574fd 100644
> --- a/include/hw/acpi/pci.h
> +++ b/include/hw/acpi/pci.h
> @@ -41,6 +41,6 @@ Aml *aml_pci_device_dsm(void);
>  void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus);
>  void build_pci_bridge_aml(AcpiDevAmlIf *adev, Aml *scope);
>  
> -void build_srat_generic_pci_initiator(GArray *table_data);
> +void build_srat_generic_affinity_structures(GArray *table_data);
>  
>  #endif
> diff --git a/include/hw/pci/pci_bridge.h b/include/hw/pci/pci_bridge.h
> index 5cd452115a..5456e24883 100644
> --- a/include/hw/pci/pci_bridge.h
> +++ b/include/hw/pci/pci_bridge.h
> @@ -102,6 +102,7 @@ typedef struct PXBPCIEDev {
>      PXBDev parent_obj;
>  } PXBPCIEDev;
>  
> +#define TYPE_PXB_CXL_BUS "pxb-cxl-bus"
>  #define TYPE_PXB_DEV "pxb"
>  OBJECT_DECLARE_SIMPLE_TYPE(PXBDev, PXB_DEV)
>  
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 968b654e58..4067100dd6 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -1955,6 +1955,19 @@ static void build_append_srat_pci_device_handle(GArray 
> *table_data,
>      build_append_int_noprefix(table_data, 0, 12);
>  }
>  
> +static void build_append_srat_acpi_device_handle(GArray *table_data,
> +                                                 const char *hid,
> +                                                 uint32_t uid)
> +{
> +    assert(strlen(hid) == 8);
> +    /* Device Handle - ACPI */
> +    for (int i = 0; i < sizeof(hid); i++) {
> +        build_append_int_noprefix(table_data, hid[i], 1);
> +    }
> +    build_append_int_noprefix(table_data, uid, 4);
> +    build_append_int_noprefix(table_data, 0, 4);
> +}
> +
>  /*
>   * ACPI spec, Revision 6.3
>   * 5.2.16.6 Generic Initiator Affinity Structure
> @@ -1982,6 +1995,33 @@ void build_srat_pci_generic_initiator(GArray 
> *table_data, int node,
>      build_append_int_noprefix(table_data, 0, 4);
>  }
>  
> +/*
> + * ACPI spec, Revision 6.5
> + * 5.2.16.7 Generic Port Affinity Structure
> + *   With ACPI Device Handle.
> + */
> +void build_srat_acpi_generic_port(GArray *table_data, int node,

shouldn't node be uint32_t?

> +                                  const char *hid,
> +                                  uint32_t uid)
> +{
> +    /* Type */
> +    build_append_int_noprefix(table_data, 6, 1);
> +    /* Length */
> +    build_append_int_noprefix(table_data, 32, 1);
> +    /* Reserved */
> +    build_append_int_noprefix(table_data, 0, 1);
> +    /* Device Handle Type: ACPI */
> +    build_append_int_noprefix(table_data, 0, 1);
> +    /* Proximity Domain */
> +    build_append_int_noprefix(table_data, node, 4);
> +    /* Device Handle */
> +    build_append_srat_acpi_device_handle(table_data, hid, uid);
> +    /* Flags - GP Enabled */
> +    build_append_int_noprefix(table_data, 1, 4);
> +    /* Reserved */
> +    build_append_int_noprefix(table_data, 0, 4);
> +}
> +
>  /*
>   * ACPI spec 5.2.17 System Locality Distance Information Table
>   * (Revision 2.0 or later)
> diff --git a/hw/acpi/pci.c b/hw/acpi/pci.c
> index 3e1db161cc..020ad53c03 100644
> --- a/hw/acpi/pci.c
> +++ b/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,118 @@ 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;
> +    uint16_t node;

ditto

> +} 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;

as long as gp->node is uint32_t it should be fine.
otherwise it's too fragile. 

> +}
> +
> +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_add(oc, "node", "int", NULL,
> +        acpi_generic_port_set_node, NULL, NULL);

missing property description calls.

> +}
> +
> +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);

not sure, 
maybe use error_fatal instead of using exit(1)?

CCing Markus to check if it's ok.


> +    }
> +
> +    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);
> +    }
ditto

> +
> +    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);
>  }
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index a50b00b7c1..d98651df55 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -510,7 +510,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
> VirtMachineState *vms)
>          }
>      }
>  
> -    build_srat_generic_pci_initiator(table_data);
> +    build_srat_generic_affinity_structures(table_data);
>  
>      if (ms->nvdimms_state->is_enabled) {
>          nvdimm_build_srat(table_data);
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 2eaa4c9203..7f5ca188c1 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -2048,7 +2048,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
> MachineState *machine)
>          build_srat_memory(table_data, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
>      }
>  
> -    build_srat_generic_pci_initiator(table_data);
> +    build_srat_generic_affinity_structures(table_data);
>  
>      /*
>       * Entry is required for Windows to enable memory hotplug in OS
> diff --git a/hw/pci-bridge/pci_expander_bridge.c 
> b/hw/pci-bridge/pci_expander_bridge.c
> index b94cb85cfb..cd7f2d5423 100644
> --- a/hw/pci-bridge/pci_expander_bridge.c
> +++ b/hw/pci-bridge/pci_expander_bridge.c
> @@ -38,7 +38,6 @@ DECLARE_INSTANCE_CHECKER(PXBBus, PXB_BUS,
>  DECLARE_INSTANCE_CHECKER(PXBBus, PXB_PCIE_BUS,
>                           TYPE_PXB_PCIE_BUS)
>  
> -#define TYPE_PXB_CXL_BUS "pxb-cxl-bus"
>  DECLARE_INSTANCE_CHECKER(PXBBus, PXB_CXL_BUS,
>                           TYPE_PXB_CXL_BUS)
>  




reply via email to

[Prev in Thread] Current Thread [Next in Thread]