From 46a1d21dbaafab2df25ac354095d90492cd3a98b Mon Sep 17 00:00:00 2001 From: Yang Zhong Date: Mon, 19 Jul 2021 19:21:06 +0800 Subject: qom: Add memory-backend-epc ObjectOptions support Add the new 'memory-backend-epc' user creatable QOM object in the ObjectOptions to support SGX since v6.1, or the sgx backend object cannot bootup. Signed-off-by: Yang Zhong Message-Id: <20210719112136.57018-4-yang.zhong@intel.com> Signed-off-by: Paolo Bonzini --- qapi/qom.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'qapi') diff --git a/qapi/qom.json b/qapi/qom.json index a25616bc7a..0222bb4506 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -647,6 +647,23 @@ '*hugetlbsize': 'size', '*seal': 'bool' } } +## +# @MemoryBackendEpcProperties: +# +# Properties for memory-backend-epc objects. +# +# The @share boolean option is true by default with epc +# +# The @merge boolean option is false by default with epc +# +# The @dump boolean option is false by default with epc +# +# Since: 6.2 +## +{ 'struct': 'MemoryBackendEpcProperties', + 'base': 'MemoryBackendProperties', + 'data': {} } + ## # @PrManagerHelperProperties: # @@ -797,6 +814,7 @@ { 'name': 'memory-backend-memfd', 'if': 'CONFIG_LINUX' }, 'memory-backend-ram', + 'memory-backend-epc', 'pef-guest', 'pr-manager-helper', 'qtest', @@ -855,6 +873,7 @@ 'memory-backend-memfd': { 'type': 'MemoryBackendMemfdProperties', 'if': 'CONFIG_LINUX' }, 'memory-backend-ram': 'MemoryBackendProperties', + 'memory-backend-epc': 'MemoryBackendEpcProperties', 'pr-manager-helper': 'PrManagerHelperProperties', 'qtest': 'QtestProperties', 'rng-builtin': 'RngProperties', -- cgit v1.2.3-55-g7522 From dfce81f1b931352af0fcfe966c115a09646bd15a Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 28 Sep 2021 10:40:58 +0200 Subject: 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 Signed-off-by: Yang Zhong Message-Id: <20210719112136.57018-6-yang.zhong@intel.com> Signed-off-by: Paolo Bonzini --- hw/i386/sgx-epc.c | 20 ++++++++++++++------ hw/i386/x86.c | 29 +++++++++++++++++++++++++++++ include/hw/i386/pc.h | 3 +++ include/hw/i386/sgx-epc.h | 14 ++++++++++++++ include/hw/i386/x86.h | 1 + qapi/machine.json | 26 +++++++++++++++++++++++++- qemu-options.hx | 10 ++++++++-- 7 files changed, 94 insertions(+), 9 deletions(-) (limited to 'qapi') diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c index c584acc17b..6677dc74b5 100644 --- a/hw/i386/sgx-epc.c +++ b/hw/i386/sgx-epc.c @@ -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) 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/include/hw/i386/pc.h b/include/hw/i386/pc.h index 4d2e35a152..668e48be8a 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -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" diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h index cf3ed5c0cd..83269972e0 100644 --- a/include/hw/i386/sgx-epc.h +++ b/include/hw/i386/sgx-epc.h @@ -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 diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 6e9244a82c..23267a3674 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -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; diff --git a/qapi/machine.json b/qapi/machine.json index 32d47f4e35..26c539fe2c 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -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: # diff --git a/qemu-options.hx b/qemu-options.hx index 8f603cc7e6..ceca52818a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -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) -- cgit v1.2.3-55-g7522 From a7c565a941b02a22f84509db797bd364c2b5716b Mon Sep 17 00:00:00 2001 From: Yang Zhong Date: Mon, 19 Jul 2021 19:21:35 +0800 Subject: sgx-epc: Add the fill_device_info() callback support Since there is no fill_device_info() callback support, and when we execute "info memory-devices" command in the monitor, the segfault will be found. This patch will add this callback support and "info memory-devices" will show sgx epc memory exposed to guest. The result as below: qemu) info memory-devices Memory device [sgx-epc]: "" memaddr: 0x180000000 size: 29360128 memdev: /objects/mem1 Memory device [sgx-epc]: "" memaddr: 0x181c00000 size: 10485760 memdev: /objects/mem2 Signed-off-by: Yang Zhong Message-Id: <20210719112136.57018-33-yang.zhong@intel.com> Signed-off-by: Paolo Bonzini --- hw/i386/sgx-epc.c | 11 ++++++++++- monitor/hmp-cmds.c | 10 ++++++++++ qapi/machine.json | 39 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 4 deletions(-) (limited to 'qapi') diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c index 6677dc74b5..55e2217eae 100644 --- a/hw/i386/sgx-epc.c +++ b/hw/i386/sgx-epc.c @@ -133,7 +133,16 @@ static MemoryRegion *sgx_epc_md_get_memory_region(MemoryDeviceState *md, static void sgx_epc_md_fill_device_info(const MemoryDeviceState *md, MemoryDeviceInfo *info) { - /* TODO */ + 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) diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index b5e71d9e6f..bcaa41350e 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -1823,6 +1823,7 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) VirtioMEMDeviceInfo *vmi; MemoryDeviceInfo *value; PCDIMMDeviceInfo *di; + SgxEPCDeviceInfo *se; for (info = info_list; info; info = info->next) { value = info->value; @@ -1870,6 +1871,15 @@ void hmp_info_memory_devices(Monitor *mon, const QDict *qdict) vmi->block_size); monitor_printf(mon, " memdev: %s\n", vmi->memdev); break; + case MEMORY_DEVICE_INFO_KIND_SGX_EPC: + se = value->u.sgx_epc.data; + monitor_printf(mon, "Memory device [%s]: \"%s\"\n", + MemoryDeviceInfoKind_str(value->type), + se->id ? se->id : ""); + monitor_printf(mon, " memaddr: 0x%" PRIx64 "\n", se->memaddr); + monitor_printf(mon, " size: %" PRIu64 "\n", se->size); + monitor_printf(mon, " memdev: %s\n", se->memdev); + break; default: g_assert_not_reached(); } diff --git a/qapi/machine.json b/qapi/machine.json index 26c539fe2c..e2f01e9c15 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1194,13 +1194,36 @@ } } +## +# @SgxEPCDeviceInfo: +# +# Sgx EPC state information +# +# @id: device's ID +# +# @memaddr: physical address in memory, where device is mapped +# +# @size: size of memory that the device provides +# +# @memdev: memory backend linked with device +# +# Since: 6.2 +## +{ 'struct': 'SgxEPCDeviceInfo', + 'data': { '*id': 'str', + 'memaddr': 'size', + 'size': 'size', + 'memdev': 'str' + } +} + ## # @MemoryDeviceInfoKind: # # Since: 2.1 ## { 'enum': 'MemoryDeviceInfoKind', - 'data': [ 'dimm', 'nvdimm', 'virtio-pmem', 'virtio-mem' ] } + 'data': [ 'dimm', 'nvdimm', 'virtio-pmem', 'virtio-mem', 'sgx-epc' ] } ## # @PCDIMMDeviceInfoWrapper: @@ -1225,13 +1248,22 @@ ## { 'struct': 'VirtioMEMDeviceInfoWrapper', 'data': { 'data': 'VirtioMEMDeviceInfo' } } + +## +# @SgxEPCDeviceInfoWrapper: +# +# Since: 6.2 +## +{ 'struct': 'SgxEPCDeviceInfoWrapper', + 'data': { 'data': 'SgxEPCDeviceInfo' } } + ## # @MemoryDeviceInfo: # # Union containing information about a memory device # # nvdimm is included since 2.12. virtio-pmem is included since 4.1. -# virtio-mem is included since 5.1. +# virtio-mem is included since 5.1. sgx-epc is included since 6.2. # # Since: 2.1 ## @@ -1241,7 +1273,8 @@ 'data': { 'dimm': 'PCDIMMDeviceInfoWrapper', 'nvdimm': 'PCDIMMDeviceInfoWrapper', 'virtio-pmem': 'VirtioPMEMDeviceInfoWrapper', - 'virtio-mem': 'VirtioMEMDeviceInfoWrapper' + 'virtio-mem': 'VirtioMEMDeviceInfoWrapper', + 'sgx-epc': 'SgxEPCDeviceInfoWrapper' } } -- cgit v1.2.3-55-g7522 From 57d874c4c7a0acbaa076a166e3da093b6edbdb0f Mon Sep 17 00:00:00 2001 From: Yang Zhong Date: Fri, 10 Sep 2021 18:22:56 +0800 Subject: target/i386: Add HMP and QMP interfaces for SGX The QMP and HMP interfaces can be used by monitor or QMP tools to retrieve the SGX information from VM side when SGX is enabled on Intel platform. Signed-off-by: Yang Zhong Message-Id: <20210910102258.46648-2-yang.zhong@intel.com> Signed-off-by: Paolo Bonzini --- hmp-commands-info.hx | 15 +++++++++++++++ hw/i386/sgx-stub.c | 7 +++++++ hw/i386/sgx.c | 31 +++++++++++++++++++++++++++++++ include/hw/i386/sgx.h | 11 +++++++++++ include/monitor/hmp-target.h | 1 + qapi/misc-target.json | 43 +++++++++++++++++++++++++++++++++++++++++++ target/i386/monitor.c | 27 +++++++++++++++++++++++++++ tests/qtest/qmp-cmd-test.c | 1 + 8 files changed, 136 insertions(+) create mode 100644 include/hw/i386/sgx.h (limited to 'qapi') diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 27206ac049..4c966e8a6b 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -877,3 +877,18 @@ SRST ``info dirty_rate`` Display the vcpu dirty rate information. ERST + +#if defined(TARGET_I386) + { + .name = "sgx", + .args_type = "", + .params = "", + .help = "show intel SGX information", + .cmd = hmp_info_sgx, + }, +#endif + +SRST + ``info sgx`` + Show intel SGX information. +ERST diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c index 483c72bba6..485e16ecc1 100644 --- a/hw/i386/sgx-stub.c +++ b/hw/i386/sgx-stub.c @@ -1,6 +1,13 @@ #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; +} void pc_machine_init_sgx_epc(PCMachineState *pcms) { diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index 8a18cddc3f..ea75398575 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -17,6 +17,37 @@ #include "monitor/qdev.h" #include "qapi/error.h" #include "exec/address-spaces.h" +#include "hw/i386/sgx.h" + +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) { diff --git a/include/hw/i386/sgx.h b/include/hw/i386/sgx.h new file mode 100644 index 0000000000..2bf90b3f4f --- /dev/null +++ b/include/hw/i386/sgx.h @@ -0,0 +1,11 @@ +#ifndef QEMU_SGX_H +#define QEMU_SGX_H + +#include "qom/object.h" +#include "qapi/error.h" +#include "qemu/error-report.h" +#include "qapi/qapi-types-misc-target.h" + +SGXInfo *sgx_get_info(Error **errp); + +#endif diff --git a/include/monitor/hmp-target.h b/include/monitor/hmp-target.h index 60fc92722a..dc53add7ee 100644 --- a/include/monitor/hmp-target.h +++ b/include/monitor/hmp-target.h @@ -49,5 +49,6 @@ void hmp_info_tlb(Monitor *mon, const QDict *qdict); void hmp_mce(Monitor *mon, const QDict *qdict); void hmp_info_local_apic(Monitor *mon, const QDict *qdict); void hmp_info_io_apic(Monitor *mon, const QDict *qdict); +void hmp_info_sgx(Monitor *mon, const QDict *qdict); #endif /* MONITOR_HMP_TARGET_H */ diff --git a/qapi/misc-target.json b/qapi/misc-target.json index 3b05ad3dbf..e2a347cc23 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -333,3 +333,46 @@ { 'command': 'query-sev-attestation-report', 'data': { 'mnonce': 'str' }, 'returns': 'SevAttestationReport', 'if': 'TARGET_I386' } + +## +# @SGXInfo: +# +# Information about intel Safe Guard eXtension (SGX) support +# +# @sgx: true if SGX is supported +# +# @sgx1: true if SGX1 is supported +# +# @sgx2: true if SGX2 is supported +# +# @flc: true if FLC is supported +# +# @section-size: The EPC section size for guest +# +# Since: 6.2 +## +{ 'struct': 'SGXInfo', + 'data': { 'sgx': 'bool', + 'sgx1': 'bool', + 'sgx2': 'bool', + 'flc': 'bool', + 'section-size': 'uint64'}, + 'if': 'TARGET_I386' } + +## +# @query-sgx: +# +# Returns information about SGX +# +# Returns: @SGXInfo +# +# Since: 6.2 +# +# Example: +# +# -> { "execute": "query-sgx" } +# <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true, +# "flc": true, "section-size" : 0 } } +# +## +{ 'command': 'query-sgx', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } diff --git a/target/i386/monitor.c b/target/i386/monitor.c index 119211f0b0..d7384ba348 100644 --- a/target/i386/monitor.c +++ b/target/i386/monitor.c @@ -35,6 +35,7 @@ #include "qapi/qapi-commands-misc-target.h" #include "qapi/qapi-commands-misc.h" #include "hw/i386/pc.h" +#include "hw/i386/sgx.h" /* Perform linear address sign extension */ static hwaddr addr_canonical(CPUArchState *env, hwaddr addr) @@ -763,3 +764,29 @@ qmp_query_sev_attestation_report(const char *mnonce, Error **errp) { return sev_get_attestation_report(mnonce, errp); } + +SGXInfo *qmp_query_sgx(Error **errp) +{ + return sgx_get_info(errp); +} + +void hmp_info_sgx(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + g_autoptr(SGXInfo) info = qmp_query_sgx(&err); + + if (err) { + error_report_err(err); + return; + } + monitor_printf(mon, "SGX support: %s\n", + info->sgx ? "enabled" : "disabled"); + monitor_printf(mon, "SGX1 support: %s\n", + info->sgx1 ? "enabled" : "disabled"); + monitor_printf(mon, "SGX2 support: %s\n", + info->sgx2 ? "enabled" : "disabled"); + monitor_printf(mon, "FLC support: %s\n", + info->flc ? "enabled" : "disabled"); + monitor_printf(mon, "size: %" PRIu64 "\n", + info->section_size); +} diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c index c98b78d033..b75f3364f3 100644 --- a/tests/qtest/qmp-cmd-test.c +++ b/tests/qtest/qmp-cmd-test.c @@ -100,6 +100,7 @@ static bool query_is_ignored(const char *cmd) /* Success depends on Host or Hypervisor SEV support */ "query-sev", "query-sev-capabilities", + "query-sgx", NULL }; int i; -- cgit v1.2.3-55-g7522 From 0205c4fa1ea35d569b4c2f63adacef438c1e8f53 Mon Sep 17 00:00:00 2001 From: Yang Zhong Date: Fri, 10 Sep 2021 18:22:57 +0800 Subject: target/i386: Add the query-sgx-capabilities QMP command Libvirt can use query-sgx-capabilities to get the host sgx capabilities to decide how to allocate SGX EPC size to VM. Signed-off-by: Yang Zhong Message-Id: <20210910102258.46648-3-yang.zhong@intel.com> Signed-off-by: Paolo Bonzini --- hw/i386/sgx-stub.c | 6 +++++ hw/i386/sgx.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ include/hw/i386/sgx.h | 1 + qapi/misc-target.json | 18 +++++++++++++ target/i386/monitor.c | 5 ++++ tests/qtest/qmp-cmd-test.c | 1 + 6 files changed, 97 insertions(+) (limited to 'qapi') diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c index 485e16ecc1..3be9f5ca32 100644 --- a/hw/i386/sgx-stub.c +++ b/hw/i386/sgx-stub.c @@ -9,6 +9,12 @@ SGXInfo *sgx_get_info(Error **errp) 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)); diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index ea75398575..e481e9358f 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -18,6 +18,72 @@ #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) { diff --git a/include/hw/i386/sgx.h b/include/hw/i386/sgx.h index 2bf90b3f4f..16fc25725c 100644 --- a/include/hw/i386/sgx.h +++ b/include/hw/i386/sgx.h @@ -7,5 +7,6 @@ #include "qapi/qapi-types-misc-target.h" SGXInfo *sgx_get_info(Error **errp); +SGXInfo *sgx_get_capabilities(Error **errp); #endif diff --git a/qapi/misc-target.json b/qapi/misc-target.json index e2a347cc23..594fbd1577 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -376,3 +376,21 @@ # ## { 'command': 'query-sgx', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } + +## +# @query-sgx-capabilities: +# +# Returns information from host SGX capabilities +# +# Returns: @SGXInfo +# +# Since: 6.2 +# +# Example: +# +# -> { "execute": "query-sgx-capabilities" } +# <- { "return": { "sgx": true, "sgx1" : true, "sgx2" : true, +# "flc": true, "section-size" : 0 } } +# +## +{ 'command': 'query-sgx-capabilities', 'returns': 'SGXInfo', 'if': 'TARGET_I386' } diff --git a/target/i386/monitor.c b/target/i386/monitor.c index d7384ba348..196c1c9e77 100644 --- a/target/i386/monitor.c +++ b/target/i386/monitor.c @@ -790,3 +790,8 @@ void hmp_info_sgx(Monitor *mon, const QDict *qdict) monitor_printf(mon, "size: %" PRIu64 "\n", info->section_size); } + +SGXInfo *qmp_query_sgx_capabilities(Error **errp) +{ + return sgx_get_capabilities(errp); +} diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c index b75f3364f3..1af2f74c28 100644 --- a/tests/qtest/qmp-cmd-test.c +++ b/tests/qtest/qmp-cmd-test.c @@ -101,6 +101,7 @@ static bool query_is_ignored(const char *cmd) "query-sev", "query-sev-capabilities", "query-sgx", + "query-sgx-capabilities", NULL }; int i; -- cgit v1.2.3-55-g7522 From 653163fcbcab72499ff1c2011f3552811d957729 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 7 Sep 2021 16:19:13 +0400 Subject: build-sys: add HAVE_IPPROTO_MPTCP The QAPI schema shouldn't rely on C system headers #define, but on configure-time project #define, so we can express the build condition in a C-independent way. Signed-off-by: Marc-André Lureau Message-Id: <20210907121943.3498701-3-marcandre.lureau@redhat.com> Signed-off-by: Paolo Bonzini --- io/dns-resolver.c | 2 +- meson.build | 2 ++ qapi/sockets.json | 2 +- util/qemu-sockets.c | 6 +++--- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'qapi') diff --git a/io/dns-resolver.c b/io/dns-resolver.c index a5946a93bf..53b0e8407a 100644 --- a/io/dns-resolver.c +++ b/io/dns-resolver.c @@ -122,7 +122,7 @@ static int qio_dns_resolver_lookup_sync_inet(QIODNSResolver *resolver, .ipv4 = iaddr->ipv4, .has_ipv6 = iaddr->has_ipv6, .ipv6 = iaddr->ipv6, -#ifdef IPPROTO_MPTCP +#ifdef HAVE_IPPROTO_MPTCP .has_mptcp = iaddr->has_mptcp, .mptcp = iaddr->mptcp, #endif diff --git a/meson.build b/meson.build index fbdab3063b..60f4f45165 100644 --- a/meson.build +++ b/meson.build @@ -1374,6 +1374,8 @@ config_host_data.set('HAVE_OPTRESET', cc.has_header_symbol('getopt.h', 'optreset')) config_host_data.set('HAVE_UTMPX', cc.has_header_symbol('utmpx.h', 'struct utmpx')) +config_host_data.set('HAVE_IPPROTO_MPTCP', + cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP')) # has_member config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID', diff --git a/qapi/sockets.json b/qapi/sockets.json index ef4b16d6f2..5773d9fcc4 100644 --- a/qapi/sockets.json +++ b/qapi/sockets.json @@ -69,7 +69,7 @@ '*ipv4': 'bool', '*ipv6': 'bool', '*keep-alive': 'bool', - '*mptcp': { 'type': 'bool', 'if': 'IPPROTO_MPTCP' } } } + '*mptcp': { 'type': 'bool', 'if': 'HAVE_IPPROTO_MPTCP' } } } ## # @UnixSocketAddress: diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 72216ef980..0585e7a629 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -278,7 +278,7 @@ static int inet_listen_saddr(InetSocketAddress *saddr, /* create socket + bind/listen */ for (e = res; e != NULL; e = e->ai_next) { -#ifdef IPPROTO_MPTCP +#ifdef HAVE_IPPROTO_MPTCP if (saddr->has_mptcp && saddr->mptcp) { e->ai_protocol = IPPROTO_MPTCP; } @@ -462,7 +462,7 @@ int inet_connect_saddr(InetSocketAddress *saddr, Error **errp) error_free(local_err); local_err = NULL; -#ifdef IPPROTO_MPTCP +#ifdef HAVE_IPPROTO_MPTCP if (saddr->has_mptcp && saddr->mptcp) { e->ai_protocol = IPPROTO_MPTCP; } @@ -699,7 +699,7 @@ int inet_parse(InetSocketAddress *addr, const char *str, Error **errp) } addr->has_keep_alive = true; } -#ifdef IPPROTO_MPTCP +#ifdef HAVE_IPPROTO_MPTCP begin = strstr(optstr, ",mptcp"); if (begin) { if (inet_parse_flag("mptcp", begin + strlen(",mptcp"), -- cgit v1.2.3-55-g7522