mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 00:03:54 -06:00
* SGX implementation for x86
* Miscellaneous bugfixes * Fix dependencies from ROMs to qtests -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmFVu/sUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroNFUgf+OexjKqJw4qzbDdQrxWqw3upoFblk y4OrmrhCyCKDwPghnjHUEVGHnNKqKpCLoIvtvFZ7xX/qezpMtZxVUliOVNQGmioR MZU/DbdlvVL/t8yKjfz1ljshk55hnSJ7rAv8LBA+B3uNzyJ+LZU9+Kbvmei5oyex nenCtXnoVNBJMvTBE/KfJbp0UasEb1OTvPBa0Y7mHyDub28FDPKr9WZbloCLUtE+ uXwbZ34VRDsxbLnXh+BJ+ljOQLdsJErAkiPKTnW1/3W8Ti7PzOzvLpbSIVdBv/9A U1qOEm48BjCrG/tFJvTUm0ZM7AHmqYfvmwpenDpL0FhReohMdUa3pycQ9g== =Hicy -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
0021c4765a
64 changed files with 1397 additions and 38 deletions
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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'))
|
||||
|
|
15
hw/i386/pc.c
15
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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
184
hw/i386/sgx-epc.c
Normal file
184
hw/i386/sgx-epc.c
Normal file
|
@ -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)
|
26
hw/i386/sgx-stub.c
Normal file
26
hw/i386/sgx-stub.c
Normal file
|
@ -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();
|
||||
}
|
170
hw/i386/sgx.c
Normal file
170
hw/i386/sgx.c
Normal file
|
@ -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);
|
||||
}
|
|
@ -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 = {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue