From patchwork Wed Jun 26 13:52:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thibault Ferrante X-Patchwork-Id: 1952642 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com (client-ip=185.125.189.65; helo=lists.ubuntu.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=patchwork.ozlabs.org) Received: from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65]) (using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4W8NSQ2DKdz23tx for ; Wed, 26 Jun 2024 23:52:53 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=lists.ubuntu.com) by lists.ubuntu.com with esmtp (Exim 4.86_2) (envelope-from ) id 1sMT4l-0006M4-3Q; Wed, 26 Jun 2024 13:52:43 +0000 Received: from smtp-relay-canonical-0.internal ([10.131.114.83] helo=smtp-relay-canonical-0.canonical.com) by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1sMT4j-0006LF-0S for kernel-team@lists.ubuntu.com; Wed, 26 Jun 2024 13:52:41 +0000 Received: from Q58-sff.fritz.box (2.general.thibf.uk.vpn [10.172.200.120]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-canonical-0.canonical.com (Postfix) with ESMTPSA id 42F7940144; Wed, 26 Jun 2024 13:52:40 +0000 (UTC) From: Thibault Ferrante To: kernel-team@lists.ubuntu.com Subject: [SRU][N:intel][PATCH 2/8] UBUNTU: SAUCE: x86/kexec: do unconditional WBINVD for bare-metal in relocate_kernel() Date: Wed, 26 Jun 2024 15:52:26 +0200 Message-ID: <20240626135232.2731811-3-thibault.ferrante@canonical.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240626135232.2731811-1-thibault.ferrante@canonical.com> References: <20240626135232.2731811-1-thibault.ferrante@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Kai Huang BugLink: https://bugs.launchpad.net/bugs/2070356 Both SME and TDX can leave caches in incoherent state due to memory encryption. During kexec, the caches must be flushed before jumping to the second kernel to avoid silent memory corruption to the second kernel. During kexec, the WBINVD in stop_this_cpu() flushes caches for all remote cpus when they are being stopped. For SME, the WBINVD in relocate_kernel() flushes the cache for the last running cpu (which is executing the kexec). Similarly, to support kexec for TDX host, after stopping all remote cpus with cache flushed, the kernel needs to flush cache for the last running cpu. Use the existing WBINVD in relocate_kernel() to cover TDX host as well. However, instead of sprinkling around vendor-specific checks, just do unconditional WBINVD to cover both SME and TDX. Kexec is not a fast path so having one additional WBINVD for platforms w/o SME/TDX is acceptable. But only do WBINVD for bare-metal because TDX guests and SEV-ES/SEV-SNP guests will get unexpected (and yet unnecessary) exception (#VE or #VC) which the kernel is unable to handle at this stage. Signed-off-by: Kai Huang Reviewed-by: Kirill A. Shutemov Cc: Tom Lendacky Cc: Dave Young (cherry picked from http://github.com/intel/kernel-downstream.git/v6.8-tdx from commit bfa6632c6c3c6df0fb1e533848b4613f9809a459) Signed-off-by: Thibault Ferrante --- arch/x86/include/asm/kexec.h | 2 +- arch/x86/kernel/machine_kexec_64.c | 2 +- arch/x86/kernel/relocate_kernel_64.S | 19 +++++++++++++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/kexec.h b/arch/x86/include/asm/kexec.h index c9f6a6c5de3c..a31f9990466e 100644 --- a/arch/x86/include/asm/kexec.h +++ b/arch/x86/include/asm/kexec.h @@ -129,7 +129,7 @@ relocate_kernel(unsigned long indirection_page, unsigned long page_list, unsigned long start_address, unsigned int preserve_context, - unsigned int host_mem_enc_active); + unsigned int bare_metal); #endif #define ARCH_HAS_KIMAGE_ARCH diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index bc0a5348b4a6..33695cec329f 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -358,7 +358,7 @@ void machine_kexec(struct kimage *image) (unsigned long)page_list, image->start, image->preserve_context, - cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)); + !boot_cpu_has(X86_FEATURE_HYPERVISOR)); #ifdef CONFIG_KEXEC_JUMP if (image->preserve_context) diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index 56cab1bb25f5..6e1590b24e41 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -50,7 +50,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel) * %rsi page_list * %rdx start address * %rcx preserve_context - * %r8 host_mem_enc_active + * %r8 bare_metal */ /* Save the CPU context, used for jumping back */ @@ -78,7 +78,7 @@ SYM_CODE_START_NOALIGN(relocate_kernel) pushq $0 popfq - /* Save SME active flag */ + /* Save the bare_metal flag */ movq %r8, %r12 /* @@ -160,9 +160,20 @@ SYM_CODE_START_LOCAL_NOALIGN(identity_mapped) movq %r9, %cr3 /* - * If SME is active, there could be old encrypted cache line + * The kernel could leave caches in incoherent state on SME/TDX + * capable platforms. Just do unconditional WBINVD to avoid + * silent memory corruption to the new kernel for these platforms. + * + * For SME, need to flush cache here before copying the kernel. + * When it is active, there could be old encrypted cache line * entries that will conflict with the now unencrypted memory - * used by kexec. Flush the caches before copying the kernel. + * used by kexec. + * + * Do WBINVD for bare-metal only to cover both SME and TDX. It + * isn't necessary to perform a WBINVD in a guest and performing + * one could result in an exception (#VE or #VC) for a TDX or + * SEV-ES/SEV-SNP guest that can crash the guest since, at this + * stage, the kernel has torn down the IDT. */ testq %r12, %r12 jz 1f