mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org
Cc: seanjc@google.com, Yan Zhao <yan.y.zhao@intel.com>,
	Rick Edgecombe <rick.p.edgecombe@intel.com>,
	Isaku Yamahata <isaku.yamahata@intel.com>,
	Sean Christopherson <sean.j.christopherson@intel.com>,
	Kai Huang <kai.huang@intel.com>,
	Dave Hansen <dave.hansen@linux.intel.com>
Subject: [PATCH 02/29] x86/virt/tdx: Add SEAMCALL wrappers to add TD private pages
Date: Wed, 26 Feb 2025 14:55:02 -0500	[thread overview]
Message-ID: <20250226195529.2314580-3-pbonzini@redhat.com> (raw)
In-Reply-To: <20250226195529.2314580-1-pbonzini@redhat.com>

From: Isaku Yamahata <isaku.yamahata@intel.com>

TDX architecture introduces the concept of private GPA vs shared GPA,
depending on the GPA.SHARED bit. The TDX module maintains a Secure EPT
(S-EPT or SEPT) tree per TD to translate TD's private memory accessed
using a private GPA. Wrap the SEAMCALL TDH.MEM.PAGE.ADD with
tdh_mem_page_add() and TDH.MEM.PAGE.AUG with tdh_mem_page_aug() to add TD
private pages and map them to the TD's private GPAs in the SEPT.

Callers of tdh_mem_page_add() and tdh_mem_page_aug() allocate and provide
normal pages to the wrappers, who further pass those pages to the TDX
module. Before passing the pages to the TDX module, tdh_mem_page_add() and
tdh_mem_page_aug() perform a CLFLUSH on the page mapped with keyID 0 to
ensure that any dirty cache lines don't write back later and clobber TD
memory or control structures. Don't worry about the other MK-TME keyIDs
because the kernel doesn't use them. The TDX docs specify that this flush
is not needed unless the TDX module exposes the CLFLUSH_BEFORE_ALLOC
feature bit. Do the CLFLUSH unconditionally for two reasons: make the
solution simpler by having a single path that can handle both
!CLFLUSH_BEFORE_ALLOC and CLFLUSH_BEFORE_ALLOC cases. Avoid wading into any
correctness uncertainty by going with a conservative solution to start.

Call tdh_mem_page_add() to add a private page to a TD during the TD's build
time (i.e., before TDH.MR.FINALIZE). Specify which GPA the 4K private page
will map to. No need to specify level info since TDH.MEM.PAGE.ADD only adds
pages at 4K level. To provide initial contents to TD, provide an additional
source page residing in memory managed by the host kernel itself (encrypted
with a shared keyID). The TDX module will copy the initial contents from
the source page in shared memory into the private page after mapping the
page in the SEPT to the specified private GPA. The TDX module allows the
source page to be the same page as the private page to be added. In that
case, the TDX module converts and encrypts the source page as a TD private
page.

Call tdh_mem_page_aug() to add a private page to a TD during the TD's
runtime (i.e., after TDH.MR.FINALIZE). TDH.MEM.PAGE.AUG supports adding
huge pages. Specify which GPA the private page will map to, along with
level info embedded in the lower bits of the GPA. The TDX module will
recognize the added page as the TD's private page after the TD's acceptance
with TDCALL TDG.MEM.PAGE.ACCEPT.

tdh_mem_page_add() and tdh_mem_page_aug() may fail. Callers can check
function return value and retrieve extended error info from the function
output parameters.

The TDX module has many internal locks. To avoid staying in SEAM mode for
too long, SEAMCALLs returns a BUSY error code to the kernel instead of
spinning on the locks. Depending on the specific SEAMCALL, the caller
may need to handle this error in specific ways (e.g., retry). Therefore,
return the SEAMCALL error code directly to the caller. Don't attempt to
handle it in the core kernel.

[Kai: Switched from generic seamcall export]
[Yan: Re-wrote the changelog]
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Kai Huang <kai.huang@intel.com>
Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Signed-off-by: Yan Zhao <yan.y.zhao@intel.com>
Message-ID: <20241112073636.22129-1-yan.y.zhao@intel.com>
Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 arch/x86/include/asm/tdx.h  |  2 ++
 arch/x86/virt/vmx/tdx/tdx.c | 39 +++++++++++++++++++++++++++++++++++++
 arch/x86/virt/vmx/tdx/tdx.h |  2 ++
 3 files changed, 43 insertions(+)

diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 5c9bdf68002c..9f978db2560f 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -165,8 +165,10 @@ static inline int pg_level_to_tdx_sept_level(enum pg_level level)
 }
 
 u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page);
+u64 tdh_mem_page_add(struct tdx_td *td, u64 gpa, struct page *page, struct page *source, u64 *ext_err1, u64 *ext_err2);
 u64 tdh_mem_sept_add(struct tdx_td *td, u64 gpa, int level, struct page *page, u64 *ext_err1, u64 *ext_err2);
 u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page);
+u64 tdh_mem_page_aug(struct tdx_td *td, u64 gpa, int level, struct page *page, u64 *ext_err1, u64 *ext_err2);
 u64 tdh_mng_key_config(struct tdx_td *td);
 u64 tdh_mng_create(struct tdx_td *td, u16 hkid);
 u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp);
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 506a75fbac0b..4ae10246260e 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -1529,6 +1529,26 @@ u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page)
 }
 EXPORT_SYMBOL_GPL(tdh_mng_addcx);
 
+u64 tdh_mem_page_add(struct tdx_td *td, u64 gpa, struct page *page, struct page *source, u64 *ext_err1, u64 *ext_err2)
+{
+	struct tdx_module_args args = {
+		.rcx = gpa,
+		.rdx = tdx_tdr_pa(td),
+		.r8 = page_to_phys(page),
+		.r9 = page_to_phys(source),
+	};
+	u64 ret;
+
+	tdx_clflush_page(page);
+	ret = seamcall_ret(TDH_MEM_PAGE_ADD, &args);
+
+	*ext_err1 = args.rcx;
+	*ext_err2 = args.rdx;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tdh_mem_page_add);
+
 u64 tdh_mem_sept_add(struct tdx_td *td, u64 gpa, int level, struct page *page, u64 *ext_err1, u64 *ext_err2)
 {
 	struct tdx_module_args args = {
@@ -1560,6 +1580,25 @@ u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page)
 }
 EXPORT_SYMBOL_GPL(tdh_vp_addcx);
 
