From patchwork Fri Dec 9 06:52:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai Huang X-Patchwork-Id: 13069307 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 14BCBC4332F for ; Fri, 9 Dec 2022 06:54:12 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id A8C958E0007; Fri, 9 Dec 2022 01:54:11 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id A3CB38E0001; Fri, 9 Dec 2022 01:54:11 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 8DD458E0007; Fri, 9 Dec 2022 01:54:11 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 7C64E8E0001 for ; Fri, 9 Dec 2022 01:54:11 -0500 (EST) Received: from smtpin10.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 5DB9C1C6A44 for ; Fri, 9 Dec 2022 06:54:11 +0000 (UTC) X-FDA: 80221853502.10.9F4D02F Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by imf20.hostedemail.com (Postfix) with ESMTP id 6E9EA1C000B for ; Fri, 9 Dec 2022 06:54:09 +0000 (UTC) Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=hOinkxCf; dmarc=pass (policy=none) header.from=intel.com; spf=pass (imf20.hostedemail.com: domain of kai.huang@intel.com designates 134.134.136.24 as permitted sender) smtp.mailfrom=kai.huang@intel.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1670568849; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=eTFP9Rxc8hi5SwbEr9DLcegkTab2VPyPEMrCEn9AXz8=; b=WXnYqNHruiyZ7iG+baFsXObu4KShkMIP7jn7/AiQ/bOgzqM8Ha6PLYEIepuepM6q3DpXT0 UUfWkK/VydJ5zGZqXqEMIs/a6xypF1v1eJKRIU0y3wciDwfVrEZ6KajldogaSxo4Qfp2c1 FTeZf6eZ0Z7Q5eKV1zRU99g0d6VapAc= ARC-Authentication-Results: i=1; imf20.hostedemail.com; dkim=pass header.d=intel.com header.s=Intel header.b=hOinkxCf; dmarc=pass (policy=none) header.from=intel.com; spf=pass (imf20.hostedemail.com: domain of kai.huang@intel.com designates 134.134.136.24 as permitted sender) smtp.mailfrom=kai.huang@intel.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1670568849; a=rsa-sha256; cv=none; b=XmL8sW5qjpLytIb1n997kw6WcAPMAQ/HgRoMupQ1DMSgUx+fM+7N8qst0cTf1nkUF0oM9r /2ypJ/OQMA2SWXRDJYpk+oQlpus/R/M4psrlHOAf3IcJloCl3LgiyaNUsTPptRgPvNO5VG 0s9c4bd5jHE+PnE4yvWLytShUb6wBZw= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1670568849; x=1702104849; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=r1pswkKPmCuwe3o1L5UTwD6LpxkqI/Lu1UdlGzXTNBc=; b=hOinkxCf5hnhomql1M5FrOSuMQQYlSFkFXGTBtFfETfXvisGEl7rXOMn MtGY/HdDbCd9VlJizNPRc7wgdwa+hSMmciDlOVg1FpINr+xvr2VHObG4X cCV4kYxuMdE8IdgVhIOtEyLq/uUZ5qW6JpclT73KE5WjhR/yzTWVrqjgg B1r0BoYmkvY6pYWwBKc78Bt4ESPw1j4iFGSiJFxLfpnDxai4/bqnNvPy3 zvRJ/tTveDVk/zvZEUwwZ/YlykWjbWsZAGdF458S9qiTQp9kmS4WmZL43 vi6nrYJMRU/Aw/MiIdxYLj1oNDsTmrSlkANTUDyJU3YPi5nKaBVpdTNzh A==; X-IronPort-AV: E=McAfee;i="6500,9779,10555"; a="318551478" X-IronPort-AV: E=Sophos;i="5.96,230,1665471600"; d="scan'208";a="318551478" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Dec 2022 22:54:09 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10555"; a="679837108" X-IronPort-AV: E=Sophos;i="5.96,230,1665471600"; d="scan'208";a="679837108" Received: from omiramon-mobl1.amr.corp.intel.com (HELO khuang2-desk.gar.corp.intel.com) ([10.212.28.82]) by orsmga001-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 08 Dec 2022 22:54:02 -0800 From: Kai Huang To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: linux-mm@kvack.org, dave.hansen@intel.com, peterz@infradead.org, tglx@linutronix.de, seanjc@google.com, pbonzini@redhat.com, dan.j.williams@intel.com, rafael.j.wysocki@intel.com, kirill.shutemov@linux.intel.com, ying.huang@intel.com, reinette.chatre@intel.com, len.brown@intel.com, tony.luck@intel.com, ak@linux.intel.com, isaku.yamahata@intel.com, chao.gao@intel.com, sathyanarayanan.kuppuswamy@linux.intel.com, bagasdotme@gmail.com, sagis@google.com, imammedo@redhat.com, kai.huang@intel.com Subject: [PATCH v8 13/16] x86/virt/tdx: Configure global KeyID on all packages Date: Fri, 9 Dec 2022 19:52:34 +1300 Message-Id: <383a2fb52a36d1e772bc547c289c5aeb8ea5d9cb.1670566861.git.kai.huang@intel.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: References: MIME-Version: 1.0 X-Rspamd-Queue-Id: 6E9EA1C000B X-Rspamd-Server: rspam09 X-Rspam-User: X-Stat-Signature: zgu8z9srnexx6wehmhu1y4w5kkdmu7g9 X-HE-Tag: 1670568849-62093 X-HE-Meta: U2FsdGVkX19MyLDBdOS7NsLLiVZnRfCTi+1B97Trl4SeSqrgCwHKauwMZIT7yT8aPifvGXbX2nokPkY9t9vk2IZN2Uui/08Bqe4MPe9T5e3iA5+PaonPwyMg+IhEBO7yrCs6V0yl4A3QFos6Ub8ORDeRH83wgjW4QhAlEODbhVGAJJJBQevGpyO4X9wsJ2GBsT5PFTGzMh9BhvwhtkU5PI+H+6mbuhCYVuP6yhbeMyI+CtmV3JonM4YWmvlUkyyXUhKClQq461XW0Bm87Lb5PSjUfmXS+a0cxyU4HJ51gFQCkfgqPJ0gOshxVPq17h0NLds9LQJKp9OkAi9AGWG0fQgD1X2bqaqhoer4rw/joylKhD/oVu/JRrg3c5MtH2y479XxQKZD23cBz+CU+B2JGS6FN9JVJDaIGmyPI5gZ/ZL9wrGr7xEYtgvkSbEW8+EhRIAZZG8g51ZVAgHO56jSl/CwAnTUERHcZ4V0l5Lfs4bp7FT1KW3tHGrEFCdg0HVplXAJE5VOVfyCBlLYp5GGGSjBupazAR9lSfeGvZUtFYi9b21c8tKfwqR52QRJaW+EZ1jeqgQOBS/evgEb+Rx3jqMx4w8AETAzyvcF1qJgFS8MJhWymYvr5nOB4aHZQcRkh62ChmWTIK18zXL3sO3qdK1/uDaTCKxPwHMeFygVYF5ZJ1LuJGUeaF+tV8pl6AhTUoNVEe03hcO977vUWwYuj4vDA3RnruR5u46MnHSqwsM+RAJX3sdwDSUNxgk3W8p321NCJ1wjPn2QbJfXEhQVFUU5NuDU2tGxp/ZcCb+qzAa7dDtf+QY9N5tGdqAoyEw+4oKIEu4vlgn06P95gebeGU/SweE+C9bmXwZptrDV4HRIHMF3Bm+KUlcyXNKWKjRjKpxXsfwlm537NbGLpmW7hQ== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: After the list of TDMRs and the global KeyID are configured to the TDX module, the kernel needs to configure the key of the global KeyID on all packages using TDH.SYS.KEY.CONFIG. TDH.SYS.KEY.CONFIG needs to be done on one (any) cpu for each package. Also, it cannot run concurrently on different cpus, so just use smp_call_function_single() to do it one by one. Note to keep things simple, neither the function to configure the global KeyID on all packages nor the tdx_enable() checks whether there's at least one online cpu for each package. Also, neither of them explicitly prevents any cpu from going offline. It is caller's responsibility to guarantee this. Intel hardware doesn't guarantee cache coherency across different KeyIDs. The kernel needs to flush PAMT's dirty cachelines (associated with KeyID 0) before the TDX module uses the global KeyID to access the PAMT. Otherwise, those dirty cachelines can silently corrupt the TDX module's metadata. Note this breaks TDX from functionality point of view but TDX's security remains intact. Following the TDX module specification, flush cache before configuring the global KeyID on all packages. Given the PAMT size can be large (~1/256th of system RAM), just use WBINVD on all CPUs to flush. Note if any TDH.SYS.KEY.CONFIG fails, the TDX module may already have used the global KeyID to write any PAMT. Therefore, need to use WBINVD to flush cache before freeing the PAMTs back to the kernel. Reviewed-by: Isaku Yamahata Signed-off-by: Kai Huang --- v7 -> v8: (Dave) - Changelog changes: - Point out this is the step of "multi-steps" of init_tdx_module(). - Removed MOVDIR64B part. - Other changes due to removing TDH.SYS.SHUTDOWN and TDH.SYS.LP.INIT. - Changed to loop over online cpus and use smp_call_function_single() directly as the patch to shut down TDX module has been removed. - Removed MOVDIR64B part in comment. v6 -> v7: - Improved changelong and comment to explain why MOVDIR64B isn't used when returning PAMTs back to the kernel. --- arch/x86/virt/vmx/tdx/tdx.c | 97 +++++++++++++++++++++++++++++++++++-- arch/x86/virt/vmx/tdx/tdx.h | 1 + 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index ab961443fed5..4c779e8412f1 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -946,6 +946,66 @@ static int config_tdx_module(struct tdmr_info_list *tdmr_list, u64 global_keyid) return ret; } +static void do_global_key_config(void *data) +{ + int ret; + + /* + * TDH.SYS.KEY.CONFIG may fail with entropy error (which is a + * recoverable error). Assume this is exceedingly rare and + * just return error if encountered instead of retrying. + */ + ret = seamcall(TDH_SYS_KEY_CONFIG, 0, 0, 0, 0, NULL, NULL); + + *(int *)data = ret; +} + +/* + * Configure the global KeyID on all packages by doing TDH.SYS.KEY.CONFIG + * on one online cpu for each package. If any package doesn't have any + * online + * + * Note: + * + * This function neither checks whether there's at least one online cpu + * for each package, nor explicitly prevents any cpu from going offline. + * If any package doesn't have any online cpu then the SEAMCALL won't be + * done on that package and the later step of TDX module initialization + * will fail. The caller needs to guarantee this. + */ +static int config_global_keyid(void) +{ + cpumask_var_t packages; + int cpu, ret = 0; + + if (!zalloc_cpumask_var(&packages, GFP_KERNEL)) + return -ENOMEM; + + for_each_online_cpu(cpu) { + int err; + + if (cpumask_test_and_set_cpu(topology_physical_package_id(cpu), + packages)) + continue; + + /* + * TDH.SYS.KEY.CONFIG cannot run concurrently on + * different cpus, so just do it one by one. + */ + ret = smp_call_function_single(cpu, do_global_key_config, &err, + true); + if (ret) + break; + if (err) { + ret = err; + break; + } + } + + free_cpumask_var(packages); + return ret; +} + static int init_tdx_module(void) { /* @@ -998,19 +1058,46 @@ static int init_tdx_module(void) if (ret) goto out_free_pamts; + /* + * Hardware doesn't guarantee cache coherency across different + * KeyIDs. The kernel needs to flush PAMT's dirty cachelines + * (associated with KeyID 0) before the TDX module can use the + * global KeyID to access the PAMT. Given PAMTs are potentially + * large (~1/256th of system RAM), just use WBINVD on all cpus + * to flush the cache. + * + * Follow the TDX spec to flush cache before configuring the + * global KeyID on all packages. + */ + wbinvd_on_all_cpus(); + + /* Config the key of global KeyID on all packages */ + ret = config_global_keyid(); + if (ret) + goto out_free_pamts; + /* * TODO: * - * - Configure the global KeyID on all packages. * - Initialize all TDMRs. * * Return error before all steps are done. */ ret = -EINVAL; out_free_pamts: - if (ret) + if (ret) { + /* + * Part of PAMT may already have been initialized by the + * TDX module. Flush cache before returning PAMT back + * to the kernel. + * + * No need to worry about integrity checks here. KeyID + * 0 has integrity checking disabled. + */ + wbinvd_on_all_cpus(); + tdmrs_free_pamt_all(&tdmr_list); - else + } else pr_info("%lu pages allocated for PAMT.\n", tdmrs_count_pamt_pages(&tdmr_list)); out_free_tdmrs: @@ -1057,7 +1144,9 @@ static int __tdx_enable(void) * tdx_enable - Enable TDX by initializing the TDX module * * The caller must make sure all online cpus are in VMX operation before - * calling this function. + * calling this function. Also, the caller must make sure there is at + * least one online cpu for each package, and to prevent any cpu from + * going offline during this function. * * This function can be called in parallel by multiple callers. * diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h index 4d2edd477480..f5c12a2543d4 100644 --- a/arch/x86/virt/vmx/tdx/tdx.h +++ b/arch/x86/virt/vmx/tdx/tdx.h @@ -19,6 +19,7 @@ /* * TDX module SEAMCALL leaf functions */ +#define TDH_SYS_KEY_CONFIG 31 #define TDH_SYS_INFO 32 #define TDH_SYS_CONFIG 45