aboutsummaryrefslogtreecommitdiff
path: root/target/i386
diff options
context:
space:
mode:
Diffstat (limited to 'target/i386')
-rw-r--r--target/i386/cpu.c5
-rw-r--r--target/i386/kvm/kvm.c29
-rw-r--r--target/i386/kvm/kvm_i386.h2
3 files changed, 35 insertions, 1 deletions
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 8a62986..de58599 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5542,7 +5542,10 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
*ecx |= XSTATE_FP_MASK | XSTATE_SSE_MASK;
/* Access to PROVISIONKEY requires additional credentials. */
- *eax &= ~(1U << 4);
+ if ((*eax & (1U << 4)) &&
+ !kvm_enable_sgx_provisioning(cs->kvm_state)) {
+ *eax &= ~(1U << 4);
+ }
}
#endif
break;
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 6dc4016..488926a 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -4644,6 +4644,35 @@ void kvm_arch_update_guest_debug(CPUState *cpu, struct kvm_guest_debug *dbg)
}
}
+static bool has_sgx_provisioning;
+
+static bool __kvm_enable_sgx_provisioning(KVMState *s)
+{
+ int fd, ret;
+
+ if (!kvm_vm_check_extension(s, KVM_CAP_SGX_ATTRIBUTE)) {
+ return false;
+ }
+
+ fd = qemu_open_old("/dev/sgx_provision", O_RDONLY);
+ if (fd < 0) {
+ return false;
+ }
+
+ ret = kvm_vm_enable_cap(s, KVM_CAP_SGX_ATTRIBUTE, 0, fd);
+ if (ret) {
+ error_report("Could not enable SGX PROVISIONKEY: %s", strerror(-ret));
+ exit(1);
+ }
+ close(fd);
+ return true;
+}
+
+bool kvm_enable_sgx_provisioning(KVMState *s)
+{
+ return MEMORIZE(__kvm_enable_sgx_provisioning(s), has_sgx_provisioning);
+}
+
static bool host_supports_vmx(void)
{
uint32_t ecx, unused;
diff --git a/target/i386/kvm/kvm_i386.h b/target/i386/kvm/kvm_i386.h
index 54667b3..a978509 100644
--- a/target/i386/kvm/kvm_i386.h
+++ b/target/i386/kvm/kvm_i386.h
@@ -51,4 +51,6 @@ bool kvm_hyperv_expand_features(X86CPU *cpu, Error **errp);
uint64_t kvm_swizzle_msi_ext_dest_id(uint64_t address);
+bool kvm_enable_sgx_provisioning(KVMState *s);
+
#endif