Re: [RFC PATCH v11 28/29] KVM: selftests: Add basic selftest for guest_memfd()
Sean Christopherson writes: > On Mon, Aug 07, 2023, Ackerley Tng wrote: >> Sean Christopherson writes: >> >> > Add a selftest to verify the basic functionality of guest_memfd(): >> > >> > >> >> Here's one more test: > > First off, thank you! I greatly appreciate all the selftests work you (and > others!) have been doing. > > For v2, can you please post a standalone patch? My workflow barfs on > unrelated, > inlined patches. I'm guessing I can get b4 to play nice, but it's easier to > just > yell at people :-) > Here's a standalone patch :) https://lore.kernel.org/lkml/20230821194411.2165757-1-ackerley...@google.com/ >
Re: [RFC PATCH v11 28/29] KVM: selftests: Add basic selftest for guest_memfd()
On Mon, Aug 07, 2023, Ackerley Tng wrote: > Sean Christopherson writes: > > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, total_size + page_size, > > page_size); > > + TEST_ASSERT(ret, "fallocate beginning at total_size should fail"); > > This should be > > TEST_ASSERT(ret, "fallocate beginning after total_size should fail"); Roger that, I'll push a fixup commit directly to kvm-x86/guest_memfd. Thanks!
Re: [RFC PATCH v11 28/29] KVM: selftests: Add basic selftest for guest_memfd()
On Mon, Aug 07, 2023, Ackerley Tng wrote: > Sean Christopherson writes: > > > Add a selftest to verify the basic functionality of guest_memfd(): > > > > > > Here's one more test: First off, thank you! I greatly appreciate all the selftests work you (and others!) have been doing. For v2, can you please post a standalone patch? My workflow barfs on unrelated, inlined patches. I'm guessing I can get b4 to play nice, but it's easier to just yell at people :-) > >From 72dc6836f01bdd613d64d4c6a4f2af8f2b777ba2 Mon Sep 17 00:00:00 2001 > From: Ackerley Tng > Date: Tue, 1 Aug 2023 18:02:50 + > Subject: [PATCH] KVM: selftests: Add tests - invalid inputs for > KVM_CREATE_GUEST_MEMFD > > Test that invalid inputs for KVM_CREATE_GUEST_MEMFD, such as > non-page-aligned page size and invalid flags, are rejected by the > KVM_CREATE_GUEST_MEMFD with EINVAL > > Signed-off-by: Ackerley Tng > --- > tools/testing/selftests/kvm/guest_memfd_test.c | 17 + > .../selftests/kvm/include/kvm_util_base.h | 11 +-- > 2 files changed, 26 insertions(+), 2 deletions(-) > > diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c > b/tools/testing/selftests/kvm/guest_memfd_test.c > index eb93c608a7e0..ad20f11b2d2c 100644 > --- a/tools/testing/selftests/kvm/guest_memfd_test.c > +++ b/tools/testing/selftests/kvm/guest_memfd_test.c > @@ -90,6 +90,21 @@ static void test_fallocate(int fd, size_t page_size, > size_t total_size) > TEST_ASSERT(!ret, "fallocate to restore punched hole should succeed"); > } > > +static void test_create_guest_memfd_invalid(struct kvm_vm *vm, size_t > page_size) > +{ > + int fd; > + > + /* Non-page-aligned page_size */ Instead of adding a comment, use the message from TEST_ASSERT() to communicate that information to the reader *and* to anyone that encounters failures. > + fd = __vm_create_guest_memfd(vm, 1, 0); ioctls() are fast. Rather than hardcode one value, iterate over a range of values, e.g. for (size = 0; size < page_size; size++) { r = __vm_create_guest_memfd(vm, size, 0); TEST_ASSERT(r && errno == EINVAL, "Informative error message...); } > + ASSERT_EQ(errno, EINVAL); > + > + /* Invalid flags */ > + fd = __vm_create_guest_memfd(vm, page_size, 99); > + ASSERT_EQ(fd, -1); > + ASSERT_EQ(errno, EINVAL); And then same thing here. Then you can use the legal flags to determine what is and isn't valid, instead of using a completely arbitrary magic number.
Re: [RFC PATCH v11 28/29] KVM: selftests: Add basic selftest for guest_memfd()
Sean Christopherson writes: > Add a selftest to verify the basic functionality of guest_memfd(): > > Here's one more test: >From 72dc6836f01bdd613d64d4c6a4f2af8f2b777ba2 Mon Sep 17 00:00:00 2001 From: Ackerley Tng Date: Tue, 1 Aug 2023 18:02:50 + Subject: [PATCH] KVM: selftests: Add tests - invalid inputs for KVM_CREATE_GUEST_MEMFD Test that invalid inputs for KVM_CREATE_GUEST_MEMFD, such as non-page-aligned page size and invalid flags, are rejected by the KVM_CREATE_GUEST_MEMFD with EINVAL Signed-off-by: Ackerley Tng --- tools/testing/selftests/kvm/guest_memfd_test.c | 17 + .../selftests/kvm/include/kvm_util_base.h | 11 +-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c index eb93c608a7e0..ad20f11b2d2c 100644 --- a/tools/testing/selftests/kvm/guest_memfd_test.c +++ b/tools/testing/selftests/kvm/guest_memfd_test.c @@ -90,6 +90,21 @@ static void test_fallocate(int fd, size_t page_size, size_t total_size) TEST_ASSERT(!ret, "fallocate to restore punched hole should succeed"); } +static void test_create_guest_memfd_invalid(struct kvm_vm *vm, size_t page_size) +{ + int fd; + + /* Non-page-aligned page_size */ + fd = __vm_create_guest_memfd(vm, 1, 0); + ASSERT_EQ(fd, -1); + ASSERT_EQ(errno, EINVAL); + + /* Invalid flags */ + fd = __vm_create_guest_memfd(vm, page_size, 99); + ASSERT_EQ(fd, -1); + ASSERT_EQ(errno, EINVAL); +} + int main(int argc, char *argv[]) { @@ -103,6 +118,8 @@ int main(int argc, char *argv[]) vm = vm_create_barebones(); + test_create_guest_memfd_invalid(vm, page_size); + fd = vm_create_guest_memfd(vm, total_size, 0); test_file_read_write(fd); diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h index 39b38c75b99c..8bdfadd72349 100644 --- a/tools/testing/selftests/kvm/include/kvm_util_base.h +++ b/tools/testing/selftests/kvm/include/kvm_util_base.h @@ -474,7 +474,8 @@ static inline uint64_t vm_get_stat(struct kvm_vm *vm, const char *stat_name) } void vm_create_irqchip(struct kvm_vm *vm); -static inline int vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size, + +static inline int __vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size, uint64_t flags) { struct kvm_create_guest_memfd gmem = { @@ -482,7 +483,13 @@ static inline int vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size, .flags = flags, }; - int fd = __vm_ioctl(vm, KVM_CREATE_GUEST_MEMFD, ); + return __vm_ioctl(vm, KVM_CREATE_GUEST_MEMFD, ); +} + +static inline int vm_create_guest_memfd(struct kvm_vm *vm, uint64_t size, + uint64_t flags) +{ + int fd = __vm_create_guest_memfd(vm, size, flags); TEST_ASSERT(fd >= 0, KVM_IOCTL_ERROR(KVM_CREATE_GUEST_MEMFD, fd)); return fd; -- 2.41.0.640.ga95def55d0-goog
Re: [RFC PATCH v11 28/29] KVM: selftests: Add basic selftest for guest_memfd()
Sean Christopherson writes: > Add a selftest to verify the basic functionality of guest_memfd(): > > + file descriptor created with the guest_memfd() ioctl does not allow > read/write/mmap operations > + file size and block size as returned from fstat are as expected > + fallocate on the fd checks that offset/length on > fallocate(FALLOC_FL_PUNCH_HOLE) should be page aligned > > > + > +static void test_fallocate(int fd, size_t page_size, size_t total_size) > +{ > + int ret; > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, total_size); > + TEST_ASSERT(!ret, "fallocate with aligned offset and size should > succeed"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, > + page_size - 1, page_size); > + TEST_ASSERT(ret, "fallocate with unaligned offset should fail"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, total_size, page_size); > + TEST_ASSERT(ret, "fallocate beginning at total_size should fail"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, total_size + page_size, > page_size); > + TEST_ASSERT(ret, "fallocate beginning at total_size should fail"); This should be TEST_ASSERT(ret, "fallocate beginning after total_size should fail"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, > + total_size, page_size); > + TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) at total_size should succeed"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, > + total_size + page_size, page_size); > + TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) after total_size should > succeed"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, > + page_size, page_size - 1); > + TEST_ASSERT(ret, "fallocate with unaligned size should fail"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, > + page_size, page_size); > + TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) with aligned offset and size > should succeed"); > + > + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, page_size, page_size); > + TEST_ASSERT(!ret, "fallocate to restore punched hole should succeed"); > +} >
[RFC PATCH v11 28/29] KVM: selftests: Add basic selftest for guest_memfd()
Add a selftest to verify the basic functionality of guest_memfd(): + file descriptor created with the guest_memfd() ioctl does not allow read/write/mmap operations + file size and block size as returned from fstat are as expected + fallocate on the fd checks that offset/length on fallocate(FALLOC_FL_PUNCH_HOLE) should be page aligned Signed-off-by: Chao Peng Co-developed-by: Ackerley Tng Signed-off-by: Ackerley Tng Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/Makefile | 1 + .../testing/selftests/kvm/guest_memfd_test.c | 114 ++ 2 files changed, 115 insertions(+) create mode 100644 tools/testing/selftests/kvm/guest_memfd_test.c diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile index fdc7dff8d6ae..18c43336ede3 100644 --- a/tools/testing/selftests/kvm/Makefile +++ b/tools/testing/selftests/kvm/Makefile @@ -123,6 +123,7 @@ TEST_GEN_PROGS_x86_64 += access_tracking_perf_test TEST_GEN_PROGS_x86_64 += demand_paging_test TEST_GEN_PROGS_x86_64 += dirty_log_test TEST_GEN_PROGS_x86_64 += dirty_log_perf_test +TEST_GEN_PROGS_x86_64 += guest_memfd_test TEST_GEN_PROGS_x86_64 += hardware_disable_test TEST_GEN_PROGS_x86_64 += kvm_create_max_vcpus TEST_GEN_PROGS_x86_64 += kvm_page_table_test diff --git a/tools/testing/selftests/kvm/guest_memfd_test.c b/tools/testing/selftests/kvm/guest_memfd_test.c new file mode 100644 index ..d698f9fde987 --- /dev/null +++ b/tools/testing/selftests/kvm/guest_memfd_test.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright Intel Corporation, 2023 + * + * Author: Chao Peng + */ + +#define _GNU_SOURCE +#include "test_util.h" +#include "kvm_util_base.h" +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +static void test_file_read_write(int fd) +{ + char buf[64]; + + TEST_ASSERT(read(fd, buf, sizeof(buf)) < 0, + "read on a guest_mem fd should fail"); + TEST_ASSERT(write(fd, buf, sizeof(buf)) < 0, + "write on a guest_mem fd should fail"); + TEST_ASSERT(pread(fd, buf, sizeof(buf), 0) < 0, + "pread on a guest_mem fd should fail"); + TEST_ASSERT(pwrite(fd, buf, sizeof(buf), 0) < 0, + "pwrite on a guest_mem fd should fail"); +} + +static void test_mmap(int fd, size_t page_size) +{ + char *mem; + + mem = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + ASSERT_EQ(mem, MAP_FAILED); +} + +static void test_file_size(int fd, size_t page_size, size_t total_size) +{ + struct stat sb; + int ret; + + ret = fstat(fd, ); + TEST_ASSERT(!ret, "fstat should succeed"); + ASSERT_EQ(sb.st_size, total_size); + ASSERT_EQ(sb.st_blksize, page_size); +} + +static void test_fallocate(int fd, size_t page_size, size_t total_size) +{ + int ret; + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, 0, total_size); + TEST_ASSERT(!ret, "fallocate with aligned offset and size should succeed"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, + page_size - 1, page_size); + TEST_ASSERT(ret, "fallocate with unaligned offset should fail"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, total_size, page_size); + TEST_ASSERT(ret, "fallocate beginning at total_size should fail"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, total_size + page_size, page_size); + TEST_ASSERT(ret, "fallocate beginning at total_size should fail"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, + total_size, page_size); + TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) at total_size should succeed"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, + total_size + page_size, page_size); + TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) after total_size should succeed"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, + page_size, page_size - 1); + TEST_ASSERT(ret, "fallocate with unaligned size should fail"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, + page_size, page_size); + TEST_ASSERT(!ret, "fallocate(PUNCH_HOLE) with aligned offset and size should succeed"); + + ret = fallocate(fd, FALLOC_FL_KEEP_SIZE, page_size, page_size); + TEST_ASSERT(!ret, "fallocate to restore punched hole should succeed"); +} + + +int main(int argc, char *argv[]) +{ + size_t page_size; + size_t total_size; + int fd; + struct kvm_vm *vm; + + page_size = getpagesize(); + total_size = page_size * 4; + + vm = vm_create_barebones(); + + fd = vm_create_guest_memfd(vm, total_size, 0); + + test_file_read_write(fd); + test_mmap(fd, page_size); +