Skip to content

Commit 4218866

Browse files
sean-jcbonzini
authored andcommitted
KVM: selftests: Add guest_memfd testcase to fault-in on !mmap()'d memory
Add a guest_memfd testcase to verify that a vCPU can fault-in guest_memfd memory that supports mmap(), but that is not currently mapped into host userspace and/or has a userspace address (in the memslot) that points at something other than the target guest_memfd range. Mapping guest_memfd memory into the guest is supposed to operate completely independently from any userspace mappings. Signed-off-by: Sean Christopherson <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent a11d712 commit 4218866

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

tools/testing/selftests/kvm/guest_memfd_test.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <linux/bitmap.h>
1515
#include <linux/falloc.h>
16+
#include <linux/sizes.h>
1617
#include <setjmp.h>
1718
#include <signal.h>
1819
#include <sys/mman.h>
@@ -21,6 +22,7 @@
2122

2223
#include "kvm_util.h"
2324
#include "test_util.h"
25+
#include "ucall_common.h"
2426

2527
static void test_file_read_write(int fd)
2628
{
@@ -298,6 +300,66 @@ static void test_guest_memfd(unsigned long vm_type)
298300
kvm_vm_free(vm);
299301
}
300302

303+
static void guest_code(uint8_t *mem, uint64_t size)
304+
{
305+
size_t i;
306+
307+
for (i = 0; i < size; i++)
308+
__GUEST_ASSERT(mem[i] == 0xaa,
309+
"Guest expected 0xaa at offset %lu, got 0x%x", i, mem[i]);
310+
311+
memset(mem, 0xff, size);
312+
GUEST_DONE();
313+
}
314+
315+
static void test_guest_memfd_guest(void)
316+
{
317+
/*
318+
* Skip the first 4gb and slot0. slot0 maps <1gb and is used to back
319+
* the guest's code, stack, and page tables, and low memory contains
320+
* the PCI hole and other MMIO regions that need to be avoided.
321+
*/
322+
const uint64_t gpa = SZ_4G;
323+
const int slot = 1;
324+
325+
struct kvm_vcpu *vcpu;
326+
struct kvm_vm *vm;
327+
uint8_t *mem;
328+
size_t size;
329+
int fd, i;
330+
331+
if (!kvm_has_cap(KVM_CAP_GUEST_MEMFD_MMAP))
332+
return;
333+
334+
vm = __vm_create_shape_with_one_vcpu(VM_SHAPE_DEFAULT, &vcpu, 1, guest_code);
335+
336+
TEST_ASSERT(vm_check_cap(vm, KVM_CAP_GUEST_MEMFD_MMAP),
337+
"Default VM type should always support guest_memfd mmap()");
338+
339+
size = vm->page_size;
340+
fd = vm_create_guest_memfd(vm, size, GUEST_MEMFD_FLAG_MMAP);
341+
vm_set_user_memory_region2(vm, slot, KVM_MEM_GUEST_MEMFD, gpa, size, NULL, fd, 0);
342+
343+
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
344+
TEST_ASSERT(mem != MAP_FAILED, "mmap() on guest_memfd failed");
345+
memset(mem, 0xaa, size);
346+
munmap(mem, size);
347+
348+
virt_pg_map(vm, gpa, gpa);
349+
vcpu_args_set(vcpu, 2, gpa, size);
350+
vcpu_run(vcpu);
351+
352+
TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE);
353+
354+
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
355+
TEST_ASSERT(mem != MAP_FAILED, "mmap() on guest_memfd failed");
356+
for (i = 0; i < size; i++)
357+
TEST_ASSERT_EQ(mem[i], 0xff);
358+
359+
close(fd);
360+
kvm_vm_free(vm);
361+
}
362+
301363
int main(int argc, char *argv[])
302364
{
303365
unsigned long vm_types, vm_type;
@@ -314,4 +376,6 @@ int main(int argc, char *argv[])
314376

315377
for_each_set_bit(vm_type, &vm_types, BITS_PER_TYPE(vm_types))
316378
test_guest_memfd(vm_type);
379+
380+
test_guest_memfd_guest();
317381
}

0 commit comments

Comments
 (0)