#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
#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)) +
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;
}
memory_region_set_size(&sgx_epc->mr, sgx_epc->size);
+
+ /* register the reset callback for sgx epc */
+ qemu_register_reset(sgx_epc_reset, NULL);
}