From: Yan Zhao <yan.y.zhao@intel.com>
To: pbonzini@redhat.com, seanjc@google.com
Cc: linux-kernel@vger.kernel.org, kvm@vger.kernel.org,
x86@kernel.org, rick.p.edgecombe@intel.com,
dave.hansen@intel.com, kas@kernel.org, tabba@google.com,
ackerleytng@google.com, quic_eberman@quicinc.com,
michael.roth@amd.com, david@redhat.com, vannapurve@google.com,
vbabka@suse.cz, thomas.lendacky@amd.com, pgonda@google.com,
zhiquan1.li@intel.com, fan.du@intel.com, jun.miao@intel.com,
ira.weiny@intel.com, isaku.yamahata@intel.com,
xiaoyao.li@intel.com, binbin.wu@linux.intel.com,
chao.p.peng@intel.com, yan.y.zhao@intel.com
Subject: [RFC PATCH v2 22/23] KVM: TDX: Handle Dynamic PAMT on page split
Date: Thu, 7 Aug 2025 17:46:16 +0800 [thread overview]
Message-ID: <20250807094616.4776-1-yan.y.zhao@intel.com> (raw)
In-Reply-To: <20250807093950.4395-1-yan.y.zhao@intel.com>
From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Page demote from 2M to 4k requires an additional PAMT page pair to cover
the 2M range that now mapped with 4k.
EPT page also has to be covered in PAMT_4K.
Allocate both from pre-allocated split PAMT pool.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Yan Zhao <yan.y.zhao@intel.com>
---
RFC v2:
- Pulled from
git://git.kernel.org/pub/scm/linux/kernel/git/kas/linux.git tdx/dpamt-huge.
- Rebased on top of TDX huge page RFC v2 (Yan).
---
arch/x86/include/asm/tdx.h | 4 ++++
arch/x86/kvm/vmx/tdx.c | 28 ++++++++++++++++++++++++----
arch/x86/virt/vmx/tdx/tdx.c | 11 +++++++----
3 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 2e529f0c578a..da317981e95a 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -123,6 +123,10 @@ u32 tdx_get_nr_guest_keyids(void);
void tdx_guest_keyid_free(unsigned int keyid);
int tdx_nr_pamt_pages(void);
+atomic_t *tdx_get_pamt_refcount(unsigned long hpa);
+int tdx_alloc_pamt_pages(struct list_head *pamt_pages,
+ struct page *(alloc)(void *data), void *data);
+void tdx_free_pamt_pages(struct list_head *pamt_pages);
int tdx_pamt_get(struct page *page, enum pg_level level,
struct page *(alloc)(void *data), void *data);
void tdx_pamt_put(struct page *page, enum pg_level level);
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index 9d24a1a86a23..6e061d659639 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -1915,28 +1915,48 @@ static int tdx_sept_free_private_spt(struct kvm *kvm, gfn_t gfn,
return 0;
}
+static struct page *tdx_alloc_pamt_page_split(void *data)
+{
+ struct kvm *kvm = data;
+ void *p;
+
+ p = kvm_mmu_memory_cache_alloc(&kvm->arch.pamt_page_cache);
+ return virt_to_page(p);
+}
+
static int tdx_spte_demote_private_spte(struct kvm *kvm, gfn_t gfn,
- enum pg_level level, struct page *page)
+ enum pg_level level, struct page *page,
+ kvm_pfn_t pfn_for_gfn)
{
int tdx_level = pg_level_to_tdx_sept_level(level);
+ hpa_t hpa = pfn_to_hpa(pfn_for_gfn);
struct kvm_tdx *kvm_tdx = to_kvm_tdx(kvm);
gpa_t gpa = gfn_to_gpa(gfn);
u64 err, entry, level_state;
+ LIST_HEAD(pamt_pages);
+
+ tdx_pamt_get(page, PG_LEVEL_4K, tdx_alloc_pamt_page_split, kvm);
+ tdx_alloc_pamt_pages(&pamt_pages, tdx_alloc_pamt_page_split, kvm);
err = tdh_mem_page_demote(&kvm_tdx->td, gpa, tdx_level, page,
- NULL, &entry, &level_state);
+ &pamt_pages, &entry, &level_state);
if (unlikely(tdx_operand_busy(err))) {
tdx_no_vcpus_enter_start(kvm);
err = tdh_mem_page_demote(&kvm_tdx->td, gpa, tdx_level, page,
- NULL, &entry, &level_state);
+ &pamt_pages, &entry, &level_state);
tdx_no_vcpus_enter_stop(kvm);
}
if (KVM_BUG_ON(err, kvm)) {
+ tdx_free_pamt_pages(&pamt_pages);
+ tdx_pamt_put(page, PG_LEVEL_4K);
pr_tdx_error_2(TDH_MEM_PAGE_DEMOTE, err, entry, level_state);
return -EIO;
}
+
+ if (tdx_supports_dynamic_pamt(tdx_sysinfo))
+ atomic_set(tdx_get_pamt_refcount(hpa), PTRS_PER_PMD);
return 0;
}
@@ -1963,7 +1983,7 @@ static int tdx_sept_split_private_spt(struct kvm *kvm, gfn_t gfn, enum pg_level
tdx_track(kvm);
- return tdx_spte_demote_private_spte(kvm, gfn, level, page);
+ return tdx_spte_demote_private_spte(kvm, gfn, level, page, pfn_for_gfn);
}
static int tdx_sept_remove_private_spte(struct kvm *kvm, gfn_t gfn,
diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
index 50f9d49f1c91..dbbddd00ec60 100644
--- a/arch/x86/virt/vmx/tdx/tdx.c
+++ b/arch/x86/virt/vmx/tdx/tdx.c
@@ -188,10 +188,11 @@ int tdx_cpu_enable(void)
}
EXPORT_SYMBOL_GPL(tdx_cpu_enable);
-static atomic_t *tdx_get_pamt_refcount(unsigned long hpa)
+atomic_t *tdx_get_pamt_refcount(unsigned long hpa)
{
return &pamt_refcounts[hpa / PMD_SIZE];
}
+EXPORT_SYMBOL_GPL(tdx_get_pamt_refcount);
static int pamt_refcount_populate(pte_t *pte, unsigned long addr, void *data)
{
@@ -2151,7 +2152,7 @@ static u64 tdh_phymem_pamt_remove(unsigned long hpa,
static DEFINE_SPINLOCK(pamt_lock);
-static void tdx_free_pamt_pages(struct list_head *pamt_pages)
+void tdx_free_pamt_pages(struct list_head *pamt_pages)
{
struct page *page;
@@ -2160,9 +2161,10 @@ static void tdx_free_pamt_pages(struct list_head *pamt_pages)
__free_page(page);
}
}
+EXPORT_SYMBOL_GPL(tdx_free_pamt_pages);
-static int tdx_alloc_pamt_pages(struct list_head *pamt_pages,
- struct page *(alloc)(void *data), void *data)
+int tdx_alloc_pamt_pages(struct list_head *pamt_pages,
+ struct page *(alloc)(void *data), void *data)
{
for (int i = 0; i < tdx_nr_pamt_pages(); i++) {
struct page *page;
@@ -2180,6 +2182,7 @@ static int tdx_alloc_pamt_pages(struct list_head *pamt_pages,
tdx_free_pamt_pages(pamt_pages);
return -ENOMEM;
}
+EXPORT_SYMBOL_GPL(tdx_alloc_pamt_pages);
static int tdx_pamt_add(atomic_t *pamt_refcount, unsigned long hpa,
struct list_head *pamt_pages)
--
2.43.2
next prev parent reply other threads:[~2025-08-07 9:46 UTC|newest]
Thread overview: 129+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-07 9:39 [RFC PATCH v2 00/23] KVM: TDX huge page support for private memory Yan Zhao
2025-08-07 9:41 ` [RFC PATCH v2 01/23] x86/tdx: Enhance tdh_mem_page_aug() to support huge pages Yan Zhao
2025-08-07 9:41 ` [RFC PATCH v2 02/23] x86/virt/tdx: Add SEAMCALL wrapper tdh_mem_page_demote() Yan Zhao
2025-09-01 8:55 ` Binbin Wu
2025-09-01 9:08 ` Yan Zhao
2025-09-02 16:56 ` Edgecombe, Rick P
2025-09-02 17:37 ` Sean Christopherson
2025-09-02 17:45 ` Edgecombe, Rick P
2025-09-04 9:31 ` Yan Zhao
2025-11-11 9:15 ` Huang, Kai
2025-11-12 8:06 ` Yan Zhao
2025-11-14 9:14 ` Binbin Wu
2025-11-14 9:21 ` Yan Zhao
2025-08-07 9:42 ` [RFC PATCH v2 03/23] x86/tdx: Enhance tdh_phymem_page_wbinvd_hkid() to invalidate huge pages Yan Zhao
2025-11-11 9:23 ` Huang, Kai
2025-11-12 8:43 ` Yan Zhao
2025-11-12 10:29 ` Huang, Kai
2025-11-13 2:35 ` Yan Zhao
2025-11-13 7:37 ` Huang, Kai
2025-11-13 9:03 ` Yan Zhao
2025-11-13 15:26 ` Dave Hansen
2025-11-14 1:21 ` Yan Zhao
2025-12-10 1:14 ` Vishal Annapurve
2025-12-10 1:18 ` Yan Zhao
2025-12-10 1:30 ` Vishal Annapurve
2025-12-10 1:55 ` Yan Zhao
2025-12-31 19:37 ` Vishal Annapurve
2026-01-06 10:37 ` Yan Zhao
2025-08-07 9:42 ` [RFC PATCH v2 04/23] KVM: TDX: Introduce tdx_clear_folio() to clear " Yan Zhao
2025-09-02 2:56 ` Binbin Wu
2025-09-03 9:51 ` Yan Zhao
2025-09-03 11:19 ` Binbin Wu
2025-09-04 2:53 ` Yan Zhao
2025-08-07 9:42 ` [RFC PATCH v2 05/23] x86/tdx: Enhance tdh_phymem_page_reclaim() to support " Yan Zhao
2025-11-17 2:09 ` Binbin Wu
2025-11-17 4:05 ` Yan Zhao
2025-08-07 9:42 ` [RFC PATCH v2 06/23] KVM: TDX: Do not hold page refcount on private guest pages Yan Zhao
2025-08-07 9:42 ` [RFC PATCH v2 07/23] KVM: x86/mmu: Disallow page merging (huge page adjustment) for mirror root Yan Zhao
2025-08-07 9:43 ` [RFC PATCH v2 08/23] KVM: x86/tdp_mmu: Alloc external_spt page for mirror page table splitting Yan Zhao
2025-11-11 9:52 ` Huang, Kai
2025-11-12 9:29 ` Yan Zhao
2025-08-07 9:43 ` [RFC PATCH v2 09/23] KVM: x86/tdp_mmu: Add split_external_spt hook called during write mmu_lock Yan Zhao
2025-11-11 10:06 ` Huang, Kai
2025-11-13 3:16 ` Yan Zhao
2025-11-17 8:53 ` Binbin Wu
2025-11-17 9:09 ` Yan Zhao
2025-08-07 9:43 ` [RFC PATCH v2 10/23] KVM: TDX: Enable huge page splitting under write kvm->mmu_lock Yan Zhao
2025-11-11 10:20 ` Huang, Kai
2025-11-13 5:53 ` Yan Zhao
2025-11-17 9:17 ` Binbin Wu
2025-11-17 9:26 ` Yan Zhao
2025-12-09 23:49 ` Sagi Shahar
2025-12-09 23:54 ` Edgecombe, Rick P
2025-12-10 0:28 ` Sagi Shahar
2025-12-10 0:50 ` Yan Zhao
2025-12-10 17:16 ` Sagi Shahar
2025-12-10 19:49 ` Edgecombe, Rick P
2025-12-11 2:10 ` Yan Zhao
2025-08-07 9:43 ` [RFC PATCH v2 11/23] KVM: x86: Reject splitting huge pages under shared mmu_lock for mirror root Yan Zhao
2025-09-03 3:30 ` Binbin Wu
2025-08-07 9:43 ` [RFC PATCH v2 12/23] KVM: x86/mmu: Introduce kvm_split_cross_boundary_leafs() Yan Zhao
2025-09-03 6:57 ` Binbin Wu
2025-09-03 9:44 ` Yan Zhao
2025-11-11 10:42 ` Huang, Kai
2025-11-13 8:54 ` Yan Zhao
2025-11-13 11:02 ` Huang, Kai
2025-11-13 11:40 ` Huang, Kai
2025-11-14 6:09 ` Yan Zhao
2025-11-18 0:14 ` Huang, Kai
2025-11-18 6:30 ` Yan Zhao
2025-11-18 8:59 ` Binbin Wu
2025-11-18 10:49 ` Huang, Kai
2025-11-19 3:41 ` Yan Zhao
2026-01-06 10:35 ` Yan Zhao
2025-11-19 6:23 ` Yan Zhao
2025-11-19 6:31 ` Yan Zhao
2025-08-07 9:44 ` [RFC PATCH v2 13/23] KVM: x86: Introduce hugepage_set_guest_inhibit() Yan Zhao
2025-08-07 9:44 ` [RFC PATCH v2 14/23] KVM: TDX: Split and inhibit huge mappings if a VMExit carries level info Yan Zhao
2025-09-03 7:36 ` Binbin Wu
2025-09-03 9:37 ` Yan Zhao
2025-11-11 10:55 ` Huang, Kai
2025-11-14 1:42 ` Yan Zhao
2025-11-18 0:26 ` Huang, Kai
2025-11-18 2:44 ` Yan Zhao
2025-11-11 11:05 ` Huang, Kai
2025-11-14 7:22 ` Yan Zhao
2025-11-18 1:04 ` Huang, Kai
2025-11-18 2:20 ` Yan Zhao
2025-11-18 9:44 ` Huang, Kai
2025-11-19 2:58 ` Yan Zhao
2025-11-19 5:51 ` Binbin Wu
2025-11-19 6:29 ` Yan Zhao
2025-11-19 6:39 ` Binbin Wu
2025-08-07 9:44 ` [RFC PATCH v2 15/23] KVM: Change the return type of gfn_handler_t() from bool to int Yan Zhao
2025-08-07 9:44 ` [RFC PATCH v2 16/23] KVM: x86: Split cross-boundary mirror leafs for KVM_SET_MEMORY_ATTRIBUTES Yan Zhao
2025-08-07 9:45 ` [RFC PATCH v2 17/23] KVM: guest_memfd: Split for punch hole and private-to-shared conversion Yan Zhao
2025-09-04 7:58 ` Binbin Wu
2025-09-04 9:48 ` Yan Zhao
2025-09-04 11:07 ` Yan Zhao
2025-10-01 6:21 ` Ackerley Tng
2025-10-13 0:18 ` Yan Zhao
2025-10-01 8:00 ` Ackerley Tng
2025-10-13 0:45 ` Yan Zhao
2025-08-07 9:45 ` [RFC PATCH v2 18/23] x86/virt/tdx: Do not perform cache flushes unless CLFLUSH_BEFORE_ALLOC is set Yan Zhao
2025-08-11 21:10 ` Sagi Shahar
2025-08-12 6:37 ` Yan Zhao
2025-09-04 8:16 ` Binbin Wu
2025-09-04 9:50 ` Yan Zhao
2025-09-05 9:05 ` Binbin Wu
2025-09-05 15:41 ` Edgecombe, Rick P
2025-09-15 6:05 ` Yan Zhao
2025-08-07 9:45 ` [RFC PATCH v2 19/23] KVM: TDX: Pass down pfn to split_external_spt() Yan Zhao
2025-09-04 8:30 ` Binbin Wu
2025-08-07 9:45 ` [RFC PATCH v2 20/23] KVM: TDX: Handle Dynamic PAMT in tdh_mem_page_demote() Yan Zhao
2025-08-07 9:46 ` [RFC PATCH v2 21/23] KVM: TDX: Preallocate PAMT pages to be used in split path Yan Zhao
2025-09-04 9:17 ` Binbin Wu
2025-09-04 9:58 ` Yan Zhao
2025-12-05 6:14 ` Sagi Shahar
2025-12-08 5:49 ` Yan Zhao
2025-12-11 1:42 ` Vishal Annapurve
2025-12-11 2:36 ` Yan Zhao
2025-08-07 9:46 ` Yan Zhao [this message]
2025-08-14 5:31 ` [RFC PATCH v2 22/23] KVM: TDX: Handle Dynamic PAMT on page split Vishal Annapurve
2025-08-14 18:29 ` Vishal Annapurve
2025-08-18 4:19 ` Yan Zhao
2025-08-07 9:46 ` [RFC PATCH v2 23/23] KVM: TDX: Turn on PG_LEVEL_2M after TD is RUNNABLE Yan Zhao
2025-11-11 11:25 ` Huang, Kai
2025-11-14 8:34 ` Yan Zhao
2025-11-18 0:56 ` Huang, Kai
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=20250807094616.4776-1-yan.y.zhao@intel.com \
--to=yan.y.zhao@intel.com \
--cc=ackerleytng@google.com \
--cc=binbin.wu@linux.intel.com \
--cc=chao.p.peng@intel.com \
--cc=dave.hansen@intel.com \
--cc=david@redhat.com \
--cc=fan.du@intel.com \
--cc=ira.weiny@intel.com \
--cc=isaku.yamahata@intel.com \
--cc=jun.miao@intel.com \
--cc=kas@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.com \
--cc=pgonda@google.com \
--cc=quic_eberman@quicinc.com \
--cc=rick.p.edgecombe@intel.com \
--cc=seanjc@google.com \
--cc=tabba@google.com \
--cc=thomas.lendacky@amd.com \
--cc=vannapurve@google.com \
--cc=vbabka@suse.cz \
--cc=x86@kernel.org \
--cc=xiaoyao.li@intel.com \
--cc=zhiquan1.li@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®