static void process_srat(ACPI_TABLE_SRAT *srat)
{
+ ACPI_DEBUG("processing system resource affinity table...\n");
+
assert(!strncmp(srat->Header.Signature, "SRAT", ACPI_NAME_SIZE));
assert(srat->TableRevision == 1);
break;
}
}
+
+ ACPI_DEBUG("done processing srat...\n");
}
+/**
+ * \brief parses the system locality distance table.
+ *
+ * \param slit pointer to the SLIT table in memory
+ *
+ * This optional table provides a matrix that describes the relative distance
+ * (memory latency) between all System Localities, which are also referred to as
+ * Proximity Domains
+ */
+static void process_slit(ACPI_TABLE_SLIT *slit)
+{
+ ACPI_DEBUG("processing system locality distance table...\n");
+
+ assert(!strncmp(slit->Header.Signature, ACPI_SIG_SLIT, ACPI_NAME_SIZE));
+ assert(slit->Header.Revision == 1);
+
+ UINT64 locality_count = slit->LocalityCount;
+
+ for (UINT64 i = 0; i < locality_count; ++i) {
+ for (UINT64 j = 0; j < locality_count; ++j) {
+ /*
+ * The diagonal elements of the matrix, the relative distances from a
+ * System Locality to itself are normalized to a value of 10. The
+ * relative distances for the non-diagonal elements are scaled to be
+ * relative to 10
+ */
+ UINT8 entry = slit->Entry[i*locality_count + j];
+ skb_add_fact("node_distance(%" PRIu64 ", %" PRIu64 ", %"PRIu8").", i,
+ j, entry);
+ assert(j!=i || entry == 10);
+ ACPI_DEBUG("locality: %lu -> %lu = %u\n", i, j, entry);
+ }
+ }
+
+ ACPI_DEBUG("done processing slit\n");
+}
+
+/**
+ * \brief parses the Memory Topology Table.
+ *
+ * \param slit pointer to the PMTT table in memory
+ *
+ * This optional table provides a matrix that describes the relative distance
+ * (memory latency) between all System Localities, which are also referred to as
+ * Proximity Domains
+ */
+static void process_pmtt(ACPI_TABLE_PMTT *pmtt)
+{
+ ACPI_DEBUG("processing Platform Memory Topology Table....\n");
+
+ assert(!strncmp(pmtt->Header.Signature, ACPI_SIG_PMTT, ACPI_NAME_SIZE));
+ assert(pmtt->Header.Revision == 1);
+
+ void *pos = (void *)pmtt + ACPI_PMTT_OFFSET;
+
+ // Scan subtables
+ while(pos < (void *)pmtt + pmtt->Header.Length) {
+
+ ACPI_PMTT_CMADS *shead = pos;
+ switch(shead->Type) {
+ case ACPI_PMTT_CMAD_TYPE_SOCKET:
+ ACPI_DEBUG("pmtt socket table\n");
+
+ pos += ACPI_PMTT_MEMCTRL_OFFSET;
+ break;
+ case ACPI_PMTT_CMAD_TYPE_MEMCTRL:
+ ACPI_DEBUG("pmtt memory controller table\n");
+ ACPI_PMTT_MEMCTRL *mctrl = pos;
+ pos += ACPI_PMTT_DIMM_OFSET(mctrl->NumProximityDomains);
+ break;
+ case ACPI_PMTT_CMAD_TYPE_DIMM:
+
+ pos += sizeof(ACPI_PMTT_DIMM);
+ break;
+ default:
+ ACPI_DEBUG("WARNING: invalid type %u\n", shead->Type);
+ break;
+ }
+ }
+
+
+ ACPI_DEBUG("done processing pmtt.\n");
+}
+
+
int init_acpi(void)
{
ACPI_STATUS as;
//pci_program_bridges();
//ACPI_DEBUG("PCI programming completed\n");
- ACPI_TABLE_HEADER *srat_header;
- as = AcpiGetTable("SRAT", 1, &srat_header);
+ ACPI_TABLE_HEADER *acpi_table_header;
+
+ as = AcpiGetTable(ACPI_SIG_SRAT, 1, &acpi_table_header);
+ ACPI_DEBUG("has SRAT: %s.\n", ACPI_SUCCESS(as) ? "yes" : "no");
if(ACPI_SUCCESS(as)) {
- process_srat((ACPI_TABLE_SRAT *)srat_header);
+ process_srat((ACPI_TABLE_SRAT *)acpi_table_header);
}
+ /*
+ * try to parse the SLIT. This is an optional table
+ */
+ as = AcpiGetTable(ACPI_SIG_SLIT, 1, &acpi_table_header);
+ ACPI_DEBUG("has SLIT: %s.\n", ACPI_SUCCESS(as) ? "yes" : "no");
+ if(ACPI_SUCCESS(as)) {
+ process_slit((ACPI_TABLE_SLIT *)acpi_table_header);
+ }
+
+ /*
+ * try to parse the PMTT. This is an optional table
+ */
+ as = AcpiGetTable(ACPI_SIG_PMTT, 1, &acpi_table_header);
+ ACPI_DEBUG("has PMTT: %s.\n", ACPI_SUCCESS(as) ? "yes" : "no");
+ if(ACPI_SUCCESS(as)) {
+ process_pmtt((ACPI_TABLE_PMTT *)acpi_table_header);
+ }
+
+ /*
+ * try to parse the PSDT. This is an optional table
+ */
+ as = AcpiGetTable(ACPI_SIG_PSDT, 1, &acpi_table_header);
+ ACPI_DEBUG("has PSDT: %s.\n", ACPI_SUCCESS(as) ? "yes" : "no");
+
+ /*
+ * try to parse the RSDT. This is an optional table
+ */
+ as = AcpiGetTable(ACPI_SIG_RSDT, 1, &acpi_table_header);
+ ACPI_DEBUG("has RSDT: %s.\n", ACPI_SUCCESS(as) ? "yes" : "no");
+
+ /*
+ * try to parse the SSDT. This is an optional table
+ */
+ as = AcpiGetTable(ACPI_SIG_SSDT, 1, &acpi_table_header);
+ ACPI_DEBUG("has SSDT: %s.\n", ACPI_SUCCESS(as) ? "yes" : "no");
+
+ /*
+ * try to parse the XSDT. This is an optional table
+ */
+ as = AcpiGetTable(ACPI_SIG_XSDT, 1, &acpi_table_header);
+ ACPI_DEBUG("has XSDT: %s.\n", ACPI_SUCCESS(as) ? "yes" : "no");
return 0;
}
#define ACPI_SIG_HEST "HEST" /* Hardware Error Source Table */
#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */
#define ACPI_SIG_MSCT "MSCT" /* Maximum System Characteristics Table */
+#define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */
#define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */
#define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */
#define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */
#define ACPI_SRAT_CPU_ENABLED (1) /* 00: Use affinity structure */
+/*******************************************************************************
+ *
+ * PMTT - Platform Memory Topology Table
+ *
+ ******************************************************************************/
+/**
+ * Table 5-92 Common Memory Aggregator Device Structure
+ */
+typedef struct acpi_pmtt_cmads
+{
+ UINT8 Type; /* The field describes type of the Memory Aggregator Device. */
+ UINT8 Reserved; /* Reserved, must be zero. */
+ UINT16 Length; /* Length in bytes for this Structure. */
+ UINT16 Flags; /* see ACPI_PMTT_CMAD_FLAG_* */
+ UINT16 Reserved2; /* Reserved, must be zero. */
+} ACPI_PMTT_CMADS;
+
+/* The field describes type of the Memory Aggregator Device. */
+#define ACPI_PMTT_CMAD_TYPE_SOCKET 0
+#define ACPI_PMTT_CMAD_TYPE_MEMCTRL 1
+#define ACPI_PMTT_CMAD_TYPE_DIMM 2
+
+/* ACPI PMTT CMAD flags */
+#define ACPI_PMTT_CMAD_FLAG_LEVEL_MASK (1 << 0)
+#define ACPI_PMTT_CMAD_FLAG_LEVEL_TOP (1 << 0)
+#define ACPI_PMTT_CMAD_FLAG_ELEM_MASK (1 << 1)
+#define ACPI_PMTT_CMAD_FLAG_ELEM_PHYSICAL (1 << 1)
+#define ACPI_PMTT_CMAD_FLAG_ELEM_LOGICAL (0 << 1)
+#define ACPI_PMTT_CMAD_FLAG_TYPE_MASK (3 << 2)
+#define ACPI_PMTT_CMAD_FLAG_TYPE_VOLATILE (2 << 2)
+#define ACPI_PMTT_CMAD_FLAG_TYPE_NVOLATIL (1 << 2)
+#define ACPI_PMTT_CMAD_FLAG_TYPE_BOTH (0 << 2)
+
+/**
+ * Table 5-95 Physical Components Identifier Structure
+ */
+typedef struct acpi_pmtt_dimm
+{
+ ACPI_PMTT_CMADS Header; /* common header for the PMTT tables */
+ UINT16 PhysicalComponentID; /* Uniquely identifies the physical memory component in the system */
+ UINT16 Reserved;
+ UINT32 SizeOfDIMM; /* Size in MB of the DIMM device */
+ UINT32 SMBIOSHandle; /* Refers to Type 17 table handle of corresponding SMBIOS record. */
+} ACPI_PMTT_DIMM;
+
+#define ACPI_PMTT_DIMM_SMBIOS_NOT_VALID 0xFFFFFFFF
+
+/**
+ * Table 5-94 Memory Controller Structure
+ */
+typedef struct acpi_pmtt_memctrl
+{
+ ACPI_PMTT_CMADS Header; /* common header for the PMTT tables */
+ UINT32 ReadLatency; /* [ns] as seen at the controller for a cacheline. */
+ UINT32 WriteLatency; /* [ns] as seen at the controller for a cacheline. */
+ UINT32 ReadBandwith; /* [MB/s] */
+ UINT32 WriteBandwidth; /* [MB/s] */
+ UINT16 OptAccessUnit; /* [Bytes] */
+ UINT16 OptAccessAlign; /* [Bytes] */
+ UINT16 Reserved;
+ UINT16 NumProximityDomains; /* Number of Proximity Domains that immediately follow. */
+ UINT32 ProximityDomains[]; /* Proximity domains for memory address space(s) spawned by this memory controller */
+} ACPI_PMTT_MEMCTRL;
+
+#define ACPI_PMTT_PCIS_OFFSET(memctrl) \
+ (memctrl->ProximityDomains[memctrl->NumProximityDomains])
+
+#define ACPI_PMTT_DIMM_OFSET(M) (32 + (4 * M))
+
+/**
+ * Table 5-93 Socket Structure
+ */
+typedef struct acpi_pmtt_socket
+{
+ ACPI_PMTT_CMADS Header; /* common header for the PMTT tables */
+ UINT16 Reserved; /* Reserved, must be zero. */
+ UINT16 SockedIdentifier; /* Uniquely identifies the socket in the system. */
+ UINT16 Reserved2; /* Reserved, must be zero. */
+ ACPI_PMTT_MEMCTRL memctrl[]; /* A list of Memory Controller Structures. */
+} ACPI_PMTT_SOCKET;
+
+#define ACPI_PMTT_PCIS_OFFSET(memctrl) \
+ (memctrl->ProximityDomains[memctrl->NumProximityDomains])
+
+#define ACPI_PMTT_MEMCTRL_OFFSET 12
+
+/*
+ * NOTE:
+ * Length in bytes of the entire PMTT. The length implies the number of Memory
+ * Aggregator structures at the end of the table.
+ */
+
+
+/**
+ * Table 5-91 Platform Memory Topology Table
+ */
+typedef struct acpi_table_pmtt
+{
+ ACPI_TABLE_HEADER Header; /* Common ACPI table header */
+ UINT64 Reserved; /* Reserved, must be zero */
+ ACPI_PMTT_CMADS mads[]; /* A list of memory aggregator device structures. */
+} ACPI_TABLE_PMTT;
+
+#define ACPI_PMTT_OFFSET 8
+
+
/* Reset to default packing */
#pragma pack()