ACPI: Adding support to parse the locality tables
authorReto Achermann <reto.achermann@inf.ethz.ch>
Thu, 4 Jun 2015 09:56:32 +0000 (11:56 +0200)
committerReto Achermann <reto.achermann@inf.ethz.ch>
Thu, 4 Jun 2015 09:58:00 +0000 (11:58 +0200)
added table definitions for the memory topology tables.

Signed-off-by: Reto Achermann <reto.achermann@inf.ethz.ch>

usr/acpi/acpi.c
usr/acpi/acpica/include/actbl1.h

index 472f835..36bcbe6 100644 (file)
@@ -656,6 +656,8 @@ static ACPI_STATUS set_apic_mode(void)
 
 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);
 
@@ -736,8 +738,95 @@ static void process_srat(ACPI_TABLE_SRAT *srat)
             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;
@@ -819,11 +908,54 @@ int init_acpi(void)
     //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;
 }
index 8af7a18..592349f 100644 (file)
 #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 */
@@ -1138,6 +1139,112 @@ typedef struct acpi_srat_x2apic_cpu_affinity
 #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()