@@ -67,11 +67,81 @@ static void build_hmat_mpda(GArray *table_data, uint16_t flags, int initiator,
build_append_int_noprefix(table_data, 0, 8);
}
+/*
+ * ACPI 6.3: 5.2.27.4 System Locality Latency and Bandwidth Information
+ * Structure: Table 5-142
+ */
+static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
+ uint32_t num_initiator, uint32_t num_target,
+ uint32_t *initiator_pxm, int type)
+{
+ uint32_t s = num_initiator;
+ uint32_t t = num_target;
+ uint8_t m, n;
+ uint8_t mask = 0x0f;
+ int i;
+
+ /* Type */
+ build_append_int_noprefix(table_data, 1, 2);
+ /* Reserved */
+ build_append_int_noprefix(table_data, 0, 2);
+ /* Length */
+ build_append_int_noprefix(table_data, 32 + 4 * s + 4 * t + 2 * s * t, 4);
+ /* Flags: Bits [3:0] Memory Hierarchy, Bits[7:4] Reserved */
+ build_append_int_noprefix(table_data, hmat_lb->hierarchy & mask, 1);
+ /* Data Type */
+ build_append_int_noprefix(table_data, hmat_lb->data_type, 1);
+ /* Reserved */
+ build_append_int_noprefix(table_data, 0, 2);
+ /* Number of Initiator Proximity Domains (s) */
+ build_append_int_noprefix(table_data, s, 4);
+ /* Number of Target Proximity Domains (t) */
+ build_append_int_noprefix(table_data, t, 4);
+ /* Reserved */
+ build_append_int_noprefix(table_data, 0, 4);
+
+ /* Entry Base Unit */
+ if (HMAT_IS_LATENCY(type)) {
+ build_append_int_noprefix(table_data, hmat_lb->base_lat, 8);
+ } else {
+ build_append_int_noprefix(table_data, hmat_lb->base_bw, 8);
+ }
+
+ /* Initiator Proximity Domain List */
+ for (i = 0; i < s; i++) {
+ build_append_int_noprefix(table_data, initiator_pxm[i], 4);
+ }
+
+ /* Target Proximity Domain List */
+ for (i = 0; i < t; i++) {
+ build_append_int_noprefix(table_data, i, 4);
+ }
+
+ /* Latency or Bandwidth Entries */
+ for (i = 0; i < s; i++) {
+ m = initiator_pxm[i];
+ for (n = 0; n < t; n++) {
+ uint16_t entry;
+
+ if (HMAT_IS_LATENCY(type)) {
+ entry = hmat_lb->latency[m][n];
+ } else {
+ entry = hmat_lb->bandwidth[m][n];
+ }
+
+ build_append_int_noprefix(table_data, entry, 2);
+ }
+ }
+}
+
/* Build HMAT sub table structures */
static void hmat_build_table_structs(GArray *table_data, NumaState *nstat)
{
uint16_t flags;
- int i;
+ uint32_t num_initiator = 0;
+ uint32_t initiator_pxm[MAX_NODES];
+ int i, hrchy, type;
+ HMAT_LB_Info *numa_hmat_lb;
for (i = 0; i < nstat->num_nodes; i++) {
flags = 0;
@@ -82,6 +152,29 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *nstat)
build_hmat_mpda(table_data, flags, nstat->nodes[i].initiator, i);
}
+
+ for (i = 0; i < nstat->num_nodes; i++) {
+ if (nstat->nodes[i].has_cpu) {
+ initiator_pxm[num_initiator++] = i;
+ }
+ }
+
+ /*
+ * ACPI 6.3: 5.2.27.4 System Locality Latency and Bandwidth Information
+ * Structure: Table 5-142
+ */
+ for (hrchy = HMAT_LB_MEM_MEMORY;
+ hrchy <= HMAT_LB_MEM_CACHE_3RD_LEVEL; hrchy++) {
+ for (type = HMAT_LB_DATA_ACCESS_LATENCY;
+ type <= HMAT_LB_DATA_WRITE_BANDWIDTH; type++) {
+ numa_hmat_lb = nstat->hmat_lb[hrchy][type];
+
+ if (numa_hmat_lb) {
+ build_hmat_lb(table_data, numa_hmat_lb, num_initiator,
+ nstat->num_nodes, initiator_pxm, type);
+ }
+ }
+ }
}
void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *nstat)
@@ -40,6 +40,47 @@
*/
#define HMAT_PROX_INIT_VALID 0x1
+#define HMAT_IS_LATENCY(type) (type <= HMAT_LB_DATA_WRITE_LATENCY)
+
+struct HMAT_LB_Info {
+ /*
+ * Indicates total number of Proximity Domains
+ * that can initiate memory access requests.
+ */
+ uint32_t num_initiator;
+ /*
+ * Indicates total number of Proximity Domains
+ * that can act as target.
+ */
+ uint32_t num_target;
+ /*
+ * Indicates it's memory or
+ * the specified level memory side cache.
+ */
+ uint8_t hierarchy;
+ /*
+ * Present the type of data,
+ * access/read/write latency or bandwidth.
+ */
+ uint8_t data_type;
+ /* The base unit for latency in nanoseconds. */
+ uint64_t base_lat;
+ /* The base unit for bandwidth in megabytes per second(MB/s). */
+ uint64_t base_bw;
+ /*
+ * latency[i][j]:
+ * Indicates the latency based on base_lat
+ * from Initiator Proximity Domain i to Target Proximity Domain j.
+ */
+ uint16_t latency[MAX_NODES][MAX_NODES];
+ /*
+ * bandwidth[i][j]:
+ * Indicates the bandwidth based on base_bw
+ * from Initiator Proximity Domain i to Target Proximity Domain j.
+ */
+ uint16_t bandwidth[MAX_NODES][MAX_NODES];
+};
+
void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *nstat);
#endif
@@ -33,6 +33,7 @@ typedef struct FWCfgEntry FWCfgEntry;
typedef struct FWCfgIoState FWCfgIoState;
typedef struct FWCfgMemState FWCfgMemState;
typedef struct FWCfgState FWCfgState;
+typedef struct HMAT_LB_Info HMAT_LB_Info;
typedef struct HVFX86EmulatorState HVFX86EmulatorState;
typedef struct I2CBus I2CBus;
typedef struct I2SCodec I2SCodec;
@@ -30,6 +30,9 @@ struct NumaState {
/* NUMA nodes information */
NodeInfo nodes[MAX_NODES];
+
+ /* NUMA modes HMAT Locality Latency and Bandwidth Information */
+ HMAT_LB_Info *hmat_lb[HMAT_LB_LEVELS][HMAT_LB_TYPES];
};
typedef struct NumaState NumaState;
@@ -126,6 +126,27 @@ extern int mem_prealloc;
#define NUMA_DISTANCE_MAX 254
#define NUMA_DISTANCE_UNREACHABLE 255
+/* the value of AcpiHmatLBInfo flags */
+enum {
+ HMAT_LB_MEM_MEMORY = 0,
+ HMAT_LB_MEM_CACHE_1ST_LEVEL = 1,
+ HMAT_LB_MEM_CACHE_2ND_LEVEL = 2,
+ HMAT_LB_MEM_CACHE_3RD_LEVEL = 3,
+};
+
+/* the value of AcpiHmatLBInfo data type */
+enum {
+ HMAT_LB_DATA_ACCESS_LATENCY = 0,
+ HMAT_LB_DATA_READ_LATENCY = 1,
+ HMAT_LB_DATA_WRITE_LATENCY = 2,
+ HMAT_LB_DATA_ACCESS_BANDWIDTH = 3,
+ HMAT_LB_DATA_READ_BANDWIDTH = 4,
+ HMAT_LB_DATA_WRITE_BANDWIDTH = 5,
+};
+
+#define HMAT_LB_LEVELS (HMAT_LB_MEM_CACHE_3RD_LEVEL + 1)
+#define HMAT_LB_TYPES (HMAT_LB_DATA_WRITE_BANDWIDTH + 1)
+
#define MAX_OPTION_ROMS 16
typedef struct QEMUOptionRom {
const char *name;