acpi: add SRAT Generic Initiator Affinity structure

Generic Initiator Affinity structure is introdcued in ACPI spec 6.3.

This structure is used to define NUMA affinity domain which is
established by generic initiator (such as by CXL device).

Signed-off-by: Jonathan Zhang <jonzhang@fb.com>
Change-Id: Ic6ef01c59e02f30dc290f27e741027e16f5d8359
Reviewed-on: https://review.coreboot.org/c/coreboot/+/52734
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Lance Zhao
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c
index 6c1828a..0874e6e 100644
--- a/src/acpi/acpi.c
+++ b/src/acpi/acpi.c
@@ -508,6 +508,23 @@
 	return mem->length;
 }
 
+int acpi_create_srat_gia_pci(acpi_srat_gia_t *gia, u32 proximity_domain,
+				u16 seg, u8 bus, u8 dev, u8 func, u32 flags)
+{
+	gia->type = ACPI_SRAT_STRUCTURE_GIA;
+	gia->length = sizeof(acpi_srat_gia_t);
+	gia->proximity_domain = proximity_domain;
+	gia->dev_handle_type = ACPI_SRAT_GIA_DEV_HANDLE_PCI;
+	/* First two bytes has segment number */
+	memcpy(gia->dev_handle, &seg, 2);
+	gia->dev_handle[2] = bus; /* Byte 2 has bus number */
+	/* Byte 3 has bits 7:3 for dev, bits 2:0 for func */
+	gia->dev_handle[3] = PCI_SLOT(dev) | PCI_FUNC(func);
+	gia->flags = flags;
+
+	return gia->length;
+}
+
 /* http://www.microsoft.com/whdc/system/sysinternals/sratdwn.mspx */
 void acpi_create_srat(acpi_srat_t *srat,
 		      unsigned long (*acpi_fill_srat)(unsigned long current))
diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h
index 6aa6cb8..d5e933b 100644
--- a/src/include/acpi/acpi.h
+++ b/src/include/acpi/acpi.h
@@ -281,6 +281,10 @@
 	/* Followed by static resource allocation structure[n] */
 } __packed acpi_srat_t;
 
+#define ACPI_SRAT_STRUCTURE_LAPIC 0
+#define ACPI_SRAT_STRUCTURE_MEM   1
+#define ACPI_SRAT_STRUCTURE_GIA   5
+
 /* SRAT: Processor Local APIC/SAPIC Affinity Structure */
 typedef struct acpi_srat_lapic {
 	u8 type;			/* Type (0) */
@@ -310,6 +314,21 @@
 	u32 resv2[2];
 } __packed acpi_srat_mem_t;
 
+/* SRAT: Generic Initiator Affinity Structure (ACPI spec 6.4 section 5.2.16.6) */
+typedef struct acpi_srat_gia {
+	u8 type;		/* Type (5) */
+	u8 length;		/* Length in bytes (32) */
+	u8 resv;
+	u8 dev_handle_type;	/* Device handle type */
+	u32 proximity_domain;	/*Proximity domain */
+	u8 dev_handle[16];	/* Device handle */
+	u32 flags;
+	u32 resv1;
+} __packed acpi_srat_gia_t;
+
+#define ACPI_SRAT_GIA_DEV_HANDLE_ACPI 0
+#define ACPI_SRAT_GIA_DEV_HANDLE_PCI  1
+
 /* SLIT (System Locality Distance Information Table) */
 typedef struct acpi_slit {
 	acpi_header_t header;
@@ -1218,6 +1237,12 @@
 int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic);
 int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek, u32 sizek,
 			 u32 flags);
+/*
+ * Given the Generic Initiator device's BDF, the proximity domain's ID
+ * and flag, create Generic Initiator Affinity structure in SRAT.
+ */
+int acpi_create_srat_gia_pci(acpi_srat_gia_t *gia, u32 proximity_domain,
+		u16 seg, u8 bus, u8 dev, u8 func, u32 flags);
 int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base,
 			      u16 seg_nr, u8 start, u8 end);
 unsigned long acpi_create_srat_lapics(unsigned long current);