vl: Add sgx compound properties to expose SGX EPC sections to guest
Because SGX EPC is enumerated through CPUID, EPC "devices" need to be realized prior to realizing the vCPUs themselves, i.e. long before generic devices are parsed and realized. From a virtualization perspective, the CPUID aspect also means that EPC sections cannot be hotplugged without paravirtualizing the guest kernel (hardware does not support hotplugging as EPC sections must be locked down during pre-boot to provide EPC's security properties). So even though EPC sections could be realized through the generic -devices command, they need to be created much earlier for them to actually be usable by the guest. Place all EPC sections in a contiguous block, somewhat arbitrarily starting after RAM above 4g. Ensuring EPC is in a contiguous region simplifies calculations, e.g. device memory base, PCI hole, etc..., allows dynamic calculation of the total EPC size, e.g. exposing EPC to guests does not require -maxmem, and last but not least allows all of EPC to be enumerated in a single ACPI entry, which is expected by some kernels, e.g. Windows 7 and 8. The new compound properties command for sgx like below: ...... -object memory-backend-epc,id=mem1,size=28M,prealloc=on \ -object memory-backend-epc,id=mem2,size=10M \ -M sgx-epc.0.memdev=mem1,sgx-epc.1.memdev=mem2 Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Yang Zhong <yang.zhong@intel.com> Message-Id: <20210719112136.57018-6-yang.zhong@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
80509c5557
commit
dfce81f1b9
@ -14,13 +14,8 @@
|
||||
#include "hw/i386/sgx-epc.h"
|
||||
#include "hw/mem/memory-device.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "monitor/qdev.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/units.h"
|
||||
#include "target/i386/cpu.h"
|
||||
#include "exec/address-spaces.h"
|
||||
|
||||
@ -56,6 +51,8 @@ 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;
|
||||
@ -77,7 +74,18 @@ static void sgx_epc_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
error_setg(errp, "'" TYPE_SGX_EPC "' not supported");
|
||||
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)
|
||||
|
@ -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 = {
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "hw/acpi/acpi_dev_interface.h"
|
||||
#include "hw/hotplug.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/i386/sgx-epc.h"
|
||||
|
||||
#define HPET_INTCAP "hpet-intcap"
|
||||
|
||||
@ -49,6 +50,8 @@ typedef struct PCMachineState {
|
||||
|
||||
/* ACPI Memory hotplug IO base address */
|
||||
hwaddr memhp_io_base;
|
||||
|
||||
SGXEPCState sgx_epc;
|
||||
} PCMachineState;
|
||||
|
||||
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
|
||||
|
@ -41,4 +41,18 @@ typedef struct SGXEPCDevice {
|
||||
HostMemoryBackendEpc *hostmem;
|
||||
} SGXEPCDevice;
|
||||
|
||||
/*
|
||||
* @base: address in guest physical address space where EPC regions start
|
||||
* @mr: address space container for memory devices
|
||||
*/
|
||||
typedef struct SGXEPCState {
|
||||
uint64_t base;
|
||||
uint64_t size;
|
||||
|
||||
MemoryRegion mr;
|
||||
|
||||
struct SGXEPCDevice **sections;
|
||||
int nr_sections;
|
||||
} SGXEPCState;
|
||||
|
||||
#endif
|
||||
|
@ -62,6 +62,7 @@ struct X86MachineState {
|
||||
unsigned pci_irq_mask;
|
||||
unsigned apic_id_limit;
|
||||
uint16_t boot_cpus;
|
||||
SgxEPCList *sgx_epc_list;
|
||||
|
||||
OnOffAuto smm;
|
||||
OnOffAuto acpi;
|
||||
|
@ -1225,7 +1225,6 @@
|
||||
##
|
||||
{ 'struct': 'VirtioMEMDeviceInfoWrapper',
|
||||
'data': { 'data': 'VirtioMEMDeviceInfo' } }
|
||||
|
||||
##
|
||||
# @MemoryDeviceInfo:
|
||||
#
|
||||
@ -1246,6 +1245,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
##
|
||||
# @SgxEPC:
|
||||
#
|
||||
# Sgx EPC cmdline information
|
||||
#
|
||||
# @memdev: memory backend linked with device
|
||||
#
|
||||
# Since: 6.2
|
||||
##
|
||||
{ 'struct': 'SgxEPC',
|
||||
'data': { 'memdev': 'str' } }
|
||||
|
||||
##
|
||||
# @SgxEPCProperties:
|
||||
#
|
||||
# SGX properties of machine types.
|
||||
#
|
||||
# @sgx-epc: list of ids of memory-backend-epc objects.
|
||||
#
|
||||
# Since: 6.2
|
||||
##
|
||||
{ 'struct': 'SgxEPCProperties',
|
||||
'data': { 'sgx-epc': ['SgxEPC'] }
|
||||
}
|
||||
|
||||
##
|
||||
# @query-memory-devices:
|
||||
#
|
||||
|
@ -126,8 +126,14 @@ SRST
|
||||
-m 512M
|
||||
ERST
|
||||
|
||||
HXCOMM Deprecated by -machine
|
||||
DEF("M", HAS_ARG, QEMU_OPTION_M, "", QEMU_ARCH_ALL)
|
||||
DEF("M", HAS_ARG, QEMU_OPTION_M,
|
||||
" sgx-epc.0.memdev=memid\n",
|
||||
QEMU_ARCH_ALL)
|
||||
|
||||
SRST
|
||||
``sgx-epc.0.memdev=@var{memid}``
|
||||
Define an SGX EPC section.
|
||||
ERST
|
||||
|
||||
DEF("cpu", HAS_ARG, QEMU_OPTION_cpu,
|
||||
"-cpu cpu select CPU ('-cpu help' for list)\n", QEMU_ARCH_ALL)
|
||||
|
Loading…
Reference in New Issue
Block a user