aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-11-11 09:56:22 +0100
committerRichard Henderson <richard.henderson@linaro.org>2021-11-11 09:56:22 +0100
commit1b9fc6d8ba6667ceb56a3392e84656dcaed0d676 (patch)
treea142544cdc38101f4fce74135b86f58159e3c24c /hw
parentb30187ef02d786da674cd80079e2fcd6bb8f85e1 (diff)
parent2c3132279b9a962c27adaea53b4c8e8480385706 (diff)
downloadqemu-1b9fc6d8ba6667ceb56a3392e84656dcaed0d676.zip
qemu-1b9fc6d8ba6667ceb56a3392e84656dcaed0d676.tar.gz
qemu-1b9fc6d8ba6667ceb56a3392e84656dcaed0d676.tar.bz2
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* Fixes for SGX * force_rcu notifiers # gpg: Signature made Wed 10 Nov 2021 10:57:48 PM CET # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: sgx: Reset the vEPC regions during VM reboot numa: avoid crash with SGX and "info numa" accel/tcg: Register a force_rcu notifier rcu: Introduce force_rcu notifier target/i386: sgx: mark device not user creatable Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/core/numa.c7
-rw-r--r--hw/i386/sgx-epc.c1
-rw-r--r--hw/i386/sgx.c50
3 files changed, 58 insertions, 0 deletions
diff --git a/hw/core/numa.c b/hw/core/numa.c
index 510d096..e6050b2 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -756,6 +756,7 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[])
PCDIMMDeviceInfo *pcdimm_info;
VirtioPMEMDeviceInfo *vpi;
VirtioMEMDeviceInfo *vmi;
+ SgxEPCDeviceInfo *se;
for (info = info_list; info; info = info->next) {
MemoryDeviceInfo *value = info->value;
@@ -781,6 +782,12 @@ static void numa_stat_memory_devices(NumaNodeMem node_mem[])
node_mem[vmi->node].node_mem += vmi->size;
node_mem[vmi->node].node_plugged_mem += vmi->size;
break;
+ case MEMORY_DEVICE_INFO_KIND_SGX_EPC:
+ se = value->u.sgx_epc.data;
+ /* TODO: once we support numa, assign to right node */
+ node_mem[0].node_mem += se->size;
+ node_mem[0].node_plugged_mem += se->size;
+ break;
default:
g_assert_not_reached();
}
diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c
index 55e2217..e508827 100644
--- a/hw/i386/sgx-epc.c
+++ b/hw/i386/sgx-epc.c
@@ -154,6 +154,7 @@ static void sgx_epc_class_init(ObjectClass *oc, void *data)
dc->realize = sgx_epc_realize;
dc->unrealize = sgx_epc_unrealize;
dc->desc = "SGX EPC section";
+ dc->user_creatable = false;
device_class_set_props(dc, sgx_epc_properties);
mdc->get_addr = sgx_epc_md_get_addr;
diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
index 1160756..8fef3dd 100644
--- a/hw/i386/sgx.c
+++ b/hw/i386/sgx.c
@@ -21,6 +21,8 @@
#include "qapi/qapi-commands-misc-target.h"
#include "exec/address-spaces.h"
#include "sysemu/hw_accel.h"
+#include "sysemu/reset.h"
+#include <sys/ioctl.h>
#define SGX_MAX_EPC_SECTIONS 8
#define SGX_CPUID_EPC_INVALID 0x0
@@ -29,6 +31,11 @@
#define SGX_CPUID_EPC_SECTION 0x1
#define SGX_CPUID_EPC_MASK 0xF
+#define SGX_MAGIC 0xA4
+#define SGX_IOC_VEPC_REMOVE_ALL _IO(SGX_MAGIC, 0x04)
+
+#define RETRY_NUM 2
+
static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
{
return (low & MAKE_64BIT_MASK(12, 20)) +
@@ -59,6 +66,46 @@ static uint64_t sgx_calc_host_epc_section_size(void)
return size;
}
+static void sgx_epc_reset(void *opaque)
+{
+ PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+ HostMemoryBackend *hostmem;
+ SGXEPCDevice *epc;
+ int failures;
+ int fd, i, j, r;
+ static bool warned = false;
+
+ /*
+ * The second pass is needed to remove SECS pages that could not
+ * be removed during the first.
+ */
+ for (i = 0; i < RETRY_NUM; i++) {
+ failures = 0;
+ for (j = 0; j < pcms->sgx_epc.nr_sections; j++) {
+ epc = pcms->sgx_epc.sections[j];
+ hostmem = MEMORY_BACKEND(epc->hostmem);
+ fd = memory_region_get_fd(host_memory_backend_get_memory(hostmem));
+
+ r = ioctl(fd, SGX_IOC_VEPC_REMOVE_ALL);
+ if (r == -ENOTTY && !warned) {
+ warned = true;
+ warn_report("kernel does not support SGX_IOC_VEPC_REMOVE_ALL");
+ warn_report("SGX might operate incorrectly in the guest after reset");
+ break;
+ } else if (r > 0) {
+ /* SECS pages remain */
+ failures++;
+ if (i == 1) {
+ error_report("cannot reset vEPC section %d", j);
+ }
+ }
+ }
+ if (!failures) {
+ break;
+ }
+ }
+}
+
SGXInfo *qmp_query_sgx_capabilities(Error **errp)
{
SGXInfo *info = NULL;
@@ -190,4 +237,7 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms)
}
memory_region_set_size(&sgx_epc->mr, sgx_epc->size);
+
+ /* register the reset callback for sgx epc */
+ qemu_register_reset(sgx_epc_reset, NULL);
}