From: Yosry Ahmed <yosry.ahmed@linux.dev>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Yosry Ahmed <yosry.ahmed@linux.dev>
Subject: [PATCH v3 13/16] KVM: selftests: Add support for nested NPTs
Date: Thu, 27 Nov 2025 01:34:37 +0000 [thread overview]
Message-ID: <20251127013440.3324671-14-yosry.ahmed@linux.dev> (raw)
In-Reply-To: <20251127013440.3324671-1-yosry.ahmed@linux.dev>
Implement nCR3 and NPT initialization functions, similar to the EPT
equivalents, and create common TDP helpers for enablement checking and
initialization. Enable NPT for nested guests by default if the TDP MMU
was initialized, similar to VMX.
Reuse the PTE masks from the main MMU in the NPT MMU, except for the C
and S bits related to confidential VMs.
Signed-off-by: Yosry Ahmed <yosry.ahmed@linux.dev>
---
.../selftests/kvm/include/x86/processor.h | 2 ++
.../selftests/kvm/include/x86/svm_util.h | 9 ++++++++
.../testing/selftests/kvm/lib/x86/memstress.c | 4 ++--
.../testing/selftests/kvm/lib/x86/processor.c | 15 +++++++++++++
tools/testing/selftests/kvm/lib/x86/svm.c | 22 +++++++++++++++++++
.../selftests/kvm/x86/vmx_dirty_log_test.c | 4 ++--
6 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/x86/processor.h b/tools/testing/selftests/kvm/include/x86/processor.h
index 95216b513379..920abd14f3a6 100644
--- a/tools/testing/selftests/kvm/include/x86/processor.h
+++ b/tools/testing/selftests/kvm/include/x86/processor.h
@@ -1487,6 +1487,8 @@ void __virt_pg_map(struct kvm_vm *vm, struct kvm_mmu *mmu, uint64_t vaddr,
void virt_map_level(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
uint64_t nr_bytes, int level);
+void vm_enable_tdp(struct kvm_vm *vm);
+bool kvm_cpu_has_tdp(void);
void tdp_map(struct kvm_vm *vm, uint64_t nested_paddr, uint64_t paddr, uint64_t size);
void tdp_identity_map_default_memslots(struct kvm_vm *vm);
void tdp_identity_map_1g(struct kvm_vm *vm, uint64_t addr, uint64_t size);
diff --git a/tools/testing/selftests/kvm/include/x86/svm_util.h b/tools/testing/selftests/kvm/include/x86/svm_util.h
index b74c6dcddcbd..5d7c42534bc4 100644
--- a/tools/testing/selftests/kvm/include/x86/svm_util.h
+++ b/tools/testing/selftests/kvm/include/x86/svm_util.h
@@ -27,6 +27,9 @@ struct svm_test_data {
void *msr; /* gva */
void *msr_hva;
uint64_t msr_gpa;
+
+ /* NPT */
+ uint64_t ncr3_gpa;
};
static inline void vmmcall(void)
@@ -57,6 +60,12 @@ struct svm_test_data *vcpu_alloc_svm(struct kvm_vm *vm, vm_vaddr_t *p_svm_gva);
void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_rsp);
void run_guest(struct vmcb *vmcb, uint64_t vmcb_gpa);
+static inline bool kvm_cpu_has_npt(void)
+{
+ return kvm_cpu_has(X86_FEATURE_NPT);
+}
+void vm_enable_npt(struct kvm_vm *vm);
+
int open_sev_dev_path_or_exit(void);
#endif /* SELFTEST_KVM_SVM_UTILS_H */
diff --git a/tools/testing/selftests/kvm/lib/x86/memstress.c b/tools/testing/selftests/kvm/lib/x86/memstress.c
index 3319cb57a78d..407abfc34909 100644
--- a/tools/testing/selftests/kvm/lib/x86/memstress.c
+++ b/tools/testing/selftests/kvm/lib/x86/memstress.c
@@ -82,9 +82,9 @@ void memstress_setup_nested(struct kvm_vm *vm, int nr_vcpus, struct kvm_vcpu *vc
int vcpu_id;
TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX));
- TEST_REQUIRE(kvm_cpu_has_ept());
+ TEST_REQUIRE(kvm_cpu_has_tdp());
- vm_enable_ept(vm);
+ vm_enable_tdp(vm);
for (vcpu_id = 0; vcpu_id < nr_vcpus; vcpu_id++) {
vcpu_alloc_vmx(vm, &vmx_gva);
diff --git a/tools/testing/selftests/kvm/lib/x86/processor.c b/tools/testing/selftests/kvm/lib/x86/processor.c
index 517a8185eade..b22c8c1bfdc3 100644
--- a/tools/testing/selftests/kvm/lib/x86/processor.c
+++ b/tools/testing/selftests/kvm/lib/x86/processor.c
@@ -8,7 +8,9 @@
#include "kvm_util.h"
#include "pmu.h"
#include "processor.h"
+#include "svm_util.h"
#include "sev.h"
+#include "vmx.h"
#ifndef NUM_INTERRUPTS
#define NUM_INTERRUPTS 256
@@ -467,6 +469,19 @@ void virt_arch_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent)
}
}
+void vm_enable_tdp(struct kvm_vm *vm)
+{
+ if (kvm_cpu_has(X86_FEATURE_VMX))
+ vm_enable_ept(vm);
+ else
+ vm_enable_npt(vm);
+}
+
+bool kvm_cpu_has_tdp(void)
+{
+ return kvm_cpu_has_ept() || kvm_cpu_has_npt();
+}
+
/*
* Map a range of TDP guest physical addresses to the VM's physical address
*
diff --git a/tools/testing/selftests/kvm/lib/x86/svm.c b/tools/testing/selftests/kvm/lib/x86/svm.c
index d239c2097391..cf3b98802164 100644
--- a/tools/testing/selftests/kvm/lib/x86/svm.c
+++ b/tools/testing/selftests/kvm/lib/x86/svm.c
@@ -59,6 +59,23 @@ static void vmcb_set_seg(struct vmcb_seg *seg, u16 selector,
seg->base = base;
}
+void vm_enable_npt(struct kvm_vm *vm)
+{
+ struct pte_masks pte_masks;
+
+ TEST_ASSERT(kvm_cpu_has_npt(), "KVM doesn't supported nested NPT");
+
+ if (vm->arch.nested.mmu)
+ return;
+
+ /* NPTs use the same PTE format, except for C/S bits */
+ pte_masks = vm->arch.mmu->pte_masks;
+ pte_masks.c = 0;
+ pte_masks.s = 0;
+
+ vm->arch.nested.mmu = mmu_create(vm, vm->pgtable_levels, &pte_masks);
+}
+
void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_rsp)
{
struct vmcb *vmcb = svm->vmcb;
@@ -102,6 +119,11 @@ void generic_svm_setup(struct svm_test_data *svm, void *guest_rip, void *guest_r
vmcb->save.rip = (u64)guest_rip;
vmcb->save.rsp = (u64)guest_rsp;
guest_regs.rdi = (u64)svm;
+
+ if (svm->ncr3_gpa) {
+ ctrl->nested_ctl |= SVM_NESTED_CTL_NP_ENABLE;
+ ctrl->nested_cr3 = svm->ncr3_gpa;
+ }
}
/*
diff --git a/tools/testing/selftests/kvm/x86/vmx_dirty_log_test.c b/tools/testing/selftests/kvm/x86/vmx_dirty_log_test.c
index 370f8d3117c2..032ab8bf60a4 100644
--- a/tools/testing/selftests/kvm/x86/vmx_dirty_log_test.c
+++ b/tools/testing/selftests/kvm/x86/vmx_dirty_log_test.c
@@ -93,7 +93,7 @@ static void test_vmx_dirty_log(bool enable_ept)
/* Create VM */
vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code);
if (enable_ept)
- vm_enable_ept(vm);
+ vm_enable_tdp(vm);
vcpu_alloc_vmx(vm, &vmx_pages_gva);
vcpu_args_set(vcpu, 1, vmx_pages_gva);
@@ -170,7 +170,7 @@ int main(int argc, char *argv[])
test_vmx_dirty_log(/*enable_ept=*/false);
- if (kvm_cpu_has_ept())
+ if (kvm_cpu_has_tdp())
test_vmx_dirty_log(/*enable_ept=*/true);
return 0;
--
2.52.0.158.g65b55ccf14-goog
next prev parent reply other threads:[~2025-11-27 1:35 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-27 1:34 [PATCH v3 00/16] Add Nested NPT support in selftests Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 01/16] KVM: selftests: Make __vm_get_page_table_entry() static Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 02/16] KVM: selftests: Stop passing a memslot to nested_map_memslot() Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 03/16] KVM: selftests: Rename nested TDP mapping functions Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 04/16] KVM: selftests: Kill eptPageTablePointer Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 05/16] KVM: selftests: Stop setting AD bits on nested EPTs on creation Yosry Ahmed
2025-12-23 22:26 ` Sean Christopherson
2025-12-23 23:35 ` Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 06/16] KVM: selftests: Introduce struct kvm_mmu Yosry Ahmed
2025-12-23 22:29 ` Sean Christopherson
2025-12-23 23:38 ` Yosry Ahmed
2025-12-29 15:24 ` Sean Christopherson
2025-11-27 1:34 ` [PATCH v3 07/16] KVM: selftests: Move PTE bitmasks to kvm_mmu Yosry Ahmed
2025-12-23 22:31 ` Sean Christopherson
2025-12-23 23:40 ` Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 08/16] KVM: selftests: Use a nested MMU to share nested EPTs between vCPUs Yosry Ahmed
2025-12-23 23:16 ` Sean Christopherson
2025-11-27 1:34 ` [PATCH v3 09/16] KVM: selftests: Stop passing VMX metadata to TDP mapping functions Yosry Ahmed
2025-12-15 18:38 ` Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 10/16] KVM: selftests: Reuse virt mapping functions for nested EPTs Yosry Ahmed
2025-12-23 23:12 ` Sean Christopherson
2025-12-23 23:45 ` Yosry Ahmed
2025-12-30 0:08 ` Sean Christopherson
2025-12-30 4:03 ` Yosry Ahmed
2025-12-30 15:43 ` Sean Christopherson
2025-12-23 23:14 ` Sean Christopherson
2025-12-23 23:47 ` Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 11/16] KVM: selftests: Move TDP mapping functions outside of vmx.c Yosry Ahmed
2025-12-23 23:13 ` Sean Christopherson
2025-11-27 1:34 ` [PATCH v3 12/16] KVM: selftests: Allow kvm_cpu_has_ept() to be called on AMD CPUs Yosry Ahmed
2025-11-27 1:34 ` Yosry Ahmed [this message]
2025-11-27 1:34 ` [PATCH v3 14/16] KVM: selftests: Set the user bit on nested NPT PTEs Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 15/16] KVM: selftests: Extend vmx_dirty_log_test to cover SVM Yosry Ahmed
2025-11-27 1:34 ` [PATCH v3 16/16] KVM: selftests: Extend memstress to run on nested SVM Yosry Ahmed
2025-12-23 22:01 ` [PATCH v3 00/16] Add Nested NPT support in selftests Sean Christopherson
2025-12-23 23:48 ` Yosry Ahmed
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=20251127013440.3324671-14-yosry.ahmed@linux.dev \
--to=yosry.ahmed@linux.dev \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.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®