]>
Commit | Line | Data |
---|---|---|
7a338472 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
783e9e51 PB |
2 | /* |
3 | * tools/testing/selftests/kvm/include/kvm_util.h | |
4 | * | |
5 | * Copyright (C) 2018, Google LLC. | |
783e9e51 PB |
6 | */ |
7 | #ifndef SELFTEST_KVM_UTIL_H | |
cc68765d | 8 | #define SELFTEST_KVM_UTIL_H |
783e9e51 PB |
9 | |
10 | #include "test_util.h" | |
11 | ||
12 | #include "asm/kvm.h" | |
13 | #include "linux/kvm.h" | |
14 | #include <sys/ioctl.h> | |
15 | ||
16 | #include "sparsebit.h" | |
17 | ||
783e9e51 | 18 | |
42593624 AJ |
19 | /* |
20 | * Callers of kvm_util only have an incomplete/opaque description of the | |
783e9e51 PB |
21 | * structure kvm_util is using to maintain the state of a VM. |
22 | */ | |
23 | struct kvm_vm; | |
24 | ||
25 | typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ | |
26 | typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ | |
27 | ||
28 | /* Minimum allocated guest virtual and physical addresses */ | |
eabe7881 | 29 | #define KVM_UTIL_MIN_VADDR 0x2000 |
783e9e51 PB |
30 | |
31 | #define DEFAULT_GUEST_PHY_PAGES 512 | |
32 | #define DEFAULT_GUEST_STACK_VADDR_MIN 0xab6000 | |
eabe7881 | 33 | #define DEFAULT_STACK_PGS 5 |
783e9e51 PB |
34 | |
35 | enum vm_guest_mode { | |
81d1cca0 AJ |
36 | VM_MODE_P52V48_4K, |
37 | VM_MODE_P52V48_64K, | |
cdbd2428 AJ |
38 | VM_MODE_P48V48_4K, |
39 | VM_MODE_P48V48_64K, | |
e28934e6 AJ |
40 | VM_MODE_P40V48_4K, |
41 | VM_MODE_P40V48_64K, | |
567a9f1e | 42 | VM_MODE_PXXV48_4K, /* For 48bits VA but ANY bits PA */ |
81d1cca0 | 43 | NUM_VM_MODES, |
783e9e51 PB |
44 | }; |
45 | ||
567a9f1e | 46 | #if defined(__aarch64__) |
fe85ec86 | 47 | #define VM_MODE_DEFAULT VM_MODE_P40V48_4K |
567a9f1e PX |
48 | #elif defined(__x86_64__) |
49 | #define VM_MODE_DEFAULT VM_MODE_PXXV48_4K | |
fe85ec86 TH |
50 | #else |
51 | #define VM_MODE_DEFAULT VM_MODE_P52V48_4K | |
52 | #endif | |
53 | ||
81d1cca0 AJ |
54 | #define vm_guest_mode_string(m) vm_guest_mode_string[m] |
55 | extern const char * const vm_guest_mode_string[]; | |
56 | ||
783e9e51 PB |
57 | enum vm_mem_backing_src_type { |
58 | VM_MEM_SRC_ANONYMOUS, | |
59 | VM_MEM_SRC_ANONYMOUS_THP, | |
60 | VM_MEM_SRC_ANONYMOUS_HUGETLB, | |
61 | }; | |
62 | ||
63 | int kvm_check_cap(long cap); | |
8b56ee91 | 64 | int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap); |
783e9e51 PB |
65 | |
66 | struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm); | |
12c386b2 | 67 | struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm); |
783e9e51 | 68 | void kvm_vm_free(struct kvm_vm *vmp); |
fa3899ad PB |
69 | void kvm_vm_restart(struct kvm_vm *vmp, int perm); |
70 | void kvm_vm_release(struct kvm_vm *vmp); | |
3b4cd0ff | 71 | void kvm_vm_get_dirty_log(struct kvm_vm *vm, int slot, void *log); |
2a31b9db PB |
72 | void kvm_vm_clear_dirty_log(struct kvm_vm *vm, int slot, void *log, |
73 | uint64_t first_page, uint32_t num_pages); | |
783e9e51 | 74 | |
eabe7881 AJ |
75 | int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, const vm_vaddr_t gva, |
76 | size_t len); | |
783e9e51 | 77 | |
6089ae0b | 78 | void kvm_vm_elf_load(struct kvm_vm *vm, const char *filename, |
eabe7881 | 79 | uint32_t data_memslot, uint32_t pgd_memslot); |
6089ae0b | 80 | |
783e9e51 | 81 | void vm_dump(FILE *stream, struct kvm_vm *vm, uint8_t indent); |
42593624 AJ |
82 | |
83 | /* | |
84 | * VM VCPU Dump | |
85 | * | |
86 | * Input Args: | |
87 | * stream - Output FILE stream | |
88 | * vm - Virtual Machine | |
89 | * vcpuid - VCPU ID | |
90 | * indent - Left margin indent amount | |
91 | * | |
92 | * Output Args: None | |
93 | * | |
94 | * Return: None | |
95 | * | |
96 | * Dumps the current state of the VCPU specified by @vcpuid, within the VM | |
97 | * given by @vm, to the FILE stream given by @stream. | |
98 | */ | |
eabe7881 AJ |
99 | void vcpu_dump(FILE *stream, struct kvm_vm *vm, uint32_t vcpuid, |
100 | uint8_t indent); | |
783e9e51 PB |
101 | |
102 | void vm_create_irqchip(struct kvm_vm *vm); | |
103 | ||
104 | void vm_userspace_mem_region_add(struct kvm_vm *vm, | |
105 | enum vm_mem_backing_src_type src_type, | |
106 | uint64_t guest_paddr, uint32_t slot, uint64_t npages, | |
107 | uint32_t flags); | |
108 | ||
eabe7881 AJ |
109 | void vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid, unsigned long ioctl, |
110 | void *arg); | |
7e50c424 VK |
111 | int _vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid, unsigned long ioctl, |
112 | void *arg); | |
783e9e51 PB |
113 | void vm_ioctl(struct kvm_vm *vm, unsigned long ioctl, void *arg); |
114 | void vm_mem_region_set_flags(struct kvm_vm *vm, uint32_t slot, uint32_t flags); | |
13e48aa9 | 115 | void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa); |
837ec79b | 116 | void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid); |
783e9e51 | 117 | vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min, |
eabe7881 | 118 | uint32_t data_memslot, uint32_t pgd_memslot); |
3b4cd0ff | 119 | void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, |
beca5470 | 120 | unsigned int npages, uint32_t pgd_memslot); |
783e9e51 PB |
121 | void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa); |
122 | void *addr_gva2hva(struct kvm_vm *vm, vm_vaddr_t gva); | |
123 | vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva); | |
42593624 AJ |
124 | |
125 | /* | |
126 | * Address Guest Virtual to Guest Physical | |
127 | * | |
128 | * Input Args: | |
129 | * vm - Virtual Machine | |
130 | * gva - VM virtual address | |
131 | * | |
132 | * Output Args: None | |
133 | * | |
134 | * Return: | |
135 | * Equivalent VM physical address | |
136 | * | |
137 | * Returns the VM physical address of the translated VM virtual | |
138 | * address given by @gva. | |
139 | */ | |
783e9e51 PB |
140 | vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva); |
141 | ||
142 | struct kvm_run *vcpu_state(struct kvm_vm *vm, uint32_t vcpuid); | |
143 | void vcpu_run(struct kvm_vm *vm, uint32_t vcpuid); | |
144 | int _vcpu_run(struct kvm_vm *vm, uint32_t vcpuid); | |
0f73bbc8 | 145 | void vcpu_run_complete_io(struct kvm_vm *vm, uint32_t vcpuid); |
449aa906 PX |
146 | void vcpu_set_guest_debug(struct kvm_vm *vm, uint32_t vcpuid, |
147 | struct kvm_guest_debug *debug); | |
783e9e51 | 148 | void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid, |
eabe7881 AJ |
149 | struct kvm_mp_state *mp_state); |
150 | void vcpu_regs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs); | |
151 | void vcpu_regs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs); | |
42593624 AJ |
152 | |
153 | /* | |
154 | * VM VCPU Args Set | |
155 | * | |
156 | * Input Args: | |
157 | * vm - Virtual Machine | |
158 | * vcpuid - VCPU ID | |
159 | * num - number of arguments | |
160 | * ... - arguments, each of type uint64_t | |
161 | * | |
162 | * Output Args: None | |
163 | * | |
164 | * Return: None | |
165 | * | |
166 | * Sets the first @num function input registers of the VCPU with @vcpuid, | |
167 | * per the C calling convention of the architecture, to the values given | |
168 | * as variable args. Each of the variable args is expected to be of type | |
169 | * uint64_t. The maximum @num can be is specific to the architecture. | |
170 | */ | |
783e9e51 | 171 | void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...); |
42593624 | 172 | |
eabe7881 AJ |
173 | void vcpu_sregs_get(struct kvm_vm *vm, uint32_t vcpuid, |
174 | struct kvm_sregs *sregs); | |
175 | void vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, | |
176 | struct kvm_sregs *sregs); | |
177 | int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, | |
178 | struct kvm_sregs *sregs); | |
ada0a50d JF |
179 | void vcpu_fpu_get(struct kvm_vm *vm, uint32_t vcpuid, |
180 | struct kvm_fpu *fpu); | |
181 | void vcpu_fpu_set(struct kvm_vm *vm, uint32_t vcpuid, | |
182 | struct kvm_fpu *fpu); | |
183 | void vcpu_get_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg); | |
184 | void vcpu_set_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg); | |
a9c788f0 | 185 | #ifdef __KVM_HAVE_VCPU_EVENTS |
783e9e51 | 186 | void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid, |
eabe7881 | 187 | struct kvm_vcpu_events *events); |
783e9e51 | 188 | void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid, |
eabe7881 | 189 | struct kvm_vcpu_events *events); |
a9c788f0 | 190 | #endif |
c7957206 | 191 | #ifdef __x86_64__ |
da1e3071 AL |
192 | void vcpu_nested_state_get(struct kvm_vm *vm, uint32_t vcpuid, |
193 | struct kvm_nested_state *state); | |
194 | int vcpu_nested_state_set(struct kvm_vm *vm, uint32_t vcpuid, | |
195 | struct kvm_nested_state *state, bool ignore_error); | |
c7957206 | 196 | #endif |
783e9e51 PB |
197 | |
198 | const char *exit_reason_str(unsigned int exit_reason); | |
199 | ||
200 | void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot); | |
42593624 AJ |
201 | |
202 | /* | |
203 | * VM Virtual Page Map | |
204 | * | |
205 | * Input Args: | |
206 | * vm - Virtual Machine | |
207 | * vaddr - VM Virtual Address | |
208 | * paddr - VM Physical Address | |
209 | * memslot - Memory region slot for new virtual translation tables | |
210 | * | |
211 | * Output Args: None | |
212 | * | |
213 | * Return: None | |
214 | * | |
215 | * Within @vm, creates a virtual translation for the page starting | |
216 | * at @vaddr to the page starting at @paddr. | |
217 | */ | |
783e9e51 | 218 | void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, |
42593624 AJ |
219 | uint32_t memslot); |
220 | ||
eabe7881 AJ |
221 | vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min, |
222 | uint32_t memslot); | |
d5106539 AJ |
223 | vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num, |
224 | vm_paddr_t paddr_min, uint32_t memslot); | |
783e9e51 | 225 | |
42593624 AJ |
226 | /* |
227 | * Create a VM with reasonable defaults | |
228 | * | |
229 | * Input Args: | |
230 | * vcpuid - The id of the single VCPU to add to the VM. | |
beca5470 | 231 | * extra_mem_pages - The number of extra pages to add (this will |
42593624 AJ |
232 | * decide how much extra space we will need to |
233 | * setup the page tables using memslot 0) | |
234 | * guest_code - The vCPU's entry point | |
235 | * | |
236 | * Output Args: None | |
237 | * | |
238 | * Return: | |
239 | * Pointer to opaque structure that describes the created VM. | |
240 | */ | |
beca5470 | 241 | struct kvm_vm *vm_create_default(uint32_t vcpuid, uint64_t extra_mem_pages, |
aee41be5 | 242 | void *guest_code); |
42593624 AJ |
243 | |
244 | /* | |
245 | * Adds a vCPU with reasonable defaults (e.g. a stack) | |
246 | * | |
247 | * Input Args: | |
248 | * vm - Virtual Machine | |
249 | * vcpuid - The id of the VCPU to add to the VM. | |
250 | * guest_code - The vCPU's entry point | |
251 | */ | |
783e9e51 PB |
252 | void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code); |
253 | ||
9dba988e AL |
254 | bool vm_is_unrestricted_guest(struct kvm_vm *vm); |
255 | ||
52200d0d PX |
256 | unsigned int vm_get_page_size(struct kvm_vm *vm); |
257 | unsigned int vm_get_page_shift(struct kvm_vm *vm); | |
258 | unsigned int vm_get_max_gfn(struct kvm_vm *vm); | |
259 | ||
94c4b76b | 260 | unsigned int vm_calc_num_guest_pages(enum vm_guest_mode mode, size_t size); |
87a802d9 AJ |
261 | unsigned int vm_num_host_pages(enum vm_guest_mode mode, unsigned int num_guest_pages); |
262 | unsigned int vm_num_guest_pages(enum vm_guest_mode mode, unsigned int num_host_pages); | |
263 | static inline unsigned int | |
264 | vm_adjust_num_guest_pages(enum vm_guest_mode mode, unsigned int num_guest_pages) | |
265 | { | |
331b4de9 AJ |
266 | unsigned int n; |
267 | n = vm_num_guest_pages(mode, vm_num_host_pages(mode, num_guest_pages)); | |
268 | #ifdef __s390x__ | |
269 | /* s390 requires 1M aligned guest sizes */ | |
270 | n = (n + 255) & ~255; | |
271 | #endif | |
272 | return n; | |
87a802d9 AJ |
273 | } |
274 | ||
783e9e51 PB |
275 | struct kvm_userspace_memory_region * |
276 | kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start, | |
277 | uint64_t end); | |
278 | ||
279 | struct kvm_dirty_log * | |
280 | allocate_kvm_dirty_log(struct kvm_userspace_memory_region *region); | |
281 | ||
282 | int vm_create_device(struct kvm_vm *vm, struct kvm_create_device *cd); | |
283 | ||
14c47b75 AJ |
284 | #define sync_global_to_guest(vm, g) ({ \ |
285 | typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g)); \ | |
286 | memcpy(_p, &(g), sizeof(g)); \ | |
287 | }) | |
288 | ||
289 | #define sync_global_from_guest(vm, g) ({ \ | |
290 | typeof(g) *_p = addr_gva2hva(vm, (vm_vaddr_t)&(g)); \ | |
291 | memcpy(&(g), _p, sizeof(g)); \ | |
292 | }) | |
293 | ||
14c47b75 AJ |
294 | /* Common ucalls */ |
295 | enum { | |
296 | UCALL_NONE, | |
297 | UCALL_SYNC, | |
298 | UCALL_ABORT, | |
299 | UCALL_DONE, | |
300 | }; | |
4e18bccc | 301 | |
14c47b75 | 302 | #define UCALL_MAX_ARGS 6 |
4e18bccc | 303 | |
14c47b75 AJ |
304 | struct ucall { |
305 | uint64_t cmd; | |
306 | uint64_t args[UCALL_MAX_ARGS]; | |
307 | }; | |
4e18bccc | 308 | |
2040f414 | 309 | void ucall_init(struct kvm_vm *vm, void *arg); |
14c47b75 AJ |
310 | void ucall_uninit(struct kvm_vm *vm); |
311 | void ucall(uint64_t cmd, int nargs, ...); | |
312 | uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc); | |
313 | ||
314 | #define GUEST_SYNC(stage) ucall(UCALL_SYNC, 2, "hello", stage) | |
315 | #define GUEST_DONE() ucall(UCALL_DONE, 0) | |
316 | #define GUEST_ASSERT(_condition) do { \ | |
317 | if (!(_condition)) \ | |
318 | ucall(UCALL_ABORT, 2, \ | |
319 | "Failed guest assert: " \ | |
320 | #_condition, __LINE__); \ | |
321 | } while (0) | |
4e18bccc | 322 | |
783e9e51 | 323 | #endif /* SELFTEST_KVM_UTIL_H */ |