From: Sean Christopherson <seanjc@google.com>
To: Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Michael Roth <michael.roth@amd.com>
Subject: [PATCH gmem 3/5] KVM: selftests: Let user specify nr of memslots in private mem conversion
Date: Mon, 23 Oct 2023 12:15:30 -0700 [thread overview]
Message-ID: <20231023191532.2405326-4-seanjc@google.com> (raw)
In-Reply-To: <20231023191532.2405326-1-seanjc@google.com>
Let the user specify the number of memslots in the private mem conversion
test, i.e. don't require the number of memslots to be '1' or "nr_vcpus".
Creating more memslots than vCPUs is particularly interesting, e.g. it can
result in a single KVM_SET_MEMORY_ATTRIBUTES spanning multiple memslots.
This also fixes an issue where the test will crash when running with
multiple vCPUs but only a single memslot.
To keep the math reasonable, align each vCPU's chunk to at least 2MiB (the
size is 2MiB+4KiB), and require the total size to be cleanly divisible by
the number of memslots. The goal is to be able to validate that KVM plays
nice with multiple memslots, being able to create a truly arbitrary number
of memslots doesn't add meaningful value, i.e. isn't worth the cost.
Reported-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
.../kvm/x86_64/private_mem_conversions_test.c | 36 +++++++++++--------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c b/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c
index c3992a295b5a..3f6d8d4dbc53 100644
--- a/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c
+++ b/tools/testing/selftests/kvm/x86_64/private_mem_conversions_test.c
@@ -371,8 +371,10 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, uint32_t
* Allocate enough memory so that each vCPU's chunk of memory can be
* naturally aligned with respect to the size of the backing store.
*/
- const size_t size = align_up(PER_CPU_DATA_SIZE, get_backing_src_pagesz(src_type));
- const size_t memfd_size = size * nr_vcpus;
+ const size_t alignment = max_t(size_t, SZ_2M, get_backing_src_pagesz(src_type));
+ const size_t per_cpu_size = align_up(PER_CPU_DATA_SIZE, alignment);
+ const size_t memfd_size = per_cpu_size * nr_vcpus;
+ const size_t slot_size = memfd_size / nr_memslots;
struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
pthread_t threads[KVM_MAX_VCPUS];
uint64_t gmem_flags;
@@ -384,6 +386,9 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, uint32_t
.type = KVM_X86_SW_PROTECTED_VM,
};
+ TEST_ASSERT(slot_size * nr_memslots == memfd_size,
+ "The memfd size (0x%lx) needs to be cleanly divisible by the number of memslots (%u)",
+ memfd_size, nr_memslots);
vm = __vm_create_with_vcpus(shape, nr_vcpus, 0, guest_code, vcpus);
vm_enable_cap(vm, KVM_CAP_EXIT_HYPERCALL, (1 << KVM_HC_MAP_GPA_RANGE));
@@ -395,16 +400,20 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, uint32_t
memfd = vm_create_guest_memfd(vm, memfd_size, gmem_flags);
for (i = 0; i < nr_memslots; i++)
- vm_mem_add(vm, src_type, BASE_DATA_GPA + size * i,
- BASE_DATA_SLOT + i, size / vm->page_size,
- KVM_MEM_PRIVATE, memfd, size * i);
+ vm_mem_add(vm, src_type, BASE_DATA_GPA + slot_size * i,
+ BASE_DATA_SLOT + i, slot_size / vm->page_size,
+ KVM_MEM_PRIVATE, memfd, slot_size * i);
for (i = 0; i < nr_vcpus; i++) {
- uint64_t gpa = BASE_DATA_GPA + i * size;
+ uint64_t gpa = BASE_DATA_GPA + i * per_cpu_size;
vcpu_args_set(vcpus[i], 1, gpa);
- virt_map(vm, gpa, gpa, size / vm->page_size);
+ /*
+ * Map only what is needed so that an out-of-bounds access
+ * results #PF => SHUTDOWN instead of data corruption.
+ */
+ virt_map(vm, gpa, gpa, PER_CPU_DATA_SIZE / vm->page_size);
pthread_create(&threads[i], NULL, __test_mem_conversions, vcpus[i]);
}
@@ -432,29 +441,28 @@ static void test_mem_conversions(enum vm_mem_backing_src_type src_type, uint32_t
static void usage(const char *cmd)
{
puts("");
- printf("usage: %s [-h] [-m] [-s mem_type] [-n nr_vcpus]\n", cmd);
+ printf("usage: %s [-h] [-m nr_memslots] [-s mem_type] [-n nr_vcpus]\n", cmd);
puts("");
backing_src_help("-s");
puts("");
puts(" -n: specify the number of vcpus (default: 1)");
puts("");
- puts(" -m: use multiple memslots (default: 1)");
+ puts(" -m: specify the number of memslots (default: 1)");
puts("");
}
int main(int argc, char *argv[])
{
enum vm_mem_backing_src_type src_type = DEFAULT_VM_MEM_SRC;
- bool use_multiple_memslots = false;
+ uint32_t nr_memslots = 1;
uint32_t nr_vcpus = 1;
- uint32_t nr_memslots;
int opt;
TEST_REQUIRE(kvm_has_cap(KVM_CAP_GUEST_MEMFD));
TEST_REQUIRE(kvm_has_cap(KVM_CAP_EXIT_HYPERCALL));
TEST_REQUIRE(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM));
- while ((opt = getopt(argc, argv, "hms:n:")) != -1) {
+ while ((opt = getopt(argc, argv, "hm:s:n:")) != -1) {
switch (opt) {
case 's':
src_type = parse_backing_src_type(optarg);
@@ -463,7 +471,7 @@ int main(int argc, char *argv[])
nr_vcpus = atoi_positive("nr_vcpus", optarg);
break;
case 'm':
- use_multiple_memslots = true;
+ nr_memslots = atoi_positive("nr_memslots", optarg);
break;
case 'h':
default:
@@ -472,8 +480,6 @@ int main(int argc, char *argv[])
}
}
- nr_memslots = use_multiple_memslots ? nr_vcpus : 1;
-
test_mem_conversions(src_type, nr_vcpus, nr_memslots);
return 0;
--
2.42.0.758.gaed0368e0e-goog
next prev parent reply other threads:[~2023-10-23 19:15 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-23 19:15 [PATCH gmem 0/5] KVM: selftests: Fix multiple memslots in conv test Sean Christopherson
2023-10-23 19:15 ` [PATCH gmem 1/5] KVM: selftests: Rework fallocate() helper to work across multiple memslots Sean Christopherson
2023-10-23 19:15 ` [PATCH gmem 2/5] KVM: selftests: Handle memslot splits in private mem conversions test Sean Christopherson
2023-10-23 19:15 ` Sean Christopherson [this message]
2023-10-23 19:15 ` [PATCH gmem 4/5] KVM: selftests: Use dedicated pattern for testing that mem is shared by default Sean Christopherson
2023-10-23 19:15 ` [PATCH gmem 5/5] KVM: selftests: Verify default pattern was written in private mem conversion Sean Christopherson
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=20231023191532.2405326-4-seanjc@google.com \
--to=seanjc@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=michael.roth@amd.com \
--cc=pbonzini@redhat.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®