File Index
Files and directories
Sign in
FILE

private_mem_kvm_exits_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/kvm/x86/private_mem_kvm_exits_test.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (C) 2023, Google LLC.
  4 */
  5#include <linux/kvm.h>
  6#include <pthread.h>
  7#include <stdint.h>
  8
  9#include "kvm_util.h"
 10#include "processor.h"
 11#include "test_util.h"
 12
 13/* Arbitrarily selected to avoid overlaps with anything else */
 14#define EXITS_TEST_GVA 0xc0000000
 15#define EXITS_TEST_GPA EXITS_TEST_GVA
 16#define EXITS_TEST_NPAGES 1
 17#define EXITS_TEST_SIZE (EXITS_TEST_NPAGES * PAGE_SIZE)
 18#define EXITS_TEST_SLOT 10
 19
 20static uint64_t guest_repeatedly_read(void)
 21{
 22	volatile uint64_t value;
 23
 24	while (true)
 25		value = *((uint64_t *) EXITS_TEST_GVA);
 26
 27	return value;
 28}
 29
 30static uint32_t run_vcpu_get_exit_reason(struct kvm_vcpu *vcpu)
 31{
 32	int r;
 33
 34	r = _vcpu_run(vcpu);
 35	if (r) {
 36		TEST_ASSERT(errno == EFAULT, KVM_IOCTL_ERROR(KVM_RUN, r));
 37		TEST_ASSERT_EQ(vcpu->run->exit_reason, KVM_EXIT_MEMORY_FAULT);
 38	}
 39	return vcpu->run->exit_reason;
 40}
 41
 42const struct vm_shape protected_vm_shape = {
 43	.mode = VM_MODE_DEFAULT,
 44	.type = KVM_X86_SW_PROTECTED_VM,
 45};
 46
 47static void test_private_access_memslot_deleted(void)
 48{
 49	struct kvm_vm *vm;
 50	struct kvm_vcpu *vcpu;
 51	pthread_t vm_thread;
 52	void *thread_return;
 53	uint32_t exit_reason;
 54
 55	vm = vm_create_shape_with_one_vcpu(protected_vm_shape, &vcpu,
 56					   guest_repeatedly_read);
 57
 58	vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
 59				    EXITS_TEST_GPA, EXITS_TEST_SLOT,
 60				    EXITS_TEST_NPAGES,
 61				    KVM_MEM_GUEST_MEMFD);
 62
 63	virt_map(vm, EXITS_TEST_GVA, EXITS_TEST_GPA, EXITS_TEST_NPAGES);
 64
 65	/* Request to access page privately */
 66	vm_mem_set_private(vm, EXITS_TEST_GPA, EXITS_TEST_SIZE);
 67
 68	pthread_create(&vm_thread, NULL,
 69		       (void *(*)(void *))run_vcpu_get_exit_reason,
 70		       (void *)vcpu);
 71
 72	vm_mem_region_delete(vm, EXITS_TEST_SLOT);
 73
 74	pthread_join(vm_thread, &thread_return);
 75	exit_reason = (uint32_t)(uint64_t)thread_return;
 76
 77	TEST_ASSERT_EQ(exit_reason, KVM_EXIT_MEMORY_FAULT);
 78	TEST_ASSERT_EQ(vcpu->run->memory_fault.flags, KVM_MEMORY_EXIT_FLAG_PRIVATE);
 79	TEST_ASSERT_EQ(vcpu->run->memory_fault.gpa, EXITS_TEST_GPA);
 80	TEST_ASSERT_EQ(vcpu->run->memory_fault.size, EXITS_TEST_SIZE);
 81
 82	kvm_vm_free(vm);
 83}
 84
 85static void test_private_access_memslot_not_private(void)
 86{
 87	struct kvm_vm *vm;
 88	struct kvm_vcpu *vcpu;
 89	uint32_t exit_reason;
 90
 91	vm = vm_create_shape_with_one_vcpu(protected_vm_shape, &vcpu,
 92					   guest_repeatedly_read);
 93
 94	/* Add a non-private memslot (flags = 0) */
 95	vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS,
 96				    EXITS_TEST_GPA, EXITS_TEST_SLOT,
 97				    EXITS_TEST_NPAGES, 0);
 98
 99	virt_map(vm, EXITS_TEST_GVA, EXITS_TEST_GPA, EXITS_TEST_NPAGES);
100
101	/* Request to access page privately */
102	vm_mem_set_private(vm, EXITS_TEST_GPA, EXITS_TEST_SIZE);
103
104	exit_reason = run_vcpu_get_exit_reason(vcpu);
105
106	TEST_ASSERT_EQ(exit_reason, KVM_EXIT_MEMORY_FAULT);
107	TEST_ASSERT_EQ(vcpu->run->memory_fault.flags, KVM_MEMORY_EXIT_FLAG_PRIVATE);
108	TEST_ASSERT_EQ(vcpu->run->memory_fault.gpa, EXITS_TEST_GPA);
109	TEST_ASSERT_EQ(vcpu->run->memory_fault.size, EXITS_TEST_SIZE);
110
111	kvm_vm_free(vm);
112}
113
114int main(int argc, char *argv[])
115{
116	TEST_REQUIRE(kvm_check_cap(KVM_CAP_VM_TYPES) & BIT(KVM_X86_SW_PROTECTED_VM));
117
118	test_private_access_memslot_deleted();
119	test_private_access_memslot_not_private();
120}
~/ Read-only file preview.