27
#include "qemu/osdep.h"
28
#include "qemu/units.h"
29
#include "sysemu/numa.h"
30
#include "hw/acpi/aml-build.h"
31
#include "hw/acpi/hmat.h"
37
static void build_hmat_mpda(GArray *table_data, uint16_t flags,
38
uint32_t initiator, uint32_t mem_node)
43
build_append_int_noprefix(table_data, 0, 2);
45
build_append_int_noprefix(table_data, 0, 2);
47
build_append_int_noprefix(table_data, 40, 4);
49
build_append_int_noprefix(table_data, flags, 2);
51
build_append_int_noprefix(table_data, 0, 2);
53
build_append_int_noprefix(table_data, initiator, 4);
55
build_append_int_noprefix(table_data, mem_node, 4);
57
build_append_int_noprefix(table_data, 0, 4);
63
build_append_int_noprefix(table_data, 0, 8);
69
build_append_int_noprefix(table_data, 0, 8);
76
static void build_hmat_lb(GArray *table_data, HMAT_LB_Info *hmat_lb,
77
uint32_t num_initiator, uint32_t num_target,
78
uint32_t *initiator_list)
81
uint32_t initiator_to_index[MAX_NODES] = {};
82
HMAT_LB_Data *lb_data;
90
+ 2 * num_initiator * num_target;
93
build_append_int_noprefix(table_data, 1, 2);
95
build_append_int_noprefix(table_data, 0, 2);
97
build_append_int_noprefix(table_data, lb_length, 4);
99
assert(!(hmat_lb->hierarchy >> 4));
100
build_append_int_noprefix(table_data, hmat_lb->hierarchy, 1);
102
build_append_int_noprefix(table_data, hmat_lb->data_type, 1);
104
build_append_int_noprefix(table_data, 0, 2);
106
build_append_int_noprefix(table_data, num_initiator, 4);
108
build_append_int_noprefix(table_data, num_target, 4);
110
build_append_int_noprefix(table_data, 0, 4);
113
if (hmat_lb->data_type <= HMAT_LB_DATA_WRITE_LATENCY) {
115
base = hmat_lb->base * 1000;
118
base = hmat_lb->base / MiB;
120
build_append_int_noprefix(table_data, base, 8);
123
for (i = 0; i < num_initiator; i++) {
124
build_append_int_noprefix(table_data, initiator_list[i], 4);
126
initiator_to_index[initiator_list[i]] = i;
130
for (i = 0; i < num_target; i++) {
131
build_append_int_noprefix(table_data, i, 4);
135
entry_list = g_new0(uint16_t, num_initiator * num_target);
136
for (i = 0; i < hmat_lb->list->len; i++) {
137
lb_data = &g_array_index(hmat_lb->list, HMAT_LB_Data, i);
138
index = initiator_to_index[lb_data->initiator] * num_target +
141
entry_list[index] = (uint16_t)(lb_data->data / hmat_lb->base);
144
for (i = 0; i < num_initiator * num_target; i++) {
145
build_append_int_noprefix(table_data, entry_list[i], 2);
152
static void build_hmat_cache(GArray *table_data, uint8_t total_levels,
153
NumaHmatCacheOptions *hmat_cache)
159
uint32_t cache_attr = total_levels;
162
cache_attr |= (uint32_t) hmat_cache->level << 4;
165
cache_attr |= (uint32_t) hmat_cache->associativity << 8;
168
cache_attr |= (uint32_t) hmat_cache->policy << 12;
171
cache_attr |= (uint32_t) hmat_cache->line << 16;
174
build_append_int_noprefix(table_data, 2, 2);
176
build_append_int_noprefix(table_data, 0, 2);
178
build_append_int_noprefix(table_data, 32, 4);
180
build_append_int_noprefix(table_data, hmat_cache->node_id, 4);
182
build_append_int_noprefix(table_data, 0, 4);
184
build_append_int_noprefix(table_data, hmat_cache->size, 8);
186
build_append_int_noprefix(table_data, cache_attr, 4);
188
build_append_int_noprefix(table_data, 0, 2);
195
build_append_int_noprefix(table_data, 0, 2);
199
static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state)
202
uint32_t num_initiator = 0;
203
uint32_t initiator_list[MAX_NODES];
204
int i, hierarchy, type, cache_level, total_levels;
205
HMAT_LB_Info *hmat_lb;
206
NumaHmatCacheOptions *hmat_cache;
208
build_append_int_noprefix(table_data, 0, 4);
210
for (i = 0; i < numa_state->num_nodes; i++) {
215
if (!numa_state->nodes[i].node_mem) {
220
if (numa_state->nodes[i].initiator < MAX_NODES) {
221
flags |= HMAT_PROXIMITY_INITIATOR_VALID;
224
build_hmat_mpda(table_data, flags, numa_state->nodes[i].initiator, i);
227
for (i = 0; i < numa_state->num_nodes; i++) {
228
if (numa_state->nodes[i].has_cpu || numa_state->nodes[i].has_gi) {
229
initiator_list[num_initiator++] = i;
237
for (hierarchy = HMAT_LB_MEM_MEMORY;
238
hierarchy <= HMAT_LB_MEM_CACHE_3RD_LEVEL; hierarchy++) {
239
for (type = HMAT_LB_DATA_ACCESS_LATENCY;
240
type <= HMAT_LB_DATA_WRITE_BANDWIDTH; type++) {
241
hmat_lb = numa_state->hmat_lb[hierarchy][type];
243
if (hmat_lb && hmat_lb->list->len) {
244
build_hmat_lb(table_data, hmat_lb, num_initiator,
245
numa_state->num_nodes, initiator_list);
254
for (i = 0; i < numa_state->num_nodes; i++) {
256
for (cache_level = 1; cache_level < HMAT_LB_LEVELS; cache_level++) {
257
if (numa_state->hmat_cache[i][cache_level]) {
261
for (cache_level = 0; cache_level <= total_levels; cache_level++) {
262
hmat_cache = numa_state->hmat_cache[i][cache_level];
264
build_hmat_cache(table_data, total_levels, hmat_cache);
270
void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state,
271
const char *oem_id, const char *oem_table_id)
273
AcpiTable table = { .sig = "HMAT", .rev = 2,
274
.oem_id = oem_id, .oem_table_id = oem_table_id };
276
acpi_table_begin(&table, table_data);
277
hmat_build_table_structs(table_data, numa_state);
278
acpi_table_end(linker, &table);