1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved
6 #include "qemu/osdep.h"
7 #include "hw/acpi/acpi_generic_initiator.h"
8 #include "hw/acpi/aml-build.h"
10 #include "hw/pci/pci_device.h"
11 #include "qemu/error-report.h"
13 typedef struct AcpiGenericInitiatorClass
{
14 ObjectClass parent_class
;
15 } AcpiGenericInitiatorClass
;
17 OBJECT_DEFINE_TYPE_WITH_INTERFACES(AcpiGenericInitiator
, acpi_generic_initiator
,
18 ACPI_GENERIC_INITIATOR
, OBJECT
,
19 { TYPE_USER_CREATABLE
},
22 OBJECT_DECLARE_SIMPLE_TYPE(AcpiGenericInitiator
, ACPI_GENERIC_INITIATOR
)
24 static void acpi_generic_initiator_init(Object
*obj
)
26 AcpiGenericInitiator
*gi
= ACPI_GENERIC_INITIATOR(obj
);
32 static void acpi_generic_initiator_finalize(Object
*obj
)
34 AcpiGenericInitiator
*gi
= ACPI_GENERIC_INITIATOR(obj
);
39 static void acpi_generic_initiator_set_pci_device(Object
*obj
, const char *val
,
42 AcpiGenericInitiator
*gi
= ACPI_GENERIC_INITIATOR(obj
);
44 gi
->pci_dev
= g_strdup(val
);
47 static void acpi_generic_initiator_set_node(Object
*obj
, Visitor
*v
,
48 const char *name
, void *opaque
,
51 AcpiGenericInitiator
*gi
= ACPI_GENERIC_INITIATOR(obj
);
52 MachineState
*ms
= MACHINE(qdev_get_machine());
55 if (!visit_type_uint32(v
, name
, &value
, errp
)) {
59 if (value
>= MAX_NODES
) {
60 error_printf("%s: Invalid NUMA node specified\n",
61 TYPE_ACPI_GENERIC_INITIATOR
);
66 ms
->numa_state
->nodes
[gi
->node
].has_gi
= true;
69 static void acpi_generic_initiator_class_init(ObjectClass
*oc
, void *data
)
71 object_class_property_add_str(oc
, "pci-dev", NULL
,
72 acpi_generic_initiator_set_pci_device
);
73 object_class_property_add(oc
, "node", "int", NULL
,
74 acpi_generic_initiator_set_node
, NULL
, NULL
);
79 * Table 5-78 Generic Initiator Affinity Structure
82 build_srat_generic_pci_initiator_affinity(GArray
*table_data
, int node
,
83 PCIDeviceHandle
*handle
)
87 build_append_int_noprefix(table_data
, 5, 1); /* Type */
88 build_append_int_noprefix(table_data
, 32, 1); /* Length */
89 build_append_int_noprefix(table_data
, 0, 1); /* Reserved */
90 build_append_int_noprefix(table_data
, 1, 1); /* Device Handle Type: PCI */
91 build_append_int_noprefix(table_data
, node
, 4); /* Proximity Domain */
93 /* Device Handle - PCI */
94 build_append_int_noprefix(table_data
, handle
->segment
, 2);
95 build_append_int_noprefix(table_data
, handle
->bdf
, 2);
96 for (index
= 0; index
< 12; index
++) {
97 build_append_int_noprefix(table_data
, 0, 1);
100 build_append_int_noprefix(table_data
, GEN_AFFINITY_ENABLED
, 4); /* Flags */
101 build_append_int_noprefix(table_data
, 0, 4); /* Reserved */
104 static int build_all_acpi_generic_initiators(Object
*obj
, void *opaque
)
106 MachineState
*ms
= MACHINE(qdev_get_machine());
107 AcpiGenericInitiator
*gi
;
108 GArray
*table_data
= opaque
;
109 PCIDeviceHandle dev_handle
;
113 if (!object_dynamic_cast(obj
, TYPE_ACPI_GENERIC_INITIATOR
)) {
117 gi
= ACPI_GENERIC_INITIATOR(obj
);
118 if (gi
->node
>= ms
->numa_state
->num_nodes
) {
119 error_printf("%s: Specified node %d is invalid.\n",
120 TYPE_ACPI_GENERIC_INITIATOR
, gi
->node
);
124 o
= object_resolve_path_type(gi
->pci_dev
, TYPE_PCI_DEVICE
, NULL
);
126 error_printf("%s: Specified device must be a PCI device.\n",
127 TYPE_ACPI_GENERIC_INITIATOR
);
131 pci_dev
= PCI_DEVICE(o
);
133 dev_handle
.segment
= 0;
134 dev_handle
.bdf
= PCI_BUILD_BDF(pci_bus_num(pci_get_bus(pci_dev
)),
137 build_srat_generic_pci_initiator_affinity(table_data
,
138 gi
->node
, &dev_handle
);
143 void build_srat_generic_pci_initiator(GArray
*table_data
)
145 object_child_foreach_recursive(object_get_root(),
146 build_all_acpi_generic_initiators
,