|
@@ -36,6 +36,7 @@
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
#include "exec/address-spaces.h"
|
|
|
#include "hw/boards.h"
|
|
|
+#include "hw/i386/sgx-epc.h"
|
|
|
#endif
|
|
|
|
|
|
#include "disas/capstone.h"
|
|
@@ -5334,6 +5335,25 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
|
*ecx |= CPUID_7_0_ECX_OSPKE;
|
|
|
}
|
|
|
*edx = env->features[FEAT_7_0_EDX]; /* Feature flags */
|
|
|
+
|
|
|
+ /*
|
|
|
+ * SGX cannot be emulated in software. If hardware does not
|
|
|
+ * support enabling SGX and/or SGX flexible launch control,
|
|
|
+ * then we need to update the VM's CPUID values accordingly.
|
|
|
+ */
|
|
|
+ if ((*ebx & CPUID_7_0_EBX_SGX) &&
|
|
|
+ (!kvm_enabled() ||
|
|
|
+ !(kvm_arch_get_supported_cpuid(cs->kvm_state, 0x7, 0, R_EBX) &
|
|
|
+ CPUID_7_0_EBX_SGX))) {
|
|
|
+ *ebx &= ~CPUID_7_0_EBX_SGX;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((*ecx & CPUID_7_0_ECX_SGX_LC) &&
|
|
|
+ (!(*ebx & CPUID_7_0_EBX_SGX) || !kvm_enabled() ||
|
|
|
+ !(kvm_arch_get_supported_cpuid(cs->kvm_state, 0x7, 0, R_ECX) &
|
|
|
+ CPUID_7_0_ECX_SGX_LC))) {
|
|
|
+ *ecx &= ~CPUID_7_0_ECX_SGX_LC;
|
|
|
+ }
|
|
|
} else if (count == 1) {
|
|
|
*eax = env->features[FEAT_7_1_EAX];
|
|
|
*ebx = 0;
|
|
@@ -5469,6 +5489,63 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
|
|
}
|
|
|
break;
|
|
|
}
|
|
|
+ case 0x12:
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
+ if (!kvm_enabled() ||
|
|
|
+ !(env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_SGX)) {
|
|
|
+ *eax = *ebx = *ecx = *edx = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * SGX sub-leafs CPUID.0x12.{0x2..N} enumerate EPC sections. Retrieve
|
|
|
+ * the EPC properties, e.g. confidentiality and integrity, from the
|
|
|
+ * host's first EPC section, i.e. assume there is one EPC section or
|
|
|
+ * that all EPC sections have the same security properties.
|
|
|
+ */
|
|
|
+ if (count > 1) {
|
|
|
+ uint64_t epc_addr, epc_size;
|
|
|
+
|
|
|
+ if (sgx_epc_get_section(count - 2, &epc_addr, &epc_size)) {
|
|
|
+ *eax = *ebx = *ecx = *edx = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ host_cpuid(index, 2, eax, ebx, ecx, edx);
|
|
|
+ *eax = (uint32_t)(epc_addr & 0xfffff000) | 0x1;
|
|
|
+ *ebx = (uint32_t)(epc_addr >> 32);
|
|
|
+ *ecx = (uint32_t)(epc_size & 0xfffff000) | (*ecx & 0xf);
|
|
|
+ *edx = (uint32_t)(epc_size >> 32);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * SGX sub-leafs CPUID.0x12.{0x0,0x1} are heavily dependent on hardware
|
|
|
+ * and KVM, i.e. QEMU cannot emulate features to override what KVM
|
|
|
+ * supports. Features can be further restricted by userspace, but not
|
|
|
+ * made more permissive.
|
|
|
+ */
|
|
|
+ *eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EAX);
|
|
|
+ *ebx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EBX);
|
|
|
+ *ecx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_ECX);
|
|
|
+ *edx = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x12, count, R_EDX);
|
|
|
+
|
|
|
+ if (count == 0) {
|
|
|
+ *eax &= env->features[FEAT_SGX_12_0_EAX];
|
|
|
+ *ebx &= env->features[FEAT_SGX_12_0_EBX];
|
|
|
+ } else {
|
|
|
+ *eax &= env->features[FEAT_SGX_12_1_EAX];
|
|
|
+ *ebx &= 0; /* ebx reserve */
|
|
|
+ *ecx &= env->features[FEAT_XSAVE_COMP_LO];
|
|
|
+ *edx &= env->features[FEAT_XSAVE_COMP_HI];
|
|
|
+
|
|
|
+ /* FP and SSE are always allowed regardless of XSAVE/XCR0. */
|
|
|
+ *ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK;
|
|
|
+
|
|
|
+ /* Access to PROVISIONKEY requires additional credentials. */
|
|
|
+ *eax &= ~(1U << 4);
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ break;
|
|
|
case 0x14: {
|
|
|
/* Intel Processor Trace Enumeration */
|
|
|
*eax = 0;
|