From 1dec2e1f19fdb39a0340356ec2d77233837b3d68 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 19 Jul 2021 19:21:15 +0800 Subject: i386: Update SGX CPUID info according to hardware/KVM/user input Expose SGX to the guest if and only if KVM is enabled and supports virtualization of SGX. While the majority of ENCLS can be emulated to some degree, because SGX uses a hardware-based root of trust, the attestation aspects of SGX cannot be emulated in software, i.e. ultimately emulation will fail as software cannot generate a valid quote/report. The complexity of partially emulating SGX in Qemu far outweighs the value added, e.g. an SGX specific simulator for userspace applications can emulate SGX for development and testing purposes. Note, access to the PROVISIONKEY is not yet advertised to the guest as KVM blocks access to the PROVISIONKEY by default and requires userspace to provide additional credentials (via ioctl()) to expose PROVISIONKEY. Signed-off-by: Sean Christopherson Signed-off-by: Yang Zhong Message-Id: <20210719112136.57018-13-yang.zhong@intel.com> Signed-off-by: Paolo Bonzini --- hw/i386/sgx-stub.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 hw/i386/sgx-stub.c (limited to 'hw/i386/sgx-stub.c') diff --git a/hw/i386/sgx-stub.c b/hw/i386/sgx-stub.c new file mode 100644 index 0000000000..483c72bba6 --- /dev/null +++ b/hw/i386/sgx-stub.c @@ -0,0 +1,13 @@ +#include "qemu/osdep.h" +#include "hw/i386/pc.h" +#include "hw/i386/sgx-epc.h" + +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(); +} -- cgit 1.4.1 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 'hw/i386/sgx-stub.c') 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 1.4.1 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 'hw/i386/sgx-stub.c') 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 1.4.1