@@ -57,6 +57,74 @@ static void build_hmat_spa(GArray *table_data, uint16_t flags,
build_append_int_noprefix(table_data, length, 8);
}
+/*
+ * ACPI 6.2: 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 *numa_hmat_lb,
+ uint32_t num_initiator, uint32_t num_target,
+ uint32_t *initiator_pxm, uint32_t *target_pxm,
+ int type)
+{
+ uint32_t s = num_initiator;
+ uint32_t t = num_target;
+ uint8_t m, n;
+ int i, j;
+
+ /* 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 */
+ build_append_int_noprefix(table_data, numa_hmat_lb->hierarchy, 1);
+ /* Data Type */
+ build_append_int_noprefix(table_data, numa_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 (type <= HMAT_LB_DATA_WRITE_LATENCY) {
+ build_append_int_noprefix(table_data, numa_hmat_lb->base_lat, 8);
+ } else {
+ build_append_int_noprefix(table_data, numa_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, target_pxm[i], 4);
+ }
+
+ /* Latency or Bandwidth Entries */
+ for (i = 0; i < s; i++) {
+ m = initiator_pxm[i];
+ for (j = 0; j < t; j++) {
+ n = target_pxm[j];
+ uint16_t entry;
+
+ if (type <= HMAT_LB_DATA_WRITE_LATENCY) {
+ entry = numa_hmat_lb->latency[m][n] * numa_hmat_lb->base_lat;
+ } else {
+ entry = numa_hmat_lb->bandwidth[m][n] * numa_hmat_lb->base_bw;
+ }
+
+ build_append_int_noprefix(table_data, entry, 2);
+ }
+ }
+}
+
static int pc_dimm_device_list(Object *obj, void *opaque)
{
GSList **list = opaque;
@@ -77,10 +145,13 @@ static void hmat_build_table_structs(GArray *table_data, MachineState *ms)
{
GSList *device_list = NULL;
uint16_t flags;
+ uint32_t num_initiator = 0, num_target = 0;
+ uint32_t initiator_pxm[MAX_NODES], target_pxm[MAX_NODES];
uint64_t mem_base, mem_len;
- int i;
+ int i, hrchy, type;
NumaState *nstat = ms->numa_state;
NumaMemRange *mem_range;
+ HMAT_LB_Info *numa_hmat_lb;
Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, NULL);
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
@@ -134,6 +205,34 @@ static void hmat_build_table_structs(GArray *table_data, MachineState *ms)
}
build_hmat_spa(table_data, flags, mem_base, mem_len, i);
}
+
+ if (!num_initiator && !num_target) {
+ for (i = 0; i < nstat->num_nodes; i++) {
+ if (nstat->nodes[i].is_initiator) {
+ initiator_pxm[num_initiator++] = i;
+ }
+ if (nstat->nodes[i].is_target) {
+ target_pxm[num_target++] = i;
+ }
+ }
+ }
+
+ /*
+ * ACPI 6.2: 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,
+ num_target, initiator_pxm, target_pxm, type);
+ }
+ }
+ }
}
void build_hmat(GArray *table_data, BIOSLinker *linker, MachineState *ms)
@@ -38,6 +38,45 @@ enum {
HMAT_SPA_RESERVATION_HINT = 0x4,
};
+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, MachineState *ms);
#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;
@@ -43,6 +43,9 @@ struct NumaState {
/* NUMA memory ranges */
GArray *mem_ranges;
+
+ /* NUMA modes HMAT Locality Latency and Bandwidth Information */
+ HMAT_LB_Info *hmat_lb[HMAT_LB_LEVELS][HMAT_LB_TYPES];
};
typedef struct NumaState NumaState;
@@ -124,6 +124,30 @@ 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_LAST_LEVEL = 1,
+ HMAT_LB_MEM_CACHE_1ST_LEVEL = 2,
+ HMAT_LB_MEM_CACHE_2ND_LEVEL = 3,
+ HMAT_LB_MEM_CACHE_3RD_LEVEL = 4,
+};
+
+/* 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 MAX_HMAT_CACHE_LEVEL 3
+
+#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;