/* * HMAT ACPI Implementation * * Copyright(C) 2019 Intel Corporation. * * Author: * Liu jingqi * Tao Xu * * HMAT is defined in ACPI 6.3: 5.2.27 Heterogeneous Memory Attribute Table * (HMAT) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see */ #include "qemu/osdep.h" #include "sysemu/numa.h" #include "hw/acpi/hmat.h" /* * ACPI 6.3: * 5.2.27.3 Memory Proximity Domain Attributes Structure: Table 5-145 */ static void build_hmat_mpda(GArray *table_data, uint16_t flags, uint32_t initiator, uint32_t mem_node) { /* Memory Proximity Domain Attributes Structure */ /* Type */ build_append_int_noprefix(table_data, 0, 2); /* Reserved */ build_append_int_noprefix(table_data, 0, 2); /* Length */ build_append_int_noprefix(table_data, 40, 4); /* Flags */ build_append_int_noprefix(table_data, flags, 2); /* Reserved */ build_append_int_noprefix(table_data, 0, 2); /* Proximity Domain for the Attached Initiator */ build_append_int_noprefix(table_data, initiator, 4); /* Proximity Domain for the Memory */ build_append_int_noprefix(table_data, mem_node, 4); /* Reserved */ build_append_int_noprefix(table_data, 0, 4); /* * Reserved: * Previously defined as the Start Address of the System Physical * Address Range. Deprecated since ACPI Spec 6.3. */ build_append_int_noprefix(table_data, 0, 8); /* * Reserved: * Previously defined as the Range Length of the region in bytes. * Deprecated since ACPI Spec 6.3. */ build_append_int_noprefix(table_data, 0, 8); } /* Build HMAT sub table structures */ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state) { uint16_t flags; int i; for (i = 0; i < numa_state->num_nodes; i++) { flags = 0; if (numa_state->nodes[i].initiator < MAX_NODES) { flags |= HMAT_PROXIMITY_INITIATOR_VALID; } build_hmat_mpda(table_data, flags, numa_state->nodes[i].initiator, i); } } void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state) { int hmat_start = table_data->len; /* reserve space for HMAT header */ acpi_data_push(table_data, 40); hmat_build_table_structs(table_data, numa_state); build_header(linker, table_data, (void *)(table_data->data + hmat_start), "HMAT", table_data->len - hmat_start, 2, NULL, NULL); }