aboutsummaryrefslogtreecommitdiff
path: root/testcases/kernel/kvm/include/kvm_host.h
blob: 2359944fd7acb5e024f93e4e4aeb4a83ebf7c44b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz>
 *
 * KVM host library for setting up and running virtual machine tests. Tests
 * can either use the default setup/run/host functions or use the advanced
 * API to create customized VMs.
 */

/*
 * Most basic usage:
 *
 * #include "kvm_test.h"
 *
 * #ifdef COMPILE_PAYLOAD
 *
 * void main(void)
 * {
 *	[VM guest code goes here]
 * }
 *
 * #else
 *
 * [optional VM host setup/run/cleanup code goes here]
 *
 * static struct tst_test test = {
 *	.test_all = tst_kvm_run,
 *	.setup = tst_kvm_setup,
 *	.cleanup = tst_kvm_cleanup,
 * };
 *
 * #endif
 */

#ifndef KVM_HOST_H_
#define KVM_HOST_H_

#include <inttypes.h>
#include <linux/kvm.h>
#include "kvm_common.h"

#define VM_KERNEL_BASEADDR 0x1000
#define VM_RESET_BASEADDR 0xfffffff0
#define VM_RESET_CODE_SIZE 8

#define MIN_FREE_RAM (10 * 1024 * 1024)
#define DEFAULT_RAM_SIZE (16 * 1024 * 1024)
#define MAX_KVM_MEMSLOTS 8

struct tst_kvm_instance {
	int vm_fd, vcpu_fd;
	struct kvm_run *vcpu_info;
	size_t vcpu_info_size;
	struct kvm_userspace_memory_region ram[MAX_KVM_MEMSLOTS];
	struct tst_kvm_result *result;
};

/* Test binary to be installed into the VM at VM_KERNEL_BASEADDR */
extern const char kvm_payload_start[], kvm_payload_end[];

/* CPU reset code to be installed into the VM at VM_RESET_BASEADDR */
extern const unsigned char tst_kvm_reset_code[VM_RESET_CODE_SIZE];

/* Default KVM test functions. */
void tst_kvm_setup(void);
void tst_kvm_run(void);
void tst_kvm_cleanup(void);

/*
 * Validate KVM guest test result (usually passed via result->result) and
 * fail with TBROK if the value cannot be safely passed to tst_res() or
 * tst_brk().
 */
void tst_kvm_validate_result(int value);

/*
 * Allocate memory slot for the VM. The returned pointer is page-aligned
 * so the actual requested base address is at ret[baseaddr % pagesize].
 *
 * The first argument is a VM file descriptor created by ioctl(KVM_CREATE_VM)
 *
 * The return value points to a guarded buffer and the user should not attempt
 * to free() it. Any extra space added at the beginning or end for page
 * alignment will be writable.
 */
void *tst_kvm_alloc_memory(struct tst_kvm_instance *inst, unsigned int slot,
	uint64_t baseaddr, size_t size, unsigned int flags);

/*
 * Translate VM virtual memory address to the corresponding physical address.
 * Returns 0 if the virtual address is unmapped or otherwise invalid.
 */
uint64_t tst_kvm_get_phys_address(const struct tst_kvm_instance *inst,
	uint64_t addr);

/*
 * Find the struct tst_kvm_instance memory slot ID for the give virtual
 * or physical VM memory address. Returns -1 if the address is not backed
 * by any memory buffer.
 */
int tst_kvm_find_phys_memslot(const struct tst_kvm_instance *inst,
	uint64_t paddr);
int tst_kvm_find_memslot(const struct tst_kvm_instance *inst, uint64_t addr);

/*
 * Convert VM virtual memory address to a directly usable pointer.
 */
void *tst_kvm_get_memptr(const struct tst_kvm_instance *inst, uint64_t addr);

/*
 * Find CPUIDs supported by KVM. x86_64 tests must set non-default CPUID,
 * otherwise bootstrap will fail to initialize 64bit mode.
 * Returns NULL if ioctl(KVM_GET_SUPPORTED_CPUID) is not supported.
 *
 * The argument is a file descriptor created by open("/dev/kvm")
 */
struct kvm_cpuid2 *tst_kvm_get_cpuid(int sysfd);

/*
 * Initialize the given KVM instance structure. Creates new KVM virtual machine
 * with 1 virtual CPU, allocates VM RAM (max. 4GB minus one page) and
 * shared result structure. KVM memory slots 0 and 1 will be set by this
 * function.
 */
void tst_kvm_create_instance(struct tst_kvm_instance *inst, size_t ram_size);

/*
 * Execute the given KVM instance and print results.
 */
void tst_kvm_run_instance(struct tst_kvm_instance *inst);

/*
 * Close the given KVM instance.
 */
void tst_kvm_destroy_instance(struct tst_kvm_instance *inst);

#endif /* KVM_HOST_H_ */