+u64 tdh_mem_page_aug(struct tdx_td *td, u64 gpa, int level, struct page *page, u64 *ext_err1, u64 *ext_err2)
+{
+	struct tdx_module_args args = {
+		.rcx = gpa | level,
+		.rdx = tdx_tdr_pa(td),
+		.r8 = page_to_phys(page),
+	};
+	u64 ret;
+
+	tdx_clflush_page(page);
+	ret = seamcall_ret(TDH_MEM_PAGE_AUG, &args);
+
+	*ext_err1 = args.rcx;
+	*ext_err2 = args.rdx;
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(tdh_mem_page_aug);
+
 u64 tdh_mng_key_config(struct tdx_td *td)
 {
 	struct tdx_module_args args = {
diff --git a/arch/x86/virt/vmx/tdx/tdx.h b/arch/x86/virt/vmx/tdx/tdx.h
index f3e37df4c63a..5879bdb0045f 100644
--- a/arch/x86/virt/vmx/tdx/tdx.h
+++ b/arch/x86/virt/vmx/tdx/tdx.h
@@ -15,8 +15,10 @@
  * TDX module SEAMCALL leaf functions
  */
 #define TDH_MNG_ADDCX			1
+#define TDH_MEM_PAGE_ADD		2
 #define TDH_MEM_SEPT_ADD		3
 #define TDH_VP_ADDCX			4
+#define TDH_MEM_PAGE_AUG		6
 #define TDH_MNG_KEY_CONFIG		8
 #define TDH_MNG_CREATE			9
 #define TDH_MNG_RD			11
-- 
2.43.5



  parent reply	other threads:[~2025-02-26 19:55 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-26 19:55 [PATCH v3 00/29] TDX MMU part 2 Paolo Bonzini
2025-02-26 19:55 ` [PATCH 01/29] x86/virt/tdx: Add SEAMCALL wrapper tdh_mem_sept_add() to add SEPT pages Paolo Bonzini
2025-02-26 19:55 ` Paolo Bonzini [this message]
2025-02-26 19:55 ` [PATCH 03/29] x86/virt/tdx: Add SEAMCALL wrappers to manage TDX TLB tracking Paolo Bonzini
2025-02-26 19:55 ` [PATCH 04/29] x86/virt/tdx: Add SEAMCALL wrappers to remove a TD private page Paolo Bonzini
2025-02-26 19:55 ` [PATCH 05/29] x86/virt/tdx: Add SEAMCALL wrappers for TD measurement of initial contents Paolo Bonzini
2025-02-26 19:55 ` [PATCH 06/29] KVM: x86/mmu: Implement memslot deletion for TDX Paolo Bonzini
2025-02-26 19:55 ` [PATCH 07/29] KVM: x86/tdp_mmu: Add a helper function to walk down the TDP MMU Paolo Bonzini
2025-02-26 19:55 ` [PATCH 08/29] KVM: x86/mmu: Do not enable page track for TD guest Paolo Bonzini
2025-02-26 19:55 ` [PATCH 09/29] KVM: VMX: Split out guts of EPT violation to common/exposed function Paolo Bonzini
2025-02-26 19:55 ` [PATCH 10/29] KVM: VMX: Teach EPT violation helper about private mem Paolo Bonzini
2025-02-26 19:55 ` [PATCH 11/29] KVM: TDX: Add accessors VMX VMCS helpers Paolo Bonzini
2025-02-26 19:55 ` [PATCH 12/29] KVM: TDX: Add load_mmu_pgd method for TDX Paolo Bonzini
2025-02-26 19:55 ` [PATCH 13/29] KVM: TDX: Set gfn_direct_bits to shared bit Paolo Bonzini
2025-02-26 19:55 ` [PATCH 14/29] KVM: TDX: Require TDP MMU, mmio caching and EPT A/D bits for TDX Paolo Bonzini
2025-02-26 19:55 ` [PATCH 15/29] KVM: x86/mmu: Add setter for shadow_mmio_value Paolo Bonzini
2025-02-26 19:55 ` [PATCH 16/29] KVM: TDX: Set per-VM shadow_mmio_value to 0 Paolo Bonzini
2025-02-26 19:55 ` [PATCH 17/29] KVM: TDX: Handle TLB tracking for TDX Paolo Bonzini
2025-02-26 19:55 ` [PATCH 18/29] KVM: TDX: Implement hooks to propagate changes of TDP MMU mirror page table Paolo Bonzini
2025-02-26 19:55 ` [PATCH 19/29] KVM: TDX: Implement hook to get max mapping level of private pages Paolo Bonzini
2025-02-26 19:55 ` [PATCH 20/29] KVM: x86/mmu: Bail out kvm_tdp_map_page() when VM dead Paolo Bonzini
2025-02-26 19:55 ` [PATCH 21/29] KVM: x86/mmu: Export kvm_tdp_map_page() Paolo Bonzini
2025-02-26 19:55 ` [PATCH 22/29] KVM: TDX: Add an ioctl to create initial guest memory Paolo Bonzini
2025-02-28  4:18   ` Yan Zhao
2025-03-06 16:04     ` Paolo Bonzini
2025-02-26 19:55 ` [PATCH 23/29] KVM: TDX: Finalize VM initialization Paolo Bonzini
2025-02-26 19:55 ` [PATCH 24/29] KVM: TDX: Handle vCPU dissociation Paolo Bonzini
2025-02-26 19:55 ` [PATCH 25/29] KVM: Add parameter "kvm" to kvm_cpu_dirty_log_size() and its callers Paolo Bonzini
2025-02-26 19:55 ` [PATCH 26/29] KVM: x86/mmu: Add parameter "kvm" to kvm_mmu_page_ad_need_write_protect() Paolo Bonzini
2025-02-26 19:55 ` [PATCH 27/29] KVM: x86: Make cpu_dirty_log_size a per-VM value Paolo Bonzini
2025-02-26 19:55 ` [PATCH 28/29] KVM: TDX: Skip updating CPU dirty logging request for TDs Paolo Bonzini
2025-02-26 19:55 ` [PATCH 29/29] KVM: TDX: Handle SEPT zap error due to page add error in premap Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250226195529.2314580-3-pbonzini@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=isaku.yamahata@intel.com \
    --cc=kai.huang@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rick.p.edgecombe@intel.com \
    --cc=sean.j.christopherson@intel.com \
    --cc=seanjc@google.com \
    --cc=yan.y.zhao@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®