aboutsummaryrefslogtreecommitdiff
path: root/hw/i386
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-09-30 17:38:30 +0100
committerPeter Maydell <peter.maydell@linaro.org>2021-09-30 17:38:31 +0100
commit0021c4765a6b83e5b09409b75d50c6caaa6971b9 (patch)
tree2d753cd2cc80d8e4ea0e3469b4334bace179c0b4 /hw/i386
parentfce8f7735fcea23056ff41be55e73eacbca31b5e (diff)
parentc1de5858bd39b299d3d8baec38b0376bed7f19e8 (diff)
Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging
* SGX implementation for x86 * Miscellaneous bugfixes * Fix dependencies from ROMs to qtests # gpg: Signature made Thu 30 Sep 2021 14:30:35 BST # 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] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini-gitlab/tags/for-upstream: (33 commits) meson_options.txt: Switch the default value for the vnc option to 'auto' build-sys: add HAVE_IPPROTO_MPTCP memory: Add tracepoint for dirty sync memory: Name all the memory listeners target/i386: Fix memory leak in sev_read_file_base64() tests: qtest: bios-tables-test depends on the unpacked edk2 ROMs meson: unpack edk2 firmware even if --disable-blobs target/i386: Add the query-sgx-capabilities QMP command target/i386: Add HMP and QMP interfaces for SGX docs/system: Add SGX documentation to the system manual sgx-epc: Add the fill_device_info() callback support i440fx: Add support for SGX EPC q35: Add support for SGX EPC i386: acpi: Add SGX EPC entry to ACPI tables i386/pc: Add e820 entry for SGX EPC section(s) hw/i386/pc: Account for SGX EPC sections when calculating device memory hw/i386/fw_cfg: Set SGX bits in feature control fw_cfg accordingly Adjust min CPUID level to 0x12 when SGX is enabled i386: Propagate SGX CPUID sub-leafs to KVM i386: kvm: Add support for exposing PROVISIONKEY to guest ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/i386')
-rw-r--r--hw/i386/Kconfig5
-rw-r--r--hw/i386/acpi-build.c22
-rw-r--r--hw/i386/fw_cfg.c12
-rw-r--r--hw/i386/meson.build2
-rw-r--r--hw/i386/pc.c15
-rw-r--r--hw/i386/pc_piix.c1
-rw-r--r--hw/i386/pc_q35.c1
-rw-r--r--hw/i386/sgx-epc.c184
-rw-r--r--hw/i386/sgx-stub.c26
-rw-r--r--hw/i386/sgx.c170
-rw-r--r--hw/i386/x86.c29
-rw-r--r--hw/i386/xen/xen-hvm.c2
12 files changed, 467 insertions, 2 deletions
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index ddedcef0b2..962d2c981b 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -6,6 +6,10 @@ config SEV
select X86_FW_OVMF
depends on KVM
+config SGX
+ bool
+ depends on KVM
+
config PC
bool
imply APPLESMC
@@ -21,6 +25,7 @@ config PC
imply PVPANIC_ISA
imply QXL
imply SEV
+ imply SGX
imply SGA
imply TEST_DEVICES
imply TPM_CRB
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index dfaa47cdc2..f4d6ae3d02 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1841,6 +1841,28 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
}
#endif
+ if (pcms->sgx_epc.size != 0) {
+ uint64_t epc_base = pcms->sgx_epc.base;
+ uint64_t epc_size = pcms->sgx_epc.size;
+
+ dev = aml_device("EPC");
+ aml_append(dev, aml_name_decl("_HID", aml_eisaid("INT0E0C")));
+ aml_append(dev, aml_name_decl("_STR",
+ aml_unicode("Enclave Page Cache 1.0")));
+ crs = aml_resource_template();
+ aml_append(crs,
+ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED,
+ AML_MAX_FIXED, AML_NON_CACHEABLE,
+ AML_READ_WRITE, 0, epc_base,
+ epc_base + epc_size - 1, 0, epc_size));
+ aml_append(dev, aml_name_decl("_CRS", crs));
+
+ method = aml_method("_STA", 0, AML_NOTSERIALIZED);
+ aml_append(method, aml_return(aml_int(0x0f)));
+ aml_append(dev, method);
+
+ aml_append(sb_scope, dev);
+ }
aml_append(dsdt, sb_scope);
/* copy AML table into ACPI tables blob and patch header there */
diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
index 4e68d5dea4..a283785a8d 100644
--- a/hw/i386/fw_cfg.c
+++ b/hw/i386/fw_cfg.c
@@ -159,7 +159,7 @@ void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg)
{
X86CPU *cpu = X86_CPU(ms->possible_cpus->cpus[0].cpu);
CPUX86State *env = &cpu->env;
- uint32_t unused, ecx, edx;
+ uint32_t unused, ebx, ecx, edx;
uint64_t feature_control_bits = 0;
uint64_t *val;
@@ -174,6 +174,16 @@ void fw_cfg_build_feature_control(MachineState *ms, FWCfgState *fw_cfg)
feature_control_bits |= FEATURE_CONTROL_LMCE;
}
+ if (env->cpuid_level >= 7) {
+ cpu_x86_cpuid(env, 0x7, 0, &unused, &ebx, &ecx, &unused);
+ if (ebx & CPUID_7_0_EBX_SGX) {
+ feature_control_bits |= FEATURE_CONTROL_SGX;
+ }
+ if (ecx & CPUID_7_0_ECX_SGX_LC) {
+ feature_control_bits |= FEATURE_CONTROL_SGX_LC;
+ }
+ }
+
if (!feature_control_bits) {
return;
}
diff --git a/hw/i386/meson.build b/hw/i386/meson.build
index 80dad29f2b..c502965219 100644
--- a/hw/i386/meson.build
+++ b/hw/i386/meson.build
@@ -16,6 +16,8 @@ i386_ss.add(when: 'CONFIG_Q35', if_true: files('pc_q35.c'))
i386_ss.add(when: 'CONFIG_VMMOUSE', if_true: files('vmmouse.c'))
i386_ss.add(when: 'CONFIG_VMPORT', if_true: files('vmport.c'))
i386_ss.add(when: 'CONFIG_VTD', if_true: files('intel_iommu.c'))
+i386_ss.add(when: 'CONFIG_SGX', if_true: files('sgx-epc.c','sgx.c'),
+ if_false: files('sgx-stub.c'))
i386_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-common.c'))
i386_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device_x86.c'))
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 557d49c9f8..df457eceba 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -889,6 +889,10 @@ void pc_memory_init(PCMachineState *pcms,
e820_add_entry(0x100000000ULL, x86ms->above_4g_mem_size, E820_RAM);
}
+ if (pcms->sgx_epc.size != 0) {
+ e820_add_entry(pcms->sgx_epc.base, pcms->sgx_epc.size, E820_RESERVED);
+ }
+
if (!pcmc->has_reserved_memory &&
(machine->ram_slots ||
(machine->maxram_size > machine->ram_size))) {
@@ -919,8 +923,15 @@ void pc_memory_init(PCMachineState *pcms,
exit(EXIT_FAILURE);
}
+ if (pcms->sgx_epc.size != 0) {
+ machine->device_memory->base = sgx_epc_above_4g_end(&pcms->sgx_epc);
+ } else {
+ machine->device_memory->base =
+ 0x100000000ULL + x86ms->above_4g_mem_size;
+ }
+
machine->device_memory->base =
- ROUND_UP(0x100000000ULL + x86ms->above_4g_mem_size, 1 * GiB);
+ ROUND_UP(machine->device_memory->base, 1 * GiB);
if (pcmc->enforce_aligned_dimm) {
/* size device region assuming 1G page max alignment per slot */
@@ -1005,6 +1016,8 @@ uint64_t pc_pci_hole64_start(void)
if (!pcmc->broken_reserved_end) {
hole64_start += memory_region_size(&ms->device_memory->mr);
}
+ } else if (pcms->sgx_epc.size != 0) {
+ hole64_start = sgx_epc_above_4g_end(&pcms->sgx_epc);
} else {
hole64_start = 0x100000000ULL + x86ms->above_4g_mem_size;
}
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c5da7739ce..6cc834aff6 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -153,6 +153,7 @@ static void pc_init1(MachineState *machine,
}
}
+ pc_machine_init_sgx_epc(pcms);
x86_cpus_init(x86ms, pcmc->default_cpu_version);
if (pcmc->kvmclock_enabled) {
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 46cd542d17..5481d5c965 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -177,6 +177,7 @@ static void pc_q35_init(MachineState *machine)
x86ms->below_4g_mem_size = machine->ram_size;
}
+ pc_machine_init_sgx_epc(pcms);
x86_cpus_init(x86ms, pcmc->default_cpu_version);
kvmclock_create(pcmc->kvmclock_create_always);
diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c
new file mode 100644
index 0000000000..55e2217eae
--- /dev/null
+++ b/hw/i386/sgx-epc.c
@@ -0,0 +1,184 @@
+/*
+ * SGX EPC device
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * Authors:
+ * Sean Christopherson <sean.j.christopherson@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "hw/i386/pc.h"
+#include "hw/i386/sgx-epc.h"
+#include "hw/mem/memory-device.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "target/i386/cpu.h"
+#include "exec/address-spaces.h"
+
+static Property sgx_epc_properties[] = {
+ DEFINE_PROP_UINT64(SGX_EPC_ADDR_PROP, SGXEPCDevice, addr, 0),
+ DEFINE_PROP_LINK(SGX_EPC_MEMDEV_PROP, SGXEPCDevice, hostmem,
+ TYPE_MEMORY_BACKEND_EPC, HostMemoryBackendEpc *),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sgx_epc_get_size(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ Error *local_err = NULL;
+ uint64_t value;
+
+ value = memory_device_get_region_size(MEMORY_DEVICE(obj), &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
+ }
+
+ visit_type_uint64(v, name, &value, errp);
+}
+
+static void sgx_epc_init(Object *obj)
+{
+ object_property_add(obj, SGX_EPC_SIZE_PROP, "uint64", sgx_epc_get_size,
+ NULL, NULL, NULL);
+}
+
+static void sgx_epc_realize(DeviceState *dev, Error **errp)
+{
+ PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+ X86MachineState *x86ms = X86_MACHINE(pcms);
+ MemoryDeviceState *md = MEMORY_DEVICE(dev);
+ SGXEPCState *sgx_epc = &pcms->sgx_epc;
+ SGXEPCDevice *epc = SGX_EPC(dev);
+ HostMemoryBackend *hostmem;
+ const char *path;
+
+ if (x86ms->boot_cpus != 0) {
+ error_setg(errp, "'" TYPE_SGX_EPC "' can't be created after vCPUs,"
+ "e.g. via -device");
+ return;
+ }
+
+ if (!epc->hostmem) {
+ error_setg(errp, "'" SGX_EPC_MEMDEV_PROP "' property is not set");
+ return;
+ }
+ hostmem = MEMORY_BACKEND(epc->hostmem);
+ if (host_memory_backend_is_mapped(hostmem)) {
+ path = object_get_canonical_path_component(OBJECT(hostmem));
+ error_setg(errp, "can't use already busy memdev: %s", path);
+ return;
+ }
+
+ epc->addr = sgx_epc->base + sgx_epc->size;
+
+ memory_region_add_subregion(&sgx_epc->mr, epc->addr - sgx_epc->base,
+ host_memory_backend_get_memory(hostmem));
+
+ host_memory_backend_set_mapped(hostmem, true);
+
+ sgx_epc->sections = g_renew(SGXEPCDevice *, sgx_epc->sections,
+ sgx_epc->nr_sections + 1);
+ sgx_epc->sections[sgx_epc->nr_sections++] = epc;
+
+ sgx_epc->size += memory_device_get_region_size(md, errp);
+}
+
+static void sgx_epc_unrealize(DeviceState *dev)
+{
+ SGXEPCDevice *epc = SGX_EPC(dev);
+ HostMemoryBackend *hostmem = MEMORY_BACKEND(epc->hostmem);
+
+ host_memory_backend_set_mapped(hostmem, false);
+}
+
+static uint64_t sgx_epc_md_get_addr(const MemoryDeviceState *md)
+{
+ const SGXEPCDevice *epc = SGX_EPC(md);
+
+ return epc->addr;
+}
+
+static void sgx_epc_md_set_addr(MemoryDeviceState *md, uint64_t addr,
+ Error **errp)
+{
+ object_property_set_uint(OBJECT(md), SGX_EPC_ADDR_PROP, addr, errp);
+}
+
+static uint64_t sgx_epc_md_get_plugged_size(const MemoryDeviceState *md,
+ Error **errp)
+{
+ return 0;
+}
+
+static MemoryRegion *sgx_epc_md_get_memory_region(MemoryDeviceState *md,
+ Error **errp)
+{
+ SGXEPCDevice *epc = SGX_EPC(md);
+ HostMemoryBackend *hostmem;
+
+ if (!epc->hostmem) {
+ error_setg(errp, "'" SGX_EPC_MEMDEV_PROP "' property must be set");
+ return NULL;
+ }
+
+ hostmem = MEMORY_BACKEND(epc->hostmem);
+ return host_memory_backend_get_memory(hostmem);
+}
+
+static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md,
+ MemoryDeviceInfo *info)
+{
+ SgxEPCDeviceInfo *se = g_new0(SgxEPCDeviceInfo, 1);
+ SGXEPCDevice *epc = SGX_EPC(md);
+
+ se->memaddr = epc->addr;
+ se->size = object_property_get_uint(OBJECT(epc), SGX_EPC_SIZE_PROP,
+ NULL);
+ se->memdev = object_get_canonical_path(OBJECT(epc->hostmem));
+
+ info->u.sgx_epc.data = se;
+ info->type = MEMORY_DEVICE_INFO_KIND_SGX_EPC;
+}
+
+static void sgx_epc_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ MemoryDeviceClass *mdc = MEMORY_DEVICE_CLASS(oc);
+
+ dc->hotpluggable = false;
+ dc->realize = sgx_epc_realize;
+ dc->unrealize = sgx_epc_unrealize;
+ dc->desc = "SGX EPC section";
+ device_class_set_props(dc, sgx_epc_properties);
+
+ mdc->get_addr = sgx_epc_md_get_addr;
+ mdc->set_addr = sgx_epc_md_set_addr;
+ mdc->get_plugged_size = sgx_epc_md_get_plugged_size;
+ mdc->get_memory_region = sgx_epc_md_get_memory_region;
+ mdc->fill_device_info = sgx_epc_md_fill_device_info;
+}
+
+static TypeInfo sgx_epc_info = {
+ .name = TYPE_SGX_EPC,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(SGXEPCDevice),
+ .instance_init = sgx_epc_init,
+ .class_init = sgx_epc_class_init,
+ .class_size = sizeof(DeviceClass),
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_MEMORY_DEVICE },
+ { }
+ },
+};
+
+static void sgx_epc_register_types(void)
+{
+ type_register_static(&sgx_epc_info);
+}
+
+type_init(sgx_epc_register_types)
diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c
new file mode 100644
index 0000000000..3be9f5ca32
--- /dev/null
+++ b/hw/i386/sgx-stub.c
@@ -0,0 +1,26 @@
+#include "qemu/osdep.h"
+#include "hw/i386/pc.h"
+#include "hw/i386/sgx-epc.h"
+#include "hw/i386/sgx.h"
+
+SGXInfo *sgx_get_info(Error **errp)
+{
+ error_setg(errp, "SGX support is not compiled in");
+ return NULL;
+}
+
+SGXInfo *sgx_get_capabilities(Error **errp)
+{
+ error_setg(errp, "SGX support is not compiled in");
+ return NULL;
+}
+
+void pc_machine_init_sgx_epc(PCMachineState *pcms)
+{
+ memset(&pcms->sgx_epc, 0, sizeof(SGXEPCState));
+}
+
+int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
+{
+ g_assert_not_reached();
+}
diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c
new file mode 100644
index 0000000000..e481e9358f
--- /dev/null
+++ b/hw/i386/sgx.c
@@ -0,0 +1,170 @@
+/*
+ * SGX common code
+ *
+ * Copyright (C) 2021 Intel Corporation
+ *
+ * Authors:
+ * Yang Zhong<yang.zhong@intel.com>
+ * Sean Christopherson <sean.j.christopherson@intel.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "hw/i386/pc.h"
+#include "hw/i386/sgx-epc.h"
+#include "hw/mem/memory-device.h"
+#include "monitor/qdev.h"
+#include "qapi/error.h"
+#include "exec/address-spaces.h"
+#include "hw/i386/sgx.h"
+#include "sysemu/hw_accel.h"
+
+#define SGX_MAX_EPC_SECTIONS 8
+#define SGX_CPUID_EPC_INVALID 0x0
+
+/* A valid EPC section. */
+#define SGX_CPUID_EPC_SECTION 0x1
+#define SGX_CPUID_EPC_MASK 0xF
+
+static uint64_t sgx_calc_section_metric(uint64_t low, uint64_t high)
+{
+ return (low & MAKE_64BIT_MASK(12, 20)) +
+ ((high & MAKE_64BIT_MASK(0, 20)) << 32);
+}
+
+static uint64_t sgx_calc_host_epc_section_size(void)
+{
+ uint32_t i, type;
+ uint32_t eax, ebx, ecx, edx;
+ uint64_t size = 0;
+
+ for (i = 0; i < SGX_MAX_EPC_SECTIONS; i++) {
+ host_cpuid(0x12, i + 2, &eax, &ebx, &ecx, &edx);
+
+ type = eax & SGX_CPUID_EPC_MASK;
+ if (type == SGX_CPUID_EPC_INVALID) {
+ break;
+ }
+
+ if (type != SGX_CPUID_EPC_SECTION) {
+ break;
+ }
+
+ size += sgx_calc_section_metric(ecx, edx);
+ }
+
+ return size;
+}
+
+SGXInfo *sgx_get_capabilities(Error **errp)
+{
+ SGXInfo *info = NULL;
+ uint32_t eax, ebx, ecx, edx;
+
+ int fd = qemu_open_old("/dev/sgx_vepc", O_RDWR);
+ if (fd < 0) {
+ error_setg(errp, "SGX is not enabled in KVM");
+ return NULL;
+ }
+
+ info = g_new0(SGXInfo, 1);
+ host_cpuid(0x7, 0, &eax, &ebx, &ecx, &edx);
+
+ info->sgx = ebx & (1U << 2) ? true : false;
+ info->flc = ecx & (1U << 30) ? true : false;
+
+ host_cpuid(0x12, 0, &eax, &ebx, &ecx, &edx);
+ info->sgx1 = eax & (1U << 0) ? true : false;
+ info->sgx2 = eax & (1U << 1) ? true : false;
+
+ info->section_size = sgx_calc_host_epc_section_size();
+
+ close(fd);
+
+ return info;
+}
+
+SGXInfo *sgx_get_info(Error **errp)
+{
+ SGXInfo *info = NULL;
+ X86MachineState *x86ms;
+ PCMachineState *pcms =
+ (PCMachineState *)object_dynamic_cast(qdev_get_machine(),
+ TYPE_PC_MACHINE);
+ if (!pcms) {
+ error_setg(errp, "SGX is only supported on PC machines");
+ return NULL;
+ }
+
+ x86ms = X86_MACHINE(pcms);
+ if (!x86ms->sgx_epc_list) {
+ error_setg(errp, "No EPC regions defined, SGX not available");
+ return NULL;
+ }
+
+ SGXEPCState *sgx_epc = &pcms->sgx_epc;
+ info = g_new0(SGXInfo, 1);
+
+ info->sgx = true;
+ info->sgx1 = true;
+ info->sgx2 = true;
+ info->flc = true;
+ info->section_size = sgx_epc->size;
+
+ return info;
+}
+
+int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size)
+{
+ PCMachineState *pcms = PC_MACHINE(qdev_get_machine());
+ SGXEPCDevice *epc;
+
+ if (pcms->sgx_epc.size == 0 || pcms->sgx_epc.nr_sections <= section_nr) {
+ return 1;
+ }
+
+ epc = pcms->sgx_epc.sections[section_nr];
+
+ *addr = epc->addr;
+ *size = memory_device_get_region_size(MEMORY_DEVICE(epc), &error_fatal);
+
+ return 0;
+}
+
+void pc_machine_init_sgx_epc(PCMachineState *pcms)
+{
+ SGXEPCState *sgx_epc = &pcms->sgx_epc;
+ X86MachineState *x86ms = X86_MACHINE(pcms);
+ SgxEPCList *list = NULL;
+ Object *obj;
+
+ memset(sgx_epc, 0, sizeof(SGXEPCState));
+ if (!x86ms->sgx_epc_list) {
+ return;
+ }
+
+ sgx_epc->base = 0x100000000ULL + x86ms->above_4g_mem_size;
+
+ memory_region_init(&sgx_epc->mr, OBJECT(pcms), "sgx-epc", UINT64_MAX);
+ memory_region_add_subregion(get_system_memory(), sgx_epc->base,
+ &sgx_epc->mr);
+
+ for (list = x86ms->sgx_epc_list; list; list = list->next) {
+ obj = object_new("sgx-epc");
+
+ /* set the memdev link with memory backend */
+ object_property_parse(obj, SGX_EPC_MEMDEV_PROP, list->value->memdev,
+ &error_fatal);
+ object_property_set_bool(obj, "realized", true, &error_fatal);
+ object_unref(obj);
+ }
+
+ if ((sgx_epc->base + sgx_epc->size) < sgx_epc->base) {
+ error_report("Size of all 'sgx-epc' =0x%"PRIu64" causes EPC to wrap",
+ sgx_epc->size);
+ exit(EXIT_FAILURE);
+ }
+
+ memory_region_set_size(&sgx_epc->mr, sgx_epc->size);
+}
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 00448ed55a..41ef9a84a9 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -30,6 +30,8 @@
#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qapi-visit-common.h"
+#include "qapi/clone-visitor.h"
+#include "qapi/qapi-visit-machine.h"
#include "qapi/visitor.h"
#include "sysemu/qtest.h"
#include "sysemu/whpx.h"
@@ -1263,6 +1265,27 @@ static void x86_machine_set_bus_lock_ratelimit(Object *obj, Visitor *v,
visit_type_uint64(v, name, &x86ms->bus_lock_ratelimit, errp);
}
+static void machine_get_sgx_epc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ X86MachineState *x86ms = X86_MACHINE(obj);
+ SgxEPCList *list = x86ms->sgx_epc_list;
+
+ visit_type_SgxEPCList(v, name, &list, errp);
+}
+
+static void machine_set_sgx_epc(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ X86MachineState *x86ms = X86_MACHINE(obj);
+ SgxEPCList *list;
+
+ list = x86ms->sgx_epc_list;
+ visit_type_SgxEPCList(v, name, &x86ms->sgx_epc_list, errp);
+
+ qapi_free_SgxEPCList(list);
+}
+
static void x86_machine_initfn(Object *obj)
{
X86MachineState *x86ms = X86_MACHINE(obj);
@@ -1322,6 +1345,12 @@ static void x86_machine_class_init(ObjectClass *oc, void *data)
x86_machine_set_bus_lock_ratelimit, NULL, NULL);
object_class_property_set_description(oc, X86_MACHINE_BUS_LOCK_RATELIMIT,
"Set the ratelimit for the bus locks acquired in VMs");
+
+ object_class_property_add(oc, "sgx-epc", "SgxEPC",
+ machine_get_sgx_epc, machine_set_sgx_epc,
+ NULL, NULL);
+ object_class_property_set_description(oc, "sgx-epc",
+ "SGX EPC device");
}
static const TypeInfo x86_machine_info = {
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 9b432773f0..e3d3d5cf89 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -721,6 +721,7 @@ static void xen_log_global_stop(MemoryListener *listener)
}
static MemoryListener xen_memory_listener = {
+ .name = "xen-memory",
.region_add = xen_region_add,
.region_del = xen_region_del,
.log_start = xen_log_start,
@@ -732,6 +733,7 @@ static MemoryListener xen_memory_listener = {
};
static MemoryListener xen_io_listener = {
+ .name = "xen-io",
.region_add = xen_io_add,
.region_del = xen_io_del,
.priority = 10,