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