Received: by 2002:a05:7412:d8a:b0:e2:908c:2ebd with SMTP id b10csp3054084rdg; Tue, 17 Oct 2023 03:16:15 -0700 (PDT) X-Google-Smtp-Source: AGHT+IESmSPIXIc6oqEHV5BRCJ+cDhh7xOJRf41pA17+PQ6SYwvkJdxYFkpq8QgR9xFZdOZBfEDe X-Received: by 2002:a05:6a20:432c:b0:159:f884:4d72 with SMTP id h44-20020a056a20432c00b00159f8844d72mr1646474pzk.42.1697537775304; Tue, 17 Oct 2023 03:16:15 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1697537775; cv=none; d=google.com; s=arc-20160816; b=tuD66AB7msdhf2jOh0wrO+dRgvtCm6GCGI2zjXEpOo5jhEXb9andwkLF8eYXhWIAgl MYtYI0tfTSxuX4As03Oa/fSdcygUYp2X2genDyo6Q+AnNIg0EmtYWcxb3KdjYeGDlTYo W9Cmk04zIEGZgQMS72n1lYgvfFiPuDorT7I3B15orWtLsQY/Xn/TwrtxnP2Yf0covqCV Ezy8+zGXvFAb7JhL9OMYqTxdUfV9LD8H19UTogmvOjayRn0VQ6JXeYxheKR/hu/YTtqF wicrgT3crd4asuKIdSkFKujcncNp22Gyi9lN4FFcdXrD0GlXrnaBqDpkcARVpU8BhWLL KMrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=1JjN4QSSmR5pNsvj01lSnDHTqOqiRjo2Y82VTOTR9wY=; fh=WBgbLtMencYhgeHuu2sUs5b9THiYLgy17d2w1N+xuf4=; b=WPgzSD2SBmvpSjWEESFXHkw206kL9zPx+/zR/syG8QVc6za501zNReLCk4CK3XbU6e V/QokpM4VB0yXDIN17QIengytABAQoEwiM4b7B6aw7uj8skbei8/RN+xGgCdD3qNvgel oW4e78NsPVESuOacMYCdbwp26z43YjIQyI7fgwTNSK33kmOoHInFCDux5VcgnIwznnCt PCQmvqgcwSjQidip6ehMK5CJHRWdt3rntV+c5MLIk9BQB9s8Xtwf9wr9awpcuMPLlsIn GnitGQ3l9jJR6ZjqeVtq0B1HIUOUxoXO3KrqxkFTMm3X04aBgoi2yeRyw7I1Cz2x0Hoi Ehmg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Wqp8AOXt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from agentk.vger.email (agentk.vger.email. [2620:137:e000::3:2]) by mx.google.com with ESMTPS id s135-20020a63778d000000b0059b85f72144si1328510pgc.372.2023.10.17.03.16.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 17 Oct 2023 03:16:15 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) client-ip=2620:137:e000::3:2; Authentication-Results: mx.google.com; dkim=pass header.i=@intel.com header.s=Intel header.b=Wqp8AOXt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:2 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by agentk.vger.email (Postfix) with ESMTP id 5755A807F4BB; Tue, 17 Oct 2023 03:15:36 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at agentk.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234970AbjJQKPY (ORCPT + 99 others); Tue, 17 Oct 2023 06:15:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32778 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234934AbjJQKPS (ORCPT ); Tue, 17 Oct 2023 06:15:18 -0400 Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.100]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 96905F9; Tue, 17 Oct 2023 03:15:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1697537710; x=1729073710; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kVsmePzX+1CQEv8I/jGhrQ8MKt6j8PZKIuV1GGpP0v4=; b=Wqp8AOXtWEgAPTlcGGjYRLIX7pk0mTfu/K0CwzONeOpvmV/zhs6znZHP 550X5WvxRCuyB3Uj3K9XqGqFhZ/izIjHlNQaK3TUgTt9sCsKVdrghvKcK t9clgeMeb3+cjOb0dNNgkPQ8aPEkk85raBg4+jnya5NwldQ4fPBB8AF1t kxiWe/vxLO5z4zBcJMSS6+15G5/rCDNhucwsRMpoJQ98sxy2psLbeHiym HdtcXQJocEHtn3NXIUtP3+Vrgh+6A+5sQUamNZSADpUAoh68pt8LwyzGl lJ9Cs3IqLgImHg2RcMAjgHb8XVzOfgr5PB2SHB2MoLsOgSZfyS9SgV1zy g==; X-IronPort-AV: E=McAfee;i="6600,9927,10865"; a="452226684" X-IronPort-AV: E=Sophos;i="6.03,231,1694761200"; d="scan'208";a="452226684" Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Oct 2023 03:15:10 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10865"; a="872503268" X-IronPort-AV: E=Sophos;i="6.03,231,1694761200"; d="scan'208";a="872503268" Received: from chowe-mobl.amr.corp.intel.com (HELO khuang2-desk.gar.corp.intel.com) ([10.255.229.64]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Oct 2023 03:15:04 -0700 From: Kai Huang To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: x86@kernel.org, dave.hansen@intel.com, kirill.shutemov@linux.intel.com, peterz@infradead.org, tony.luck@intel.com, tglx@linutronix.de, bp@alien8.de, mingo@redhat.com, hpa@zytor.com, seanjc@google.com, pbonzini@redhat.com, rafael@kernel.org, david@redhat.com, dan.j.williams@intel.com, len.brown@intel.com, ak@linux.intel.com, isaku.yamahata@intel.com, ying.huang@intel.com, chao.gao@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com, nik.borisov@suse.com, bagasdotme@gmail.com, sagis@google.com, imammedo@redhat.com, kai.huang@intel.com Subject: [PATCH v14 01/23] x86/virt/tdx: Detect TDX during kernel boot Date: Tue, 17 Oct 2023 23:14:25 +1300 Message-ID: <121aab11b48b4e6550cfe6d23b4daab744ee2076.1697532085.git.kai.huang@intel.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-0.9 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on agentk.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (agentk.vger.email [0.0.0.0]); Tue, 17 Oct 2023 03:15:36 -0700 (PDT) Intel Trust Domain Extensions (TDX) protects guest VMs from malicious host and certain physical attacks. A CPU-attested software module called 'the TDX module' runs inside a new isolated memory range as a trusted hypervisor to manage and run protected VMs. Pre-TDX Intel hardware has support for a memory encryption architecture called MKTME. The memory encryption hardware underpinning MKTME is also used for Intel TDX. TDX ends up "stealing" some of the physical address space from the MKTME architecture for crypto-protection to VMs. The BIOS is responsible for partitioning the "KeyID" space between legacy MKTME and TDX. The KeyIDs reserved for TDX are called 'TDX private KeyIDs' or 'TDX KeyIDs' for short. During machine boot, TDX microcode verifies that the BIOS programmed TDX private KeyIDs consistently and correctly programmed across all CPU packages. The MSRs are locked in this state after verification. This is why MSR_IA32_MKTME_KEYID_PARTITIONING gets used for TDX enumeration: it indicates not just that the hardware supports TDX, but that all the boot-time security checks passed. The TDX module is expected to be loaded by the BIOS when it enables TDX, but the kernel needs to properly initialize it before it can be used to create and run any TDX guests. The TDX module will be initialized by the KVM subsystem when KVM wants to use TDX. Add a new early_initcall(tdx_init) to detect the TDX by detecting TDX private KeyIDs. Also add a function to report whether TDX is enabled by the BIOS. Similar to AMD SME, kexec() will use it to determine whether cache flush is needed. The TDX module itself requires one TDX KeyID as the 'TDX global KeyID' to protect its metadata. Each TDX guest also needs a TDX KeyID for its own protection. Just use the first TDX KeyID as the global KeyID and leave the rest for TDX guests. If no TDX KeyID is left for TDX guests, disable TDX as initializing the TDX module alone is useless. Signed-off-by: Kai Huang Reviewed-by: Kirill A. Shutemov Reviewed-by: Isaku Yamahata Reviewed-by: David Hildenbrand Reviewed-by: Dave Hansen --- v13 -> v14: - "tdx:" -> "virt/tdx:" (internal) - Add Dave's tag --- arch/x86/include/asm/msr-index.h | 3 ++ arch/x86/include/asm/tdx.h | 4 ++ arch/x86/virt/vmx/tdx/Makefile | 2 +- arch/x86/virt/vmx/tdx/tdx.c | 90 ++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 arch/x86/virt/vmx/tdx/tdx.c diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 1d111350197f..7a44cac70e9f 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -535,6 +535,9 @@ #define MSR_RELOAD_PMC0 0x000014c1 #define MSR_RELOAD_FIXED_CTR0 0x00001309 +/* KeyID partitioning between MKTME and TDX */ +#define MSR_IA32_MKTME_KEYID_PARTITIONING 0x00000087 + /* * AMD64 MSRs. Not complete. See the architecture manual for a more * complete list. diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index adcbe3f1de30..a252328734c7 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -81,6 +81,10 @@ static inline long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, u64 __seamcall(u64 fn, struct tdx_module_args *args); u64 __seamcall_ret(u64 fn, struct tdx_module_args *args); u64 __seamcall_saved_ret(u64 fn, struct tdx_module_args *args); + +bool platform_tdx_enabled(void); +#else +static inline bool platform_tdx_enabled(void) { return false; } #endif /* CONFIG_INTEL_TDX_HOST */ #endif /* !__ASSEMBLY__ */ diff --git a/arch/x86/virt/vmx/tdx/Makefile b/arch/x86/virt/vmx/tdx/Makefile index 46ef8f73aebb..90da47eb85ee 100644 --- a/arch/x86/virt/vmx/tdx/Makefile +++ b/arch/x86/virt/vmx/tdx/Makefile @@ -1,2 +1,2 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-y += seamcall.o +obj-y += seamcall.o tdx.o diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c new file mode 100644 index 000000000000..13d22ea2e2d9 --- /dev/null +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright(c) 2023 Intel Corporation. + * + * Intel Trusted Domain Extensions (TDX) support + */ + +#define pr_fmt(fmt) "virt/tdx: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +static u32 tdx_global_keyid __ro_after_init; +static u32 tdx_guest_keyid_start __ro_after_init; +static u32 tdx_nr_guest_keyids __ro_after_init; + +static int __init record_keyid_partitioning(u32 *tdx_keyid_start, + u32 *nr_tdx_keyids) +{ + u32 _nr_mktme_keyids, _tdx_keyid_start, _nr_tdx_keyids; + int ret; + + /* + * IA32_MKTME_KEYID_PARTIONING: + * Bit [31:0]: Number of MKTME KeyIDs. + * Bit [63:32]: Number of TDX private KeyIDs. + */ + ret = rdmsr_safe(MSR_IA32_MKTME_KEYID_PARTITIONING, &_nr_mktme_keyids, + &_nr_tdx_keyids); + if (ret) + return -ENODEV; + + if (!_nr_tdx_keyids) + return -ENODEV; + + /* TDX KeyIDs start after the last MKTME KeyID. */ + _tdx_keyid_start = _nr_mktme_keyids + 1; + + *tdx_keyid_start = _tdx_keyid_start; + *nr_tdx_keyids = _nr_tdx_keyids; + + return 0; +} + +static int __init tdx_init(void) +{ + u32 tdx_keyid_start, nr_tdx_keyids; + int err; + + err = record_keyid_partitioning(&tdx_keyid_start, &nr_tdx_keyids); + if (err) + return err; + + pr_info("BIOS enabled: private KeyID range [%u, %u)\n", + tdx_keyid_start, tdx_keyid_start + nr_tdx_keyids); + + /* + * The TDX module itself requires one 'global KeyID' to protect + * its metadata. If there's only one TDX KeyID, there won't be + * any left for TDX guests thus there's no point to enable TDX + * at all. + */ + if (nr_tdx_keyids < 2) { + pr_err("initialization failed: too few private KeyIDs available.\n"); + return -ENODEV; + } + + /* + * Just use the first TDX KeyID as the 'global KeyID' and + * leave the rest for TDX guests. + */ + tdx_global_keyid = tdx_keyid_start; + tdx_guest_keyid_start = tdx_keyid_start + 1; + tdx_nr_guest_keyids = nr_tdx_keyids - 1; + + return 0; +} +early_initcall(tdx_init); + +/* Return whether the BIOS has enabled TDX */ +bool platform_tdx_enabled(void) +{ + return !!tdx_global_keyid; +} -- 2.41.0