Commit 4d4c0285 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-x86-selftests-6.9' of https://github.com/kvm-x86/linux into HEAD

KVM selftests changes for 6.9:

 - Add macros to reduce the amount of boilerplate code needed to write "simple"
   selftests, and to utilize selftest TAP infrastructure, which is especially
   beneficial for KVM selftests with multiple testcases.

 - Add basic smoke tests for SEV and SEV-ES, along with a pile of library
   support for handling private/encrypted/protected memory.

 - Fix benign bugs where tests neglect to close() guest_memfd files.
parents f074158a e9da6f08
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ LIBKVM_x86_64 += lib/x86_64/handlers.S
LIBKVM_x86_64 += lib/x86_64/hyperv.c
LIBKVM_x86_64 += lib/x86_64/memstress.c
LIBKVM_x86_64 += lib/x86_64/processor.c
LIBKVM_x86_64 += lib/x86_64/sev.c
LIBKVM_x86_64 += lib/x86_64/svm.c
LIBKVM_x86_64 += lib/x86_64/ucall.c
LIBKVM_x86_64 += lib/x86_64/vmx.c
@@ -118,6 +119,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/vmx_pmu_caps_test
TEST_GEN_PROGS_x86_64 += x86_64/xen_shinfo_test
TEST_GEN_PROGS_x86_64 += x86_64/xen_vmcall_test
TEST_GEN_PROGS_x86_64 += x86_64/sev_migrate_tests
TEST_GEN_PROGS_x86_64 += x86_64/sev_smoke_test
TEST_GEN_PROGS_x86_64 += x86_64/amx_test
TEST_GEN_PROGS_x86_64 += x86_64/max_vcpuid_cap_test
TEST_GEN_PROGS_x86_64 += x86_64/triple_fault_event_test
+3 −0
Original line number Diff line number Diff line
@@ -167,6 +167,9 @@ static void test_create_guest_memfd_multiple(struct kvm_vm *vm)
	TEST_ASSERT(ret != -1, "memfd fstat should succeed");
	TEST_ASSERT(st1.st_size == 4096, "first memfd st_size should still match requested size");
	TEST_ASSERT(st1.st_ino != st2.st_ino, "different memfd should have different inode numbers");

	close(fd2);
	close(fd1);
}

int main(int argc, char *argv[])
+7 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SELFTEST_KVM_UTIL_ARCH_H
#define SELFTEST_KVM_UTIL_ARCH_H

struct kvm_vm_arch {};

#endif  // SELFTEST_KVM_UTIL_ARCH_H
+36 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Macros for defining a KVM test
 *
 * Copyright (C) 2022, Google LLC.
 */

#ifndef SELFTEST_KVM_TEST_HARNESS_H
#define SELFTEST_KVM_TEST_HARNESS_H

#include "kselftest_harness.h"

#define KVM_ONE_VCPU_TEST_SUITE(name)					\
	FIXTURE(name) {							\
		struct kvm_vcpu *vcpu;					\
	};								\
									\
	FIXTURE_SETUP(name) {						\
		(void)vm_create_with_one_vcpu(&self->vcpu, NULL);	\
	}								\
									\
	FIXTURE_TEARDOWN(name) {					\
		kvm_vm_free(self->vcpu->vm);				\
	}

#define KVM_ONE_VCPU_TEST(suite, test, guestcode)			\
static void __suite##_##test(struct kvm_vcpu *vcpu);			\
									\
TEST_F(suite, test)							\
{									\
	vcpu_arch_set_entry_point(self->vcpu, guestcode);		\
	__suite##_##test(self->vcpu);					\
}									\
static void __suite##_##test(struct kvm_vcpu *vcpu)

#endif /* SELFTEST_KVM_TEST_HARNESS_H */
+53 −8
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@
#include <linux/types.h>

#include <asm/atomic.h>
#include <asm/kvm.h>

#include <sys/ioctl.h>

#include "kvm_util_arch.h"
#include "sparsebit.h"

/*
@@ -46,6 +48,7 @@ typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
struct userspace_mem_region {
	struct kvm_userspace_memory_region2 region;
	struct sparsebit *unused_phy_pages;
	struct sparsebit *protected_phy_pages;
	int fd;
	off_t offset;
	enum vm_mem_backing_src_type backing_src_type;
@@ -90,6 +93,7 @@ enum kvm_mem_region_type {
struct kvm_vm {
	int mode;
	unsigned long type;
	uint8_t subtype;
	int kvm_fd;
	int fd;
	unsigned int pgtable_levels;
@@ -111,6 +115,9 @@ struct kvm_vm {
	vm_vaddr_t idt;
	vm_vaddr_t handlers;
	uint32_t dirty_ring_size;
	uint64_t gpa_tag_mask;

	struct kvm_vm_arch arch;

	/* Cache of information for binary stats interface */
	int stats_fd;
