From nobody Fri Oct 3 21:00:32 2025 Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.16]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A84E2D0C82; Mon, 25 Aug 2025 22:59:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.16 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756162757; cv=none; b=VpCB1pNGOoABc1WW7FgaQ296MMCC0FZtDqsgY4KK4axqOZ8YF2Y5MPXSmblwIWd2hV9UZvgzezE7/TgEQ/N9cla6xBk3GGgOg14oujU1AH7e/W1n0+Yc//ufYsqmGoSMdjpe6TyCE50WXzF/AgSqwRkPuNKf9gZn3eK0uz+I8sI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1756162757; c=relaxed/simple; bh=Ofg/UDToVH9qFqg6h8UOGVTfr9OxNQiv8OrCJPx9AQ8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aC2D7M0+7PktmhlcrnZZgn5rOBxV0KpHs6HSfNYepn2EtMYVhVsmvaEx5m2Lqj86mqN4K6Vztivpasl2jdxVUm37eQlWeI9f8LrtsCQgsmNRWV4hP4pgerxNRFwn/eKKdoKCdb8QhVJdjL4p+Tz57OGmU6MLa5ve9Ms+S8L+HzA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=dzq87vPW; arc=none smtp.client-ip=198.175.65.16 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="dzq87vPW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1756162756; x=1787698756; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ofg/UDToVH9qFqg6h8UOGVTfr9OxNQiv8OrCJPx9AQ8=; b=dzq87vPW5aw98i+elqvu4jgLN2hyrMwTLnvp8fTJivqtM6ZAV5qiBOpu R3ZZRG7AxbcLD/IIZ+d8P4B4BlYzxVPBPd+p5AejN2ket51L9A40itUwk /vRkrKBJwG3El5EZrOb8uUM/kPEPQtVZu6ktupU+vgJdGOu7F7mfPTpgm U6QllZqgP8hXxAargiIGKe9Xs9Lp+d9w6m+Pb+xqmjQFdyEw09I4hQ2xM r0EZsqbj35UfzLC1mu2Ih9969JEm8NkQ+n30JWA0yOrX8UiZDCdncjaxe iTvMeOJG/mWvqKQFQpfZk85knW80/RGk9uNrk1OACf90NGVpB6SIJZaxi w==; X-CSE-ConnectionGUID: hEcZJGrsSiqkyV3iESdZ2g== X-CSE-MsgGUID: 9VVcgQOAShWRpLm5VrHzkQ== X-IronPort-AV: E=McAfee;i="6800,10657,11533"; a="58533369" X-IronPort-AV: E=Sophos;i="6.18,214,1751266800"; d="scan'208";a="58533369" Received: from fmviesa001.fm.intel.com ([10.60.135.141]) by orvoesa108.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Aug 2025 15:59:16 -0700 X-CSE-ConnectionGUID: PhIIub0/Sjuv37jB/CC/dA== X-CSE-MsgGUID: GkjcV/a+TNq+hnFBm9Mh8w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.18,214,1751266800"; d="scan'208";a="200308435" Received: from ldmartin-desk2.corp.intel.com (HELO khuang2-desk.gar.corp.intel.com) ([10.124.223.59]) by smtpauth.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 Aug 2025 15:59:10 -0700 From: Kai Huang To: dave.hansen@intel.com, bp@alien8.de, tglx@linutronix.de, peterz@infradead.org, mingo@redhat.com, hpa@zytor.com, thomas.lendacky@amd.com Cc: x86@kernel.org, kas@kernel.org, rick.p.edgecombe@intel.com, dwmw@amazon.co.uk, linux-kernel@vger.kernel.org, pbonzini@redhat.com, seanjc@google.com, kvm@vger.kernel.org, reinette.chatre@intel.com, isaku.yamahata@intel.com, dan.j.williams@intel.com, ashish.kalra@amd.com, nik.borisov@suse.com, chao.gao@intel.com, sagis@google.com, farrah.chen@intel.com Subject: [PATCH v7 3/7] x86/virt/tdx: Mark memory cache state incoherent when making SEAMCALL Date: Tue, 26 Aug 2025 10:58:38 +1200 Message-ID: <65859cd0daf3bc29926e68fea17252db84604b97.1756161460.git.kai.huang@intel.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" On TDX platforms, dirty cacheline aliases with and without encryption bits can coexist, and the cpu can flush them back to memory in random order. During kexec, the caches must be flushed before jumping to the new kernel otherwise the dirty cachelines could silently corrupt the memory used by the new kernel due to different encryption property. A percpu boolean is used to mark whether the cache of a given CPU may be in an incoherent state, and the kexec performs WBINVD on the CPUs with that boolean turned on. For TDX, only the TDX module or the TDX guests can generate dirty cachelines of TDX private memory, i.e., they are only generated when the kernel does a SEAMCALL. Set that boolean when the kernel does SEAMCALL so that kexec can flush the cache correctly. The kernel provides both the __seamcall*() assembly functions and the seamcall*() wrapper ones which additionally handle running out of entropy error in a loop. Most of the SEAMCALLs are called using the seamcall*(), except TDH.VP.ENTER and TDH.PHYMEM.PAGE.RDMD which are called using __seamcall*() variant directly. To cover the two special cases, add a new __seamcall_dirty_cache() helper which only sets the percpu boolean and calls the __seamcall*(), and change the special cases to use the new helper. To cover all other SEAMCALLs, change seamcall*() to call the new helper. For the SEAMCALLs invoked via seamcall*(), they can be made from both task context and IRQ disabled context. Given SEAMCALL is just a lengthy instruction (e.g., thousands of cycles) from kernel's point of view and preempt_{disable|enable}() is cheap compared to it, just unconditionally disable preemption during setting the boolean and making SEAMCALL. Signed-off-by: Kai Huang Tested-by: Farrah Chen Reviewed-by: Chao Gao Reviewed-by: Rick Edgecombe --- arch/x86/include/asm/tdx.h | 25 ++++++++++++++++++++++++- arch/x86/virt/vmx/tdx/tdx.c | 4 ++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 57b46f05ff97..c178360c1fb1 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -102,10 +102,31 @@ u64 __seamcall_ret(u64 fn, struct tdx_module_args *ar= gs); u64 __seamcall_saved_ret(u64 fn, struct tdx_module_args *args); void tdx_init(void); =20 +#include #include +#include =20 typedef u64 (*sc_func_t)(u64 fn, struct tdx_module_args *args); =20 +static __always_inline u64 __seamcall_dirty_cache(sc_func_t func, u64 fn, + struct tdx_module_args *args) +{ + lockdep_assert_preemption_disabled(); + + /* + * SEAMCALLs are made to the TDX module and can generate dirty + * cachelines of TDX private memory. Mark cache state incoherent + * so that the cache can be flushed during kexec. + * + * This needs to be done before actually making the SEAMCALL, + * because kexec-ing CPU could send NMI to stop remote CPUs, + * in which case even disabling IRQ won't help here. + */ + this_cpu_write(cache_state_incoherent, true); + + return func(fn, args); +} + static __always_inline u64 sc_retry(sc_func_t func, u64 fn, struct tdx_module_args *args) { @@ -113,7 +134,9 @@ static __always_inline u64 sc_retry(sc_func_t func, u64= fn, u64 ret; =20 do { - ret =3D func(fn, args); + preempt_disable(); + ret =3D __seamcall_dirty_cache(func, fn, args); + preempt_enable(); } while (ret =3D=3D TDX_RND_NO_ENTROPY && --retry); =20 return ret; diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c index 823850399bb7..2abf53ed59c8 100644 --- a/arch/x86/virt/vmx/tdx/tdx.c +++ b/arch/x86/virt/vmx/tdx/tdx.c @@ -1268,7 +1268,7 @@ static bool paddr_is_tdx_private(unsigned long phys) return false; =20 /* Get page type from the TDX module */ - sret =3D __seamcall_ret(TDH_PHYMEM_PAGE_RDMD, &args); + sret =3D __seamcall_dirty_cache(__seamcall_ret, TDH_PHYMEM_PAGE_RDMD, &ar= gs); =20 /* * The SEAMCALL will not return success unless there is a @@ -1524,7 +1524,7 @@ noinstr __flatten u64 tdh_vp_enter(struct tdx_vp *td,= struct tdx_module_args *ar { args->rcx =3D tdx_tdvpr_pa(td); =20 - return __seamcall_saved_ret(TDH_VP_ENTER, args); + return __seamcall_dirty_cache(__seamcall_saved_ret, TDH_VP_ENTER, args); } EXPORT_SYMBOL_GPL(tdh_vp_enter); =20 --=20 2.50.1