2bc292
From 6274a2a09a8931188889467b104bf2e2fc39cb54 Mon Sep 17 00:00:00 2001
2bc292
From: Yang Zhong <yang.zhong@intel.com>
2bc292
Date: Mon, 1 Nov 2021 12:20:05 -0400
2bc292
Subject: [PATCH 01/12] numa: Enable numa for SGX EPC sections
2bc292
2bc292
RH-Author: Paul Lai <plai@redhat.com>
2bc292
RH-MergeRequest: 65: Enable SGX and add SGX Numa support
2bc292
RH-Commit: [1/5] ff69d138c3f5903096388ec7ccf8dc5e6c6c6ffb
2bc292
RH-Bugzilla: 2033708
2bc292
RH-Acked-by: Paolo Bonzini <None>
2bc292
RH-Acked-by: Bandan Das <None>
2bc292
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
2bc292
2bc292
The basic SGX did not enable numa for SGX EPC sections, which
2bc292
result in all EPC sections located in numa node 0. This patch
2bc292
enable SGX numa function in the guest and the EPC section can
2bc292
work with RAM as one numa node.
2bc292
2bc292
The Guest kernel related log:
2bc292
[    0.009981] ACPI: SRAT: Node 0 PXM 0 [mem 0x180000000-0x183ffffff]
2bc292
[    0.009982] ACPI: SRAT: Node 1 PXM 1 [mem 0x184000000-0x185bfffff]
2bc292
The SRAT table can normally show SGX EPC sections menory info in different
2bc292
numa nodes.
2bc292
2bc292
The SGX EPC numa related command:
2bc292
 ......
2bc292
 -m 4G,maxmem=20G \
2bc292
 -smp sockets=2,cores=2 \
2bc292
 -cpu host,+sgx-provisionkey \
2bc292
 -object memory-backend-ram,size=2G,host-nodes=0,policy=bind,id=node0 \
2bc292
 -object memory-backend-epc,id=mem0,size=64M,prealloc=on,host-nodes=0,policy=bind \
2bc292
 -numa node,nodeid=0,cpus=0-1,memdev=node0 \
2bc292
 -object memory-backend-ram,size=2G,host-nodes=1,policy=bind,id=node1 \
2bc292
 -object memory-backend-epc,id=mem1,size=28M,prealloc=on,host-nodes=1,policy=bind \
2bc292
 -numa node,nodeid=1,cpus=2-3,memdev=node1 \
2bc292
 -M sgx-epc.0.memdev=mem0,sgx-epc.0.node=0,sgx-epc.1.memdev=mem1,sgx-epc.1.node=1 \
2bc292
 ......
2bc292
2bc292
Signed-off-by: Yang Zhong <yang.zhong@intel.com>
2bc292
Message-Id: <20211101162009.62161-2-yang.zhong@intel.com>
2bc292
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2bc292
(cherry picked from commit 1105812382e1126d86dddc16b3700f8c79dc93d1)
2bc292
Signed-off-by: Paul Lai <plai@redhat.com>
2bc292
---
2bc292
 hw/core/numa.c            |  5 ++---
2bc292
 hw/i386/acpi-build.c      |  2 ++
2bc292
 hw/i386/sgx-epc.c         |  3 +++
2bc292
 hw/i386/sgx-stub.c        |  4 ++++
2bc292
 hw/i386/sgx.c             | 44 +++++++++++++++++++++++++++++++++++++++
2bc292
 include/hw/i386/sgx-epc.h |  3 +++
2bc292
 monitor/hmp-cmds.c        |  1 +
2bc292
 qapi/machine.json         | 10 ++++++++-
2bc292
 qemu-options.hx           |  4 ++--
2bc292
 9 files changed, 70 insertions(+), 6 deletions(-)
2bc292
2bc292
diff --git a/hw/core/numa.c b/hw/core/numa.c
2bc292
index e6050b2273..1aa05dcf42 100644
2bc292
--- a/hw/core/numa.c
2bc292
+++ b/hw/core/numa.c
2bc292
@@ -784,9 +784,8 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[])
2bc292
                 break;
2bc292
             case MEMORY_DEVICE_INFO_KIND_SGX_EPC:
2bc292
                 se = value->u.sgx_epc.data;
2bc292
-                /* TODO: once we support numa, assign to right node */
2bc292
-                node_mem[0].node_mem += se->size;
2bc292
-                node_mem[0].node_plugged_mem += se->size;
2bc292
+                node_mem[se->node].node_mem += se->size;
2bc292
+                node_mem[se->node].node_plugged_mem = 0;
2bc292
                 break;
2bc292
             default:
2bc292
                 g_assert_not_reached();
2bc292
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
2bc292
index a99c6e4fe3..8383b83ee3 100644
2bc292
--- a/hw/i386/acpi-build.c
2bc292
+++ b/hw/i386/acpi-build.c
2bc292
@@ -2068,6 +2068,8 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
2bc292
         nvdimm_build_srat(table_data);
2bc292
     }
2bc292
 