@@ -191,10 +198,14 @@ enum vm_guest_mode {
};

struct vm_shape {
	enum vm_guest_mode mode;
	unsigned int type;
	uint32_t type;
	uint8_t  mode;
	uint8_t  subtype;
	uint16_t padding;
};

kvm_static_assert(sizeof(struct vm_shape) == sizeof(uint64_t));

#define VM_TYPE_DEFAULT			0

#define VM_SHAPE(__mode)			\
@@ -564,6 +575,13 @@ void vm_mem_add(struct kvm_vm *vm, enum vm_mem_backing_src_type src_type,
		uint64_t guest_paddr, uint32_t slot, uint64_t npages,
		uint32_t flags, int guest_memfd_fd, uint64_t guest_memfd_offset);

#ifndef vm_arch_has_protected_memory
static inline bool vm_arch_has_protected_memory(struct kvm_vm *vm)
{
	return false;
}
#endif

void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags);
void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa);
void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot);
@@ -573,6 +591,9 @@ vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_mi
vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min);
vm_vaddr_t __vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
			    enum kvm_mem_region_type type);
vm_vaddr_t vm_vaddr_alloc_shared(struct kvm_vm *vm, size_t sz,
				 vm_vaddr_t vaddr_min,
				 enum kvm_mem_region_type type);
vm_vaddr_t vm_vaddr_alloc_pages(struct kvm_vm *vm, int nr_pages);
vm_vaddr_t __vm_vaddr_alloc_page(struct kvm_vm *vm,
				 enum kvm_mem_region_type type);
@@ -585,6 +606,12 @@ void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva);
vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva);
void *addr_gpa2alias(struct kvm_vm *vm, vm_paddr_t gpa);


static inline vm_paddr_t vm_untag_gpa(struct kvm_vm *vm, vm_paddr_t gpa)
{
	return gpa & ~vm->gpa_tag_mask;
}

void vcpu_run(struct kvm_vcpu *vcpu);
int _vcpu_run(struct kvm_vcpu *vcpu);

@@ -827,10 +854,23 @@ const char *exit_reason_str(unsigned int exit_reason);

vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
			     uint32_t memslot);
vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
			      vm_paddr_t paddr_min, uint32_t memslot);
vm_paddr_t __vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
				vm_paddr_t paddr_min, uint32_t memslot,
				bool protected);
vm_paddr_t vm_alloc_page_table(struct kvm_vm *vm);

static inline vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
					    vm_paddr_t paddr_min, uint32_t memslot)
{
	/*
	 * By default, allocate memory as protected for VMs that support
	 * protected memory, as the majority of memory for such VMs is
	 * protected, i.e. using shared memory is effectively opt-in.
	 */
	return __vm_phy_pages_alloc(vm, num, paddr_min, memslot,
				    vm_arch_has_protected_memory(vm));
}

/*
 * ____vm_create() does KVM_CREATE_VM and little else.  __vm_create() also
 * loads the test binary into guest memory and creates an IRQ chip (x86 only).
@@ -969,15 +1009,18 @@ static inline void vcpu_dump(FILE *stream, struct kvm_vcpu *vcpu,
 * Input Args:
 *   vm - Virtual Machine
 *   vcpu_id - The id of the VCPU to add to the VM.
 *   guest_code - The vCPU's entry point
 */
struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id,
				  void *guest_code);
struct kvm_vcpu *vm_arch_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id);
void vcpu_arch_set_entry_point(struct kvm_vcpu *vcpu, void *guest_code);

static inline struct kvm_vcpu *vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id,
					   void *guest_code)
{
	return vm_arch_vcpu_add(vm, vcpu_id, guest_code);
	struct kvm_vcpu *vcpu = vm_arch_vcpu_add(vm, vcpu_id);

	vcpu_arch_set_entry_point(vcpu, guest_code);

	return vcpu;
}

/* Re-create a vCPU after restarting a VM, e.g. for state save/restore tests. */
@@ -1081,6 +1124,8 @@ void kvm_selftest_arch_init(void);

void kvm_arch_vm_post_create(struct kvm_vm *vm);

bool vm_is_gpa_protected(struct kvm_vm *vm, vm_paddr_t paddr);

uint32_t guest_get_vcpuid(void);

#endif /* SELFTEST_KVM_UTIL_BASE_H */
Loading