Verify that creating a memslot overlapping the ucall MMIO region fails with EEXIST and that ucalls work before and after the attempt. Skip when MMIO ucalls or read-only memory are unsupported. Signed-off-by: Tharit Tangkijwanichakul --- tools/testing/selftests/kvm/Makefile.kvm | 1 + .../selftests/kvm/reserved_slot_test.c | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tools/testing/selftests/kvm/reserved_slot_test.c diff --git a/tools/testing/selftests/kvm/Makefile.kvm b/tools/testing/selftests/kvm/Makefile.kvm index 1f4bc2a1322d..ff4a5e9733e9 100644 --- a/tools/testing/selftests/kvm/Makefile.kvm +++ b/tools/testing/selftests/kvm/Makefile.kvm @@ -68,6 +68,7 @@ TEST_GEN_PROGS_COMMON += set_memory_region_test TEST_GEN_PROGS_COMMON += memslot_modification_stress_test TEST_GEN_PROGS_COMMON += memslot_perf_test TEST_GEN_PROGS_COMMON += vm_types_test +TEST_GEN_PROGS_COMMON += reserved_slot_test # Compiled test targets TEST_GEN_PROGS_x86 = $(TEST_GEN_PROGS_COMMON) diff --git a/tools/testing/selftests/kvm/reserved_slot_test.c b/tools/testing/selftests/kvm/reserved_slot_test.c new file mode 100644 index 000000000000..4a908017ca73 --- /dev/null +++ b/tools/testing/selftests/kvm/reserved_slot_test.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "kvm_util.h" +#include "processor.h" +#include "test_util.h" + +#define CLOBBERED_SLOT TEST_MEM_SLOT_BASE + +static void guest_code(void) +{ + GUEST_SYNC(1); + GUEST_SYNC(2); +} + +static void test_slot1_protected(void) +{ + struct kvm_vcpu *vcpu; + struct kvm_run *run; + struct kvm_vm *vm; + struct ucall uc; + u32 nr_pages; + size_t slot_size; + void *slot_mem; + int ret; + + vm = vm_create_with_one_vcpu(&vcpu, guest_code); + nr_pages = vm_adjust_num_guest_pages(vm->mode, 1); + slot_size = (size_t)nr_pages * vm->page_size; + + run = vcpu->run; + vcpu_run(vcpu); + TEST_ASSERT(run->exit_reason == KVM_EXIT_MMIO, + "Unexpected exit reason = %u", run->exit_reason); + TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC && uc.args[1] == 1, + "Expected the first sync before clobbering the ucall GPA"); + + slot_mem = kvm_mmap(slot_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1); + ret = __vm_set_user_memory_region2(vm, CLOBBERED_SLOT, 0, + vm->ucall_mmio_addr, slot_size, slot_mem, 0, 0); + TEST_ASSERT(ret == -1 && errno == EEXIST, + "Expected the ucall GPA overlap to be rejected: ret=%d errno=%d", + ret, errno); + + vcpu_run(vcpu); + TEST_ASSERT(run->exit_reason == KVM_EXIT_MMIO, + "Unexpected exit reason = %u", run->exit_reason); + TEST_ASSERT(get_ucall(vcpu, &uc) == UCALL_SYNC && uc.args[1] == 2, + "Expected the second sync after attempting to clobber the ucall GPA"); + + kvm_vm_free(vm); + TEST_ASSERT(!munmap(slot_mem, slot_size), "munmap() failed, errno=%d", errno); +} + +int main(void) +{ + TEST_REQUIRE(UCALL_EXIT_REASON == KVM_EXIT_MMIO); + TEST_REQUIRE(kvm_has_cap(KVM_CAP_READONLY_MEM)); + + test_slot1_protected(); + return 0; +} -- 2.53.0