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