From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 49EFEC32751 for ; Tue, 6 Aug 2019 18:57:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1FDDD20C01 for ; Tue, 6 Aug 2019 18:57:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726626AbfHFS5J (ORCPT ); Tue, 6 Aug 2019 14:57:09 -0400 Received: from mga06.intel.com ([134.134.136.31]:40919 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726412AbfHFS5I (ORCPT ); Tue, 6 Aug 2019 14:57:08 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 06 Aug 2019 11:57:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,353,1559545200"; d="scan'208";a="176715094" Received: from sjchrist-coffee.jf.intel.com ([10.54.74.41]) by orsmga003.jf.intel.com with ESMTP; 06 Aug 2019 11:56:59 -0700 From: Sean Christopherson To: Eduardo Habkost , Igor Mammedov , "Michael S. Tsirkin" , Marcel Apfelbaum , Paolo Bonzini , Richard Henderson , Cornelia Huck , Eric Blake , Markus Armbruster , Marcelo Tosatti Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org Subject: [RFC PATCH 10/20] i386: Update SGX CPUID info according to hardware/KVM/user input Date: Tue, 6 Aug 2019 11:56:39 -0700 Message-Id: <20190806185649.2476-11-sean.j.christopherson@intel.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20190806185649.2476-1-sean.j.christopherson@intel.com> References: <20190806185649.2476-1-sean.j.christopherson@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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 --- hw/i386/sgx-epc.c | 17 +++++++++ include/hw/i386/sgx-epc.h | 1 + target/i386/cpu.c | 76 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/hw/i386/sgx-epc.c b/hw/i386/sgx-epc.c index 09aba1f8ea..7f26e9cb10 100644 --- a/hw/i386/sgx-epc.c +++ b/hw/i386/sgx-epc.c @@ -181,6 +181,23 @@ static void sgx_epc_register_types(void) type_init(sgx_epc_register_types) +int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size) +{ + PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); + SGXEPCDevice *epc; + + if (pcms->sgx_epc == NULL || pcms->sgx_epc->nr_sections <= section_nr) { + return 1; + } + + epc = pcms->sgx_epc->sections[section_nr]; + + *addr = epc->addr; + *size = memory_device_get_region_size(MEMORY_DEVICE(epc), &error_fatal); + + return 0; +} + static int sgx_epc_set_property(void *opaque, const char *name, const char *value, Error **errp) diff --git a/include/hw/i386/sgx-epc.h b/include/hw/i386/sgx-epc.h index 562c66148f..91ed4773e3 100644 --- a/include/hw/i386/sgx-epc.h +++ b/include/hw/i386/sgx-epc.h @@ -58,5 +58,6 @@ typedef struct SGXEPCState { extern int sgx_epc_enabled; void pc_machine_init_sgx_epc(PCMachineState *pcms); +int sgx_epc_get_section(int section_nr, uint64_t *addr, uint64_t *size); #endif diff --git a/target/i386/cpu.c b/target/i386/cpu.c index ab08c1765e..1bb9586230 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -57,6 +57,7 @@ #include "hw/xen/xen.h" #include "hw/i386/apic_internal.h" #include "hw/boards.h" +#include "hw/i386/sgx-epc.h" #endif #include "disas/capstone.h" @@ -4359,6 +4360,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 { *eax = 0; *ebx = 0; @@ -4488,6 +4508,62 @@ 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]; + } else { + *eax &= env->features[FEAT_SGX_12_1_EAX]; + *ebx &= env->features[FEAT_SGX_12_1_EBX]; + *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; -- 2.22.0