From: "Pratik R. Sampat" <pratikrajesh.sampat@amd.com>
To: <kvm@vger.kernel.org>
Cc: <seanjc@google.com>, <pbonzini@redhat.com>, <pgonda@google.com>,
<thomas.lendacky@amd.com>, <michael.roth@amd.com>,
<shuah@kernel.org>, <linux-kselftest@vger.kernel.org>,
<linux-kernel@vger.kernel.org>
Subject: [PATCH v3 9/9] KVM: selftests: Interleave fallocate for KVM_PRE_FAULT_MEMORY
Date: Thu, 5 Sep 2024 07:41:07 -0500 [thread overview]
Message-ID: <20240905124107.6954-10-pratikrajesh.sampat@amd.com> (raw)
In-Reply-To: <20240905124107.6954-1-pratikrajesh.sampat@amd.com>
fallocate triggers gmem_prepare(), and KVM_PRE_FAULT_MEMORY can cause
guest page faults at unexpected points. Therefore, introduce several
test cases to interleave fallocate, hole punching through various
parts of the SNP launch lifecycle, and observe both positive and
negative vcpcu_run exit statuses.
Signed-off-by: Pratik R. Sampat <pratikrajesh.sampat@amd.com>
Tested-by: Peter Gonda <pgonda@google.com>
Tested-by: Srikanth Aithal <sraithal@amd.com>
---
.../kvm/x86_64/coco_pre_fault_memory_test.c | 121 +++++++++++++++++-
1 file changed, 114 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c b/tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c
index c31a5f9e18f4..e9757ba3234c 100644
--- a/tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c
+++ b/tools/testing/selftests/kvm/x86_64/coco_pre_fault_memory_test.c
@@ -47,6 +47,31 @@ enum prefault_snp_test_type {
PREFAULT_PRIVATE_SHARED_AFTER_FINALIZING
};
+enum falloc_snp_test_type {
+ /* Skip alloc tests. */
+ NO_ALLOC_TYPE,
+ /*
+ * Allocate and/or deallocate a region of guest memfd before
+ * memory regions are updated to be protected and encrypted
+ *
+ * This should succeed since allocation and deallocation is
+ * supported before the memory is finalized.
+ */
+ ALLOC_BEFORE_UPDATE,
+ ALLOC_AFTER_UPDATE,
+ DEALLOC_BEFORE_UPDATE,
+ ALLOC_DEALLOC_BEFORE_UPDATE,
+ /*
+ * Allocate and/or deallocate a region of guest memfd after
+ * memory regions are updated to be protected and encrypted
+ *
+ * This should fail since dealloc will nuke the pages that
+ * contain the initial code that the guest will run.
+ */
+ DEALLOC_AFTER_UPDATE,
+ ALLOC_DEALLOC_AFTER_UPDATE
+};
+
static void guest_code_sev(void)
{
int i;
@@ -73,6 +98,29 @@ static void guest_code_sev(void)
GUEST_DONE();
}
+static void __falloc_region(struct kvm_vm *vm, bool punch_hole)
+{
+ int ctr, ret, flags = FALLOC_FL_KEEP_SIZE;
+ struct userspace_mem_region *region;
+
+ hash_for_each(vm->regions.slot_hash, ctr, region, slot_node) {
+ if (punch_hole)
+ flags |= FALLOC_FL_PUNCH_HOLE;
+ ret = fallocate(region->region.guest_memfd, flags, 0, PAGE_SIZE * TEST_NPAGES);
+ TEST_ASSERT(!ret, "fallocate should succeed.");
+ }
+}
+
+static void gmemfd_alloc(struct kvm_vm *vm)
+{
+ __falloc_region(vm, false);
+}
+
+static void gmemfd_dealloc(struct kvm_vm *vm)
+{
+ __falloc_region(vm, true);
+}
+
static void __pre_fault_memory(struct kvm_vcpu *vcpu, u64 gpa, u64 size,
u64 left, bool expect_fail)
{
@@ -137,13 +185,34 @@ static void pre_fault_memory_negative(struct kvm_vcpu *vcpu, u64 gpa,
}
static void pre_fault_memory_snp(struct kvm_vcpu *vcpu, struct kvm_vm *vm,
- bool private, enum prefault_snp_test_type p_type)
+ bool private, enum prefault_snp_test_type p_type,
+ enum falloc_snp_test_type f_type)
{
+ if (f_type == ALLOC_BEFORE_UPDATE ||
+ f_type == ALLOC_DEALLOC_BEFORE_UPDATE) {
+ gmemfd_alloc(vm);
+ }
+
+ if (f_type == DEALLOC_BEFORE_UPDATE ||
+ f_type == ALLOC_DEALLOC_BEFORE_UPDATE) {
+ gmemfd_dealloc(vm);
+ }
+
if (p_type == PREFAULT_SHARED_BEFORE_FINALIZING)
pre_fault_memory_negative(vcpu, TEST_GPA, SZ_2M, 0);
snp_vm_launch_start(vm, SNP_POLICY);
+ if (f_type == ALLOC_BEFORE_UPDATE ||
+ f_type == ALLOC_DEALLOC_BEFORE_UPDATE) {
+ gmemfd_alloc(vm);
+ }
+
+ if (f_type == DEALLOC_BEFORE_UPDATE ||
+ f_type == ALLOC_DEALLOC_BEFORE_UPDATE) {
+ gmemfd_dealloc(vm);
+ }
+
if (p_type == PREFAULT_SHARED_BEFORE_FINALIZING)
pre_fault_memory_negative(vcpu, TEST_GPA, SZ_2M, 0);
@@ -164,11 +233,36 @@ static void pre_fault_memory_snp(struct kvm_vcpu *vcpu, struct kvm_vm *vm,
snp_vm_launch_update(vm);
+ if (f_type == ALLOC_AFTER_UPDATE ||
+ f_type == ALLOC_DEALLOC_AFTER_UPDATE) {
+ gmemfd_alloc(vm);
+ }
+
+ /*
+ * Hole-punch after SNP LAUNCH UPDATE is not expected to fail
+ * immediately, rather its affects are observed on vcpu_run()
+ * as the pages that contain the initial code is nuked.
+ */
+ if (f_type == DEALLOC_AFTER_UPDATE ||
+ f_type == ALLOC_DEALLOC_AFTER_UPDATE) {
+ gmemfd_dealloc(vm);
+ }
+
if (p_type == PREFAULT_SHARED_BEFORE_FINALIZING)
pre_fault_memory_negative(vcpu, TEST_GPA, SZ_2M, 0);
snp_vm_launch_finish(vm);
+ if (f_type == ALLOC_AFTER_UPDATE ||
+ f_type == ALLOC_DEALLOC_AFTER_UPDATE) {
+ gmemfd_alloc(vm);
+ }
+
+ if (f_type == DEALLOC_AFTER_UPDATE ||
+ f_type == ALLOC_DEALLOC_AFTER_UPDATE) {
+ gmemfd_dealloc(vm);
+ }
+
/*
* After finalization, pre-faulting either private or shared
* ranges should work regardless of whether the pages were
@@ -210,7 +304,8 @@ static void pre_fault_memory_sev(unsigned long vm_type, struct kvm_vcpu *vcpu,
}
static void test_pre_fault_memory_sev(unsigned long vm_type, bool private,
- enum prefault_snp_test_type p_type)
+ enum prefault_snp_test_type p_type,
+ enum falloc_snp_test_type f_type)
{
struct kvm_vcpu *vcpu;
struct kvm_vm *vm;
@@ -246,12 +341,22 @@ static void test_pre_fault_memory_sev(unsigned long vm_type, bool private,
}
if (vm_type == KVM_X86_SNP_VM)
- pre_fault_memory_snp(vcpu, vm, private, p_type);
+ pre_fault_memory_snp(vcpu, vm, private, p_type, f_type);
else
pre_fault_memory_sev(vm_type, vcpu, vm);
vcpu_run(vcpu);
+ /* Expect SHUTDOWN when we falloc using PUNCH_HOLE after SNP_UPDATE */
+ if (vm->type == KVM_X86_SNP_VM &&
+ (f_type == DEALLOC_AFTER_UPDATE ||
+ f_type == ALLOC_DEALLOC_AFTER_UPDATE)) {
+ TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SHUTDOWN,
+ "Wanted SYSTEM_EVENT, got %s",
+ exit_reason_str(vcpu->run->exit_reason));
+ goto out;
+ }
+
if (vm->type == KVM_X86_SEV_ES_VM || vm->type == KVM_X86_SNP_VM) {
TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SYSTEM_EVENT,
"Wanted SYSTEM_EVENT, got %s",
@@ -278,7 +383,7 @@ static void test_pre_fault_memory_sev(unsigned long vm_type, bool private,
static void test_pre_fault_memory(unsigned long vm_type, bool private)
{
- int pt;
+ int pt, ft;
if (vm_type && !(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(vm_type))) {
pr_info("Skipping tests for vm_type 0x%lx\n", vm_type);
@@ -288,11 +393,13 @@ static void test_pre_fault_memory(unsigned long vm_type, bool private)
switch (vm_type) {
case KVM_X86_SEV_VM:
case KVM_X86_SEV_ES_VM:
- test_pre_fault_memory_sev(vm_type, private, NO_PREFAULT_TYPE);
+ test_pre_fault_memory_sev(vm_type, private, NO_PREFAULT_TYPE, NO_ALLOC_TYPE);
break;
case KVM_X86_SNP_VM:
- for (pt = 0; pt <= PREFAULT_PRIVATE_SHARED_AFTER_FINALIZING; pt++)
- test_pre_fault_memory_sev(vm_type, private, pt);
+ for (pt = 0; pt <= PREFAULT_PRIVATE_SHARED_AFTER_FINALIZING; pt++) {
+ for (ft = 0; ft <= ALLOC_DEALLOC_AFTER_UPDATE; ft++)
+ test_pre_fault_memory_sev(vm_type, private, pt, ft);
+ }
break;
default:
abort();
--
2.34.1
next prev parent reply other threads:[~2024-09-05 12:43 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-05 12:40 [PATCH v3 0/9] SEV Kernel Selftests Pratik R. Sampat
2024-09-05 12:40 ` [PATCH v3 1/9] KVM: selftests: Decouple SEV ioctls from asserts Pratik R. Sampat
2024-10-14 22:18 ` Sean Christopherson
2024-10-21 20:23 ` Pratik R. Sampat
2024-09-05 12:41 ` [PATCH v3 2/9] KVM: selftests: Add a basic SNP smoke test Pratik R. Sampat
2024-10-14 22:46 ` Sean Christopherson
2024-10-21 20:23 ` Pratik R. Sampat
2024-10-28 17:55 ` Sean Christopherson
2024-10-28 20:41 ` Pratik R. Sampat
2024-10-30 13:46 ` Sean Christopherson
2024-10-30 16:35 ` Pratik R. Sampat
2024-10-30 17:57 ` Sean Christopherson
2024-10-31 15:45 ` Pratik R. Sampat
2024-10-31 16:27 ` Sean Christopherson
2024-11-04 20:21 ` Pratik R. Sampat
2024-11-04 23:47 ` Sean Christopherson
2024-11-05 4:14 ` Pratik R. Sampat
2024-09-05 12:41 ` [PATCH v3 3/9] KVM: selftests: Add SNP to shutdown testing Pratik R. Sampat
2024-09-05 12:41 ` [PATCH v3 4/9] KVM: selftests: SEV IOCTL test Pratik R. Sampat
2024-09-05 12:41 ` [PATCH v3 5/9] KVM: selftests: SNP " Pratik R. Sampat
2024-09-05 12:41 ` [PATCH v3 6/9] KVM: selftests: SEV-SNP test for KVM_SEV_INIT2 Pratik R. Sampat
2024-09-05 12:41 ` [PATCH v3 7/9] KVM: selftests: Add interface to manually flag protected/encrypted ranges Pratik R. Sampat
2024-10-14 22:58 ` Sean Christopherson
2024-10-21 20:23 ` Pratik R. Sampat
2024-09-05 12:41 ` [PATCH v3 8/9] KVM: selftests: Add a CoCo-specific test for KVM_PRE_FAULT_MEMORY Pratik R. Sampat
2024-09-05 12:41 ` Pratik R. Sampat [this message]
2024-10-14 22:23 ` [PATCH v3 0/9] SEV Kernel Selftests Sean Christopherson
2024-10-21 20:23 ` Pratik R. Sampat
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=20240905124107.6954-10-pratikrajesh.sampat@amd.com \
--to=pratikrajesh.sampat@amd.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.com \
--cc=pgonda@google.com \
--cc=seanjc@google.com \
--cc=shuah@kernel.org \
--cc=thomas.lendacky@amd.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