2bc292
+    sgx_epc_build_srat(table_data);
2bc292
+
2bc292
     /*
2bc292
      * TODO: this part is not in ACPI spec and current linux kernel boots fine
2bc292
      * without these entries. But I recall there were issues the last time I
2bc292
diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c
2bc292
index e508827e78..96b2940d75 100644
2bc292
--- a/hw/i386/sgx-epc.c
2bc292
+++ b/hw/i386/sgx-epc.c
2bc292
@@ -21,6 +21,7 @@
2bc292
 
2bc292
 static Property sgx_epc_properties[] = {
2bc292
     DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0),
2bc292
+    DEFINE_PROP_UINT32(SGX_EPC_NUMA_NODE_PROP, SGXEPCDevice, node, 0),
2bc292
     DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem,
2bc292
                      TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
2bc292
     DEFINE_PROP_END_OF_LIST(),
2bc292
@@ -139,6 +140,8 @@ static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md,
2bc292
     se->memaddr = epc->addr;
2bc292
     se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP,
2bc292
                                         NULL);
2bc292
+    se->node = object_property_get_uint(OBJECT(epc), SGX_EPC_NUMA_NODE_PROP,
2bc292
+                                        NULL);
2bc292
     se->memdev = object_get_canonical_path(OBJECT(epc->hostmem));
2bc292
 
2bc292
     info->u.sgx_epc.data = se;
2bc292
diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c
2bc292
index c9b379e665..26833eb233 100644
2bc292
--- a/hw/i386/sgx-stub.c
2bc292
+++ b/hw/i386/sgx-stub.c
2bc292
@@ -6,6 +6,10 @@
2bc292
 #include "qapi/error.h"
2bc292
 #include "qapi/qapi-commands-misc-target.h"
2bc292
 
2bc292
+void sgx_epc_build_srat(GArray *table_data)
2bc292
+{
2bc292
+}
2bc292
+
2bc292
 SGXInfo *qmp_query_sgx(Error **errp)
2bc292
 {
2bc292
     error_setg(errp, "SGX support is not compiled in");
2bc292
diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
2bc292
index 8fef3dd8fa..d04299904a 100644
2bc292
--- a/hw/i386/sgx.c
2bc292
+++ b/hw/i386/sgx.c
2bc292
@@ -23,6 +23,7 @@
2bc292
 #include "sysemu/hw_accel.h"
2bc292
 #include "sysemu/reset.h"
2bc292
 #include <sys/ioctl.h>
2bc292
+#include "hw/acpi/aml-build.h"
2bc292
 
2bc292
 #define SGX_MAX_EPC_SECTIONS            8
2bc292
 #define SGX_CPUID_EPC_INVALID           0x0
2bc292
@@ -36,6 +37,46 @@
2bc292
 
2bc292
 #define RETRY_NUM                       2
2bc292
 
2bc292
+static int sgx_epc_device_list(Object *obj, void *opaque)
2bc292
+{
2bc292
+    GSList **list = opaque;
2bc292
+
2bc292
+    if (object_dynamic_cast(obj, TYPE_SGX_EPC)) {
2bc292
+        *list = g_slist_append(*list, DEVICE(obj));
2bc292
+    }
2bc292
+
2bc292
+    object_child_foreach(obj, sgx_epc_device_list, opaque);
2bc292
+    return 0;
2bc292
+}
2bc292
+
2bc292
+static GSList *sgx_epc_get_device_list(void)
2bc292
+{
2bc292
+    GSList *list = NULL;
2bc292
+
2bc292
+    object_child_foreach(qdev_get_machine(), sgx_epc_device_list, &list);
2bc292
+    return list;
2bc292
+}
2bc292
+
2bc292
+void sgx_epc_build_srat(GArray *table_data)
2bc292
+{
2bc292
+    GSList *device_list = sgx_epc_get_device_list();
2bc292
+
2bc292
+    for (; device_list; device_list = device_list->next) {
2bc292
+        DeviceState *dev = device_list->data;
2bc292
+        Object *obj = OBJECT(dev);
2bc292
+        uint64_t addr, size;
2bc292
+        int node;
2bc292
+
2bc292
+        node = object_property_get_uint(obj, SGX_EPC_NUMA_NODE_PROP,
2bc292
+                                        &error_abort);
2bc292
+        addr = object_property_get_uint(obj, SGX_EPC_ADDR_PROP, &error_abort);
2bc292
+        size = object_property_get_uint(obj, SGX_EPC_SIZE_PROP, &error_abort);
2bc292
+
2bc292
+        build_srat_memory(table_data, addr, size, node, MEM_AFFINITY_ENABLED);
2bc292
+    }
2bc292
+    g_slist_free(device_list);
2bc292
+}
2bc292
+
2bc292
 static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
2bc292
 {
2bc292
     return (low & MAKE_64BIT_MASK(12, 20)) +
2bc292
@@ -226,6 +267,9 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms)
2bc292
         /* set the memdev link with memory backend */
2bc292
         object_property_parse(obj, SGX_EPC_MEMDEV_PROP, list->value->memdev,
2bc292
                               &error_fatal);
2bc292
+        /* set the numa node property for sgx epc object */
2bc292
+        object_property_set_uint(obj, SGX_EPC_NUMA_NODE_PROP, list->value->node,
2bc292
+                             &error_fatal);
2bc292
         object_property_set_bool(obj, "realized", true, &error_fatal);
2bc292
         object_unref(obj);
2bc292
     }
2bc292
diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h
2bc292
index a6a65be854..581fac389a 100644
2bc292
--- a/include/hw/i386/sgx-epc.h
2bc292
+++ b/include/hw/i386/sgx-epc.h
2bc292
@@ -25,6 +25,7 @@
2bc292
 #define SGX_EPC_ADDR_PROP "addr"
2bc292
 #define SGX_EPC_SIZE_PROP "size"
2bc292
 #define SGX_EPC_MEMDEV_PROP "memdev"
2bc292
+#define SGX_EPC_NUMA_NODE_PROP "node"
2bc292
 
2bc292
 /**
2bc292
  * SGXEPCDevice:
2bc292
@@ -38,6 +39,7 @@ typedef struct SGXEPCDevice {
2bc292
 
2bc292
     /* public */
2bc292
     uint64_t addr;
2bc292
+    uint32_t node;
2bc292
     HostMemoryBackendEpc *hostmem;
2bc292
 } SGXEPCDevice;
2bc292
 
2bc292
@@ -56,6 +58,7 @@ typedef struct SGXEPCState {
2bc292
 } SGXEPCState;
2bc292
 
2bc292
 bool sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size);
2bc292
+void sgx_epc_build_srat(GArray *table_data);
2bc292
 
2bc292
 static inline uint64_t sgx_epc_above_4g_end(SGXEPCState *sgx_epc)
2bc292
 {
2bc292
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
2bc292
index 9c91bf93e9..2669156b28 100644
2bc292
--- a/monitor/hmp-cmds.c
2bc292
+++ b/monitor/hmp-cmds.c
2bc292
@@ -1810,6 +1810,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict)
2bc292
                                se->id ? se->id : "");
2bc292
                 monitor_printf(mon, "  memaddr: 0x%" PRIx64 "\n", se->memaddr);
2bc292
                 monitor_printf(mon, "  size: %" PRIu64 "\n", se->size);
2bc292
+                monitor_printf(mon, "  node: %" PRId64 "\n", se->node);
2bc292
                 monitor_printf(mon, "  memdev: %s\n", se->memdev);
2bc292
                 break;
2bc292
             default:
2bc292
diff --git a/qapi/machine.json b/qapi/machine.json
2bc292
index 067e3f5378..16e771affc 100644
2bc292
--- a/qapi/machine.json
2bc292
+++ b/qapi/machine.json
2bc292
@@ -1207,12 +1207,15 @@
2bc292
 #
2bc292
 # @memdev: memory backend linked with device
2bc292
 #
2bc292
+# @node: the numa node
2bc292
+#
2bc292
 # Since: 6.2
2bc292
 ##
2bc292
 { 'struct': 'SgxEPCDeviceInfo',
2bc292
   'data': { '*id': 'str',
2bc292
             'memaddr': 'size',
2bc292
             'size': 'size',
2bc292
+            'node': 'int',
2bc292
             'memdev': 'str'
2bc292
           }
2bc292
 }
2bc292
@@ -1285,10 +1288,15 @@
2bc292
 #
2bc292
 # @memdev: memory backend linked with device
2bc292
 #
2bc292
+# @node: the numa node
2bc292
+#
2bc292
 # Since: 6.2
2bc292
 ##
2bc292
 { 'struct': 'SgxEPC',
2bc292
-  'data': { 'memdev': 'str' } }
2bc292
+  'data': { 'memdev': 'str',
2bc292
+            'node': 'int'
2bc292
+          }
2bc292
+}
2bc292
 
2bc292
 ##
2bc292
 # @SgxEPCProperties:
2bc292
diff --git a/qemu-options.hx b/qemu-options.hx
2bc292
index 94c4a8dbaf..4b7798088b 100644
2bc292
--- a/qemu-options.hx
2bc292
+++ b/qemu-options.hx
2bc292
@@ -127,11 +127,11 @@ SRST
2bc292
 ERST
2bc292
 
2bc292
 DEF("M", HAS_ARG, QEMU_OPTION_M,
2bc292
-    "                sgx-epc.0.memdev=memid\n",
2bc292
+    "                sgx-epc.0.memdev=memid,sgx-epc.0.node=numaid\n",
2bc292
     QEMU_ARCH_ALL)
2bc292
 
2bc292
 SRST
2bc292
-``sgx-epc.0.memdev=@var{memid}``
2bc292
+``sgx-epc.0.memdev=@var{memid},sgx-epc.0.node=@var{numaid}``
2bc292
     Define an SGX EPC section.
2bc292
 ERST
2bc292
 
2bc292
-- 
2bc292
2.27.0
2bc292