forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/tools/testing/selftests/kvm/lib/kvm_util.c
....@@ -1,25 +1,24 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * tools/testing/selftests/kvm/lib/kvm_util.c
34 *
45 * Copyright (C) 2018, Google LLC.
5
- *
6
- * This work is licensed under the terms of the GNU GPL, version 2.
76 */
87
98 #include "test_util.h"
109 #include "kvm_util.h"
1110 #include "kvm_util_internal.h"
11
+#include "processor.h"
1212
1313 #include <assert.h>
1414 #include <sys/mman.h>
1515 #include <sys/types.h>
1616 #include <sys/stat.h>
17
+#include <unistd.h>
1718 #include <linux/kernel.h>
1819
19
-#define KVM_DEV_PATH "/dev/kvm"
20
-
2120 #define KVM_UTIL_PGS_PER_HUGEPG 512
22
-#define KVM_UTIL_MIN_PADDR 0x2000
21
+#define KVM_UTIL_MIN_PFN 2
2322
2423 /* Aligns x up to the next multiple of size. Size must be a power of 2. */
2524 static void *align(void *x, size_t size)
....@@ -30,7 +29,8 @@
3029 return (void *) (((size_t) x + mask) & ~mask);
3130 }
3231
33
-/* Capability
32
+/*
33
+ * Capability
3434 *
3535 * Input Args:
3636 * cap - Capability
....@@ -86,22 +86,86 @@
8686 return ret;
8787 }
8888
89
+/* VCPU Enable Capability
90
+ *
91
+ * Input Args:
92
+ * vm - Virtual Machine
93
+ * vcpu_id - VCPU
94
+ * cap - Capability
95
+ *
96
+ * Output Args: None
97
+ *
98
+ * Return: On success, 0. On failure a TEST_ASSERT failure is produced.
99
+ *
100
+ * Enables a capability (KVM_CAP_*) on the VCPU.
101
+ */
102
+int vcpu_enable_cap(struct kvm_vm *vm, uint32_t vcpu_id,
103
+ struct kvm_enable_cap *cap)
104
+{
105
+ struct vcpu *vcpu = vcpu_find(vm, vcpu_id);
106
+ int r;
107
+
108
+ TEST_ASSERT(vcpu, "cannot find vcpu %d", vcpu_id);
109
+
110
+ r = ioctl(vcpu->fd, KVM_ENABLE_CAP, cap);
111
+ TEST_ASSERT(!r, "KVM_ENABLE_CAP vCPU ioctl failed,\n"
112
+ " rc: %i, errno: %i", r, errno);
113
+
114
+ return r;
115
+}
116
+
89117 static void vm_open(struct kvm_vm *vm, int perm)
90118 {
91119 vm->kvm_fd = open(KVM_DEV_PATH, perm);
92120 if (vm->kvm_fd < 0)
93121 exit(KSFT_SKIP);
94122
95
- /* Create VM. */
96
- vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, NULL);
123
+ if (!kvm_check_cap(KVM_CAP_IMMEDIATE_EXIT)) {
124
+ print_skip("immediate_exit not available");
125
+ exit(KSFT_SKIP);
126
+ }
127
+
128
+ vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, vm->type);
97129 TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, "
98130 "rc: %i errno: %i", vm->fd, errno);
99131 }
100132
101
-/* VM Create
133
+const char * const vm_guest_mode_string[] = {
134
+ "PA-bits:52, VA-bits:48, 4K pages",
135
+ "PA-bits:52, VA-bits:48, 64K pages",
136
+ "PA-bits:48, VA-bits:48, 4K pages",
137
+ "PA-bits:48, VA-bits:48, 64K pages",
138
+ "PA-bits:40, VA-bits:48, 4K pages",
139
+ "PA-bits:40, VA-bits:48, 64K pages",
140
+ "PA-bits:ANY, VA-bits:48, 4K pages",
141
+};
142
+_Static_assert(sizeof(vm_guest_mode_string)/sizeof(char *) == NUM_VM_MODES,
143
+ "Missing new mode strings?");
144
+
145
+struct vm_guest_mode_params {
146
+ unsigned int pa_bits;
147
+ unsigned int va_bits;
148
+ unsigned int page_size;
149
+ unsigned int page_shift;
150
+};
151
+
152
+static const struct vm_guest_mode_params vm_guest_mode_params[] = {
153
+ { 52, 48, 0x1000, 12 },
154
+ { 52, 48, 0x10000, 16 },
155
+ { 48, 48, 0x1000, 12 },
156
+ { 48, 48, 0x10000, 16 },
157
+ { 40, 48, 0x1000, 12 },
158
+ { 40, 48, 0x10000, 16 },
159
+ { 0, 0, 0x1000, 12 },
160
+};
161
+_Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
162
+ "Missing new mode params?");
163
+
164
+/*
165
+ * VM Create
102166 *
103167 * Input Args:
104
- * mode - VM Mode (e.g. VM_MODE_FLAT48PG)
168
+ * mode - VM Mode (e.g. VM_MODE_P52V48_4K)
105169 * phy_pages - Physical memory pages
106170 * perm - permission
107171 *
....@@ -110,7 +174,7 @@
110174 * Return:
111175 * Pointer to opaque structure that describes the created VM.
112176 *
113
- * Creates a VM with the mode specified by mode (e.g. VM_MODE_FLAT48PG).
177
+ * Creates a VM with the mode specified by mode (e.g. VM_MODE_P52V48_4K).
114178 * When phy_pages is non-zero, a memory region of phy_pages physical pages
115179 * is created and mapped starting at guest physical address 0. The file
116180 * descriptor to control the created VM is created with the permissions
....@@ -119,36 +183,84 @@
119183 struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
120184 {
121185 struct kvm_vm *vm;
122
- int kvm_fd;
123186
124
- /* Allocate memory. */
187
+ pr_debug("%s: mode='%s' pages='%ld' perm='%d'\n", __func__,
188
+ vm_guest_mode_string(mode), phy_pages, perm);
189
+
125190 vm = calloc(1, sizeof(*vm));
126
- TEST_ASSERT(vm != NULL, "Insufficent Memory");
191
+ TEST_ASSERT(vm != NULL, "Insufficient Memory");
192
+
193
+ INIT_LIST_HEAD(&vm->vcpus);
194
+ INIT_LIST_HEAD(&vm->userspace_mem_regions);
127195
128196 vm->mode = mode;
129
- vm_open(vm, perm);
197
+ vm->type = 0;
198
+
199
+ vm->pa_bits = vm_guest_mode_params[mode].pa_bits;
200
+ vm->va_bits = vm_guest_mode_params[mode].va_bits;
201
+ vm->page_size = vm_guest_mode_params[mode].page_size;
202
+ vm->page_shift = vm_guest_mode_params[mode].page_shift;
130203
131204 /* Setup mode specific traits. */
132205 switch (vm->mode) {
133
- case VM_MODE_FLAT48PG:
134
- vm->page_size = 0x1000;
135
- vm->page_shift = 12;
136
-
137
- /* Limit to 48-bit canonical virtual addresses. */
138
- vm->vpages_valid = sparsebit_alloc();
139
- sparsebit_set_num(vm->vpages_valid,
140
- 0, (1ULL << (48 - 1)) >> vm->page_shift);
141
- sparsebit_set_num(vm->vpages_valid,
142
- (~((1ULL << (48 - 1)) - 1)) >> vm->page_shift,
143
- (1ULL << (48 - 1)) >> vm->page_shift);
144
-
145
- /* Limit physical addresses to 52-bits. */
146
- vm->max_gfn = ((1ULL << 52) >> vm->page_shift) - 1;
206
+ case VM_MODE_P52V48_4K:
207
+ vm->pgtable_levels = 4;
147208 break;
148
-
209
+ case VM_MODE_P52V48_64K:
210
+ vm->pgtable_levels = 3;
211
+ break;
212
+ case VM_MODE_P48V48_4K:
213
+ vm->pgtable_levels = 4;
214
+ break;
215
+ case VM_MODE_P48V48_64K:
216
+ vm->pgtable_levels = 3;
217
+ break;
218
+ case VM_MODE_P40V48_4K:
219
+ vm->pgtable_levels = 4;
220
+ break;
221
+ case VM_MODE_P40V48_64K:
222
+ vm->pgtable_levels = 3;
223
+ break;
224
+ case VM_MODE_PXXV48_4K:
225
+#ifdef __x86_64__
226
+ kvm_get_cpu_address_width(&vm->pa_bits, &vm->va_bits);
227
+ /*
228
+ * Ignore KVM support for 5-level paging (vm->va_bits == 57),
229
+ * it doesn't take effect unless a CR4.LA57 is set, which it
230
+ * isn't for this VM_MODE.
231
+ */
232
+ TEST_ASSERT(vm->va_bits == 48 || vm->va_bits == 57,
233
+ "Linear address width (%d bits) not supported",
234
+ vm->va_bits);
235
+ pr_debug("Guest physical address width detected: %d\n",
236
+ vm->pa_bits);
237
+ vm->pgtable_levels = 4;
238
+ vm->va_bits = 48;
239
+#else
240
+ TEST_FAIL("VM_MODE_PXXV48_4K not supported on non-x86 platforms");
241
+#endif
242
+ break;
149243 default:
150
- TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
244
+ TEST_FAIL("Unknown guest mode, mode: 0x%x", mode);
151245 }
246
+
247
+#ifdef __aarch64__
248
+ if (vm->pa_bits != 40)
249
+ vm->type = KVM_VM_TYPE_ARM_IPA_SIZE(vm->pa_bits);
250
+#endif
251
+
252
+ vm_open(vm, perm);
253
+
254
+ /* Limit to VA-bit canonical virtual addresses. */
255
+ vm->vpages_valid = sparsebit_alloc();
256
+ sparsebit_set_num(vm->vpages_valid,
257
+ 0, (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
258
+ sparsebit_set_num(vm->vpages_valid,
259
+ (~((1ULL << (vm->va_bits - 1)) - 1)) >> vm->page_shift,
260
+ (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
261
+
262
+ /* Limit physical addresses to PA-bits. */
263
+ vm->max_gfn = ((1ULL << vm->pa_bits) >> vm->page_shift) - 1;
152264
153265 /* Allocate and setup memory for guest. */
154266 vm->vpages_mapped = sparsebit_alloc();
....@@ -159,7 +271,8 @@
159271 return vm;
160272 }
161273
162
-/* VM Restart
274
+/*
275
+ * VM Restart
163276 *
164277 * Input Args:
165278 * vm - VM that has been released before
....@@ -179,14 +292,14 @@
179292 if (vmp->has_irqchip)
180293 vm_create_irqchip(vmp);
181294
182
- for (region = vmp->userspace_mem_region_head; region;
183
- region = region->next) {
295
+ list_for_each_entry(region, &vmp->userspace_mem_regions, list) {
184296 int ret = ioctl(vmp->fd, KVM_SET_USER_MEMORY_REGION, &region->region);
185297 TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION IOCTL failed,\n"
186298 " rc: %i errno: %i\n"
187299 " slot: %u flags: 0x%x\n"
188
- " guest_phys_addr: 0x%lx size: 0x%lx",
189
- ret, errno, region->region.slot, region->region.flags,
300
+ " guest_phys_addr: 0x%llx size: 0x%llx",
301
+ ret, errno, region->region.slot,
302
+ region->region.flags,
190303 region->region.guest_phys_addr,
191304 region->region.memory_size);
192305 }
....@@ -199,10 +312,24 @@
199312
200313 ret = ioctl(vm->fd, KVM_GET_DIRTY_LOG, &args);
201314 TEST_ASSERT(ret == 0, "%s: KVM_GET_DIRTY_LOG failed: %s",
202
- strerror(-ret));
315
+ __func__, strerror(-ret));
203316 }
204317
205
-/* Userspace Memory Region Find
318
+void kvm_vm_clear_dirty_log(struct kvm_vm *vm, int slot, void *log,
319
+ uint64_t first_page, uint32_t num_pages)
320
+{
321
+ struct kvm_clear_dirty_log args = { .dirty_bitmap = log, .slot = slot,
322
+ .first_page = first_page,
323
+ .num_pages = num_pages };
324
+ int ret;
325
+
326
+ ret = ioctl(vm->fd, KVM_CLEAR_DIRTY_LOG, &args);
327
+ TEST_ASSERT(ret == 0, "%s: KVM_CLEAR_DIRTY_LOG failed: %s",
328
+ __func__, strerror(-ret));
329
+}
330
+
331
+/*
332
+ * Userspace Memory Region Find
206333 *
207334 * Input Args:
208335 * vm - Virtual Machine
....@@ -220,13 +347,12 @@
220347 * of the regions is returned. Null is returned only when no overlapping
221348 * region exists.
222349 */
223
-static struct userspace_mem_region *userspace_mem_region_find(
224
- struct kvm_vm *vm, uint64_t start, uint64_t end)
350
+static struct userspace_mem_region *
351
+userspace_mem_region_find(struct kvm_vm *vm, uint64_t start, uint64_t end)
225352 {
226353 struct userspace_mem_region *region;
227354
228
- for (region = vm->userspace_mem_region_head; region;
229
- region = region->next) {
355
+ list_for_each_entry(region, &vm->userspace_mem_regions, list) {
230356 uint64_t existing_start = region->region.guest_phys_addr;
231357 uint64_t existing_end = region->region.guest_phys_addr
232358 + region->region.memory_size - 1;
....@@ -237,7 +363,8 @@
237363 return NULL;
238364 }
239365
240
-/* KVM Userspace Memory Region Find
366
+/*
367
+ * KVM Userspace Memory Region Find
241368 *
242369 * Input Args:
243370 * vm - Virtual Machine
....@@ -265,7 +392,8 @@
265392 return &region->region;
266393 }
267394
268
-/* VCPU Find
395
+/*
396
+ * VCPU Find
269397 *
270398 * Input Args:
271399 * vm - Virtual Machine
....@@ -280,34 +408,32 @@
280408 * returns a pointer to it. Returns NULL if the VM doesn't contain a VCPU
281409 * for the specified vcpuid.
282410 */
283
-struct vcpu *vcpu_find(struct kvm_vm *vm,
284
- uint32_t vcpuid)
411
+struct vcpu *vcpu_find(struct kvm_vm *vm, uint32_t vcpuid)
285412 {
286
- struct vcpu *vcpup;
413
+ struct vcpu *vcpu;
287414
288
- for (vcpup = vm->vcpu_head; vcpup; vcpup = vcpup->next) {
289
- if (vcpup->id == vcpuid)
290
- return vcpup;
415
+ list_for_each_entry(vcpu, &vm->vcpus, list) {
416
+ if (vcpu->id == vcpuid)
417
+ return vcpu;
291418 }
292419
293420 return NULL;
294421 }
295422
296
-/* VM VCPU Remove
423
+/*
424
+ * VM VCPU Remove
297425 *
298426 * Input Args:
299
- * vm - Virtual Machine
300
- * vcpuid - VCPU ID
427
+ * vcpu - VCPU to remove
301428 *
302429 * Output Args: None
303430 *
304431 * Return: None, TEST_ASSERT failures for all error conditions
305432 *
306
- * Within the VM specified by vm, removes the VCPU given by vcpuid.
433
+ * Removes a vCPU from a VM and frees its resources.
307434 */
308
-static void vm_vcpu_rm(struct kvm_vm *vm, uint32_t vcpuid)
435
+static void vm_vcpu_rm(struct vcpu *vcpu)
309436 {
310
- struct vcpu *vcpu = vcpu_find(vm, vcpuid);
311437 int ret;
312438
313439 ret = munmap(vcpu->state, sizeof(*vcpu->state));
....@@ -317,24 +443,18 @@
317443 TEST_ASSERT(ret == 0, "Close of VCPU fd failed, rc: %i "
318444 "errno: %i", ret, errno);
319445
320
- if (vcpu->next)
321
- vcpu->next->prev = vcpu->prev;
322
- if (vcpu->prev)
323
- vcpu->prev->next = vcpu->next;
324
- else
325
- vm->vcpu_head = vcpu->next;
446
+ list_del(&vcpu->list);
326447 free(vcpu);
327448 }
328449
329450 void kvm_vm_release(struct kvm_vm *vmp)
330451 {
452
+ struct vcpu *vcpu, *tmp;
331453 int ret;
332454
333
- /* Free VCPUs. */
334
- while (vmp->vcpu_head)
335
- vm_vcpu_rm(vmp, vmp->vcpu_head->id);
455
+ list_for_each_entry_safe(vcpu, tmp, &vmp->vcpus, list)
456
+ vm_vcpu_rm(vcpu);
336457
337
- /* Close file descriptor for the VM. */
338458 ret = close(vmp->fd);
339459 TEST_ASSERT(ret == 0, "Close of vm fd failed,\n"
340460 " vmp->fd: %i rc: %i errno: %i", vmp->fd, ret, errno);
....@@ -344,34 +464,38 @@
344464 " vmp->kvm_fd: %i rc: %i errno: %i", vmp->kvm_fd, ret, errno);
345465 }
346466
347
-/* Destroys and frees the VM pointed to by vmp.
467
+static void __vm_mem_region_delete(struct kvm_vm *vm,
468
+ struct userspace_mem_region *region)
469
+{
470
+ int ret;
471
+
472
+ list_del(&region->list);
473
+
474
+ region->region.memory_size = 0;
475
+ ret = ioctl(vm->fd, KVM_SET_USER_MEMORY_REGION, &region->region);
476
+ TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION IOCTL failed, "
477
+ "rc: %i errno: %i", ret, errno);
478
+
479
+ sparsebit_free(&region->unused_phy_pages);
480
+ ret = munmap(region->mmap_start, region->mmap_size);
481
+ TEST_ASSERT(ret == 0, "munmap failed, rc: %i errno: %i", ret, errno);
482
+
483
+ free(region);
484
+}
485
+
486
+/*
487
+ * Destroys and frees the VM pointed to by vmp.
348488 */
349489 void kvm_vm_free(struct kvm_vm *vmp)
350490 {
351
- int ret;
491
+ struct userspace_mem_region *region, *tmp;
352492
353493 if (vmp == NULL)
354494 return;
355495
356496 /* Free userspace_mem_regions. */
357
- while (vmp->userspace_mem_region_head) {
358
- struct userspace_mem_region *region
359
- = vmp->userspace_mem_region_head;
360
-
361
- region->region.memory_size = 0;
362
- ret = ioctl(vmp->fd, KVM_SET_USER_MEMORY_REGION,
363
- &region->region);
364
- TEST_ASSERT(ret == 0, "KVM_SET_USER_MEMORY_REGION IOCTL failed, "
365
- "rc: %i errno: %i", ret, errno);
366
-
367
- vmp->userspace_mem_region_head = region->next;
368
- sparsebit_free(&region->unused_phy_pages);
369
- ret = munmap(region->mmap_start, region->mmap_size);
370
- TEST_ASSERT(ret == 0, "munmap failed, rc: %i errno: %i",
371
- ret, errno);
372
-
373
- free(region);
374
- }
497
+ list_for_each_entry_safe(region, tmp, &vmp->userspace_mem_regions, list)
498
+ __vm_mem_region_delete(vmp, region);
375499
376500 /* Free sparsebit arrays. */
377501 sparsebit_free(&vmp->vpages_valid);
....@@ -383,7 +507,8 @@
383507 free(vmp);
384508 }
385509
386
-/* Memory Compare, host virtual to guest virtual
510
+/*
511
+ * Memory Compare, host virtual to guest virtual
387512 *
388513 * Input Args:
389514 * hva - Starting host virtual address
....@@ -405,23 +530,25 @@
405530 * a length of len, to the guest bytes starting at the guest virtual
406531 * address given by gva.
407532 */
408
-int kvm_memcmp_hva_gva(void *hva,
409
- struct kvm_vm *vm, vm_vaddr_t gva, size_t len)
533
+int kvm_memcmp_hva_gva(void *hva, struct kvm_vm *vm, vm_vaddr_t gva, size_t len)
410534 {
411535 size_t amt;
412536
413
- /* Compare a batch of bytes until either a match is found
537
+ /*
538
+ * Compare a batch of bytes until either a match is found
414539 * or all the bytes have been compared.
415540 */
416541 for (uintptr_t offset = 0; offset < len; offset += amt) {
417542 uintptr_t ptr1 = (uintptr_t)hva + offset;
418543
419
- /* Determine host address for guest virtual address
544
+ /*
545
+ * Determine host address for guest virtual address
420546 * at offset.
421547 */
422548 uintptr_t ptr2 = (uintptr_t)addr_gva2hva(vm, gva + offset);
423549
424
- /* Determine amount to compare on this pass.
550
+ /*
551
+ * Determine amount to compare on this pass.
425552 * Don't allow the comparsion to cross a page boundary.
426553 */
427554 amt = len - offset;
....@@ -433,7 +560,8 @@
433560 assert((ptr1 >> vm->page_shift) == ((ptr1 + amt - 1) >> vm->page_shift));
434561 assert((ptr2 >> vm->page_shift) == ((ptr2 + amt - 1) >> vm->page_shift));
435562
436
- /* Perform the comparison. If there is a difference
563
+ /*
564
+ * Perform the comparison. If there is a difference
437565 * return that result to the caller, otherwise need
438566 * to continue on looking for a mismatch.
439567 */
....@@ -442,109 +570,15 @@
442570 return ret;
443571 }
444572
445
- /* No mismatch found. Let the caller know the two memory
573
+ /*
574
+ * No mismatch found. Let the caller know the two memory
446575 * areas are equal.
447576 */
448577 return 0;
449578 }
450579
451
-/* Allocate an instance of struct kvm_cpuid2
452
- *
453
- * Input Args: None
454
- *
455
- * Output Args: None
456
- *
457
- * Return: A pointer to the allocated struct. The caller is responsible
458
- * for freeing this struct.
459
- *
460
- * Since kvm_cpuid2 uses a 0-length array to allow a the size of the
461
- * array to be decided at allocation time, allocation is slightly
462
- * complicated. This function uses a reasonable default length for
463
- * the array and performs the appropriate allocation.
464
- */
465
-static struct kvm_cpuid2 *allocate_kvm_cpuid2(void)
466
-{
467
- struct kvm_cpuid2 *cpuid;
468
- int nent = 100;
469
- size_t size;
470
-
471
- size = sizeof(*cpuid);
472
- size += nent * sizeof(struct kvm_cpuid_entry2);
473
- cpuid = malloc(size);
474
- if (!cpuid) {
475
- perror("malloc");
476
- abort();
477
- }
478
-
479
- cpuid->nent = nent;
480
-
481
- return cpuid;
482
-}
483
-
484
-/* KVM Supported CPUID Get
485
- *
486
- * Input Args: None
487
- *
488
- * Output Args:
489
- *
490
- * Return: The supported KVM CPUID
491
- *
492
- * Get the guest CPUID supported by KVM.
493
- */
494
-struct kvm_cpuid2 *kvm_get_supported_cpuid(void)
495
-{
496
- static struct kvm_cpuid2 *cpuid;
497
- int ret;
498
- int kvm_fd;
499
-
500
- if (cpuid)
501
- return cpuid;
502
-
503
- cpuid = allocate_kvm_cpuid2();
504
- kvm_fd = open(KVM_DEV_PATH, O_RDONLY);
505
- if (kvm_fd < 0)
506
- exit(KSFT_SKIP);
507
-
508
- ret = ioctl(kvm_fd, KVM_GET_SUPPORTED_CPUID, cpuid);
509
- TEST_ASSERT(ret == 0, "KVM_GET_SUPPORTED_CPUID failed %d %d\n",
510
- ret, errno);
511
-
512
- close(kvm_fd);
513
- return cpuid;
514
-}
515
-
516
-/* Locate a cpuid entry.
517
- *
518
- * Input Args:
519
- * cpuid: The cpuid.
520
- * function: The function of the cpuid entry to find.
521
- *
522
- * Output Args: None
523
- *
524
- * Return: A pointer to the cpuid entry. Never returns NULL.
525
- */
526
-struct kvm_cpuid_entry2 *
527
-kvm_get_supported_cpuid_index(uint32_t function, uint32_t index)
528
-{
529
- struct kvm_cpuid2 *cpuid;
530
- struct kvm_cpuid_entry2 *entry = NULL;
531
- int i;
532
-
533
- cpuid = kvm_get_supported_cpuid();
534
- for (i = 0; i < cpuid->nent; i++) {
535
- if (cpuid->entries[i].function == function &&
536
- cpuid->entries[i].index == index) {
537
- entry = &cpuid->entries[i];
538
- break;
539
- }
540
- }
541
-
542
- TEST_ASSERT(entry, "Guest CPUID entry not found: (EAX=%x, ECX=%x).",
543
- function, index);
544
- return entry;
545
-}
546
-
547
-/* VM Userspace Memory Region Add
580
+/*
581
+ * VM Userspace Memory Region Add
548582 *
549583 * Input Args:
550584 * vm - Virtual Machine
....@@ -571,9 +605,13 @@
571605 uint32_t flags)
572606 {
573607 int ret;
574
- unsigned long pmem_size = 0;
575608 struct userspace_mem_region *region;
576609 size_t huge_page_size = KVM_UTIL_PGS_PER_HUGEPG * vm->page_size;
610
+ size_t alignment;
611
+
612
+ TEST_ASSERT(vm_adjust_num_guest_pages(vm->mode, npages) == npages,
613
+ "Number of guest pages is not compatible with the host. "
614
+ "Try npages=%d", vm_adjust_num_guest_pages(vm->mode, npages));
577615
578616 TEST_ASSERT((guest_paddr % vm->page_size) == 0, "Guest physical "
579617 "address not on a page boundary.\n"
....@@ -586,13 +624,14 @@
586624 " vm->max_gfn: 0x%lx vm->page_size: 0x%x",
587625 guest_paddr, npages, vm->max_gfn, vm->page_size);
588626
589
- /* Confirm a mem region with an overlapping address doesn't
627
+ /*
628
+ * Confirm a mem region with an overlapping address doesn't
590629 * already exist.
591630 */
592631 region = (struct userspace_mem_region *) userspace_mem_region_find(
593632 vm, guest_paddr, (guest_paddr + npages * vm->page_size) - 1);
594633 if (region != NULL)
595
- TEST_ASSERT(false, "overlapping userspace_mem_region already "
634
+ TEST_FAIL("overlapping userspace_mem_region already "
596635 "exists\n"
597636 " requested guest_paddr: 0x%lx npages: 0x%lx "
598637 "page_size: 0x%x\n"
....@@ -602,13 +641,11 @@
602641 (uint64_t) region->region.memory_size);
603642
604643 /* Confirm no region with the requested slot already exists. */
605
- for (region = vm->userspace_mem_region_head; region;
606
- region = region->next) {
607
- if (region->region.slot == slot)
608
- break;
609
- }
610
- if (region != NULL)
611
- TEST_ASSERT(false, "A mem region with the requested slot "
644
+ list_for_each_entry(region, &vm->userspace_mem_regions, list) {
645
+ if (region->region.slot != slot)
646
+ continue;
647
+
648
+ TEST_FAIL("A mem region with the requested slot "
612649 "already exists.\n"
613650 " requested slot: %u paddr: 0x%lx npages: 0x%lx\n"
614651 " existing slot: %u paddr: 0x%lx size: 0x%lx",
....@@ -616,15 +653,27 @@
616653 region->region.slot,
617654 (uint64_t) region->region.guest_phys_addr,
618655 (uint64_t) region->region.memory_size);
656
+ }
619657
620658 /* Allocate and initialize new mem region structure. */
621659 region = calloc(1, sizeof(*region));
622660 TEST_ASSERT(region != NULL, "Insufficient Memory");
623661 region->mmap_size = npages * vm->page_size;
624662
625
- /* Enough memory to align up to a huge page. */
663
+#ifdef __s390x__
664
+ /* On s390x, the host address must be aligned to 1M (due to PGSTEs) */
665
+ alignment = 0x100000;
666
+#else
667
+ alignment = 1;
668
+#endif
669
+
626670 if (src_type == VM_MEM_SRC_ANONYMOUS_THP)
627
- region->mmap_size += huge_page_size;
671
+ alignment = max(huge_page_size, alignment);
672
+
673
+ /* Add enough memory to align up if necessary */
674
+ if (alignment > 1)
675
+ region->mmap_size += alignment;
676
+
628677 region->mmap_start = mmap(NULL, region->mmap_size,
629678 PROT_READ | PROT_WRITE,
630679 MAP_PRIVATE | MAP_ANONYMOUS
....@@ -634,19 +683,26 @@
634683 "test_malloc failed, mmap_start: %p errno: %i",
635684 region->mmap_start, errno);
636685
637
- /* Align THP allocation up to start of a huge page. */
638
- region->host_mem = align(region->mmap_start,
639
- src_type == VM_MEM_SRC_ANONYMOUS_THP ? huge_page_size : 1);
686
+ /* Align host address */
687
+ region->host_mem = align(region->mmap_start, alignment);
640688
641689 /* As needed perform madvise */
642690 if (src_type == VM_MEM_SRC_ANONYMOUS || src_type == VM_MEM_SRC_ANONYMOUS_THP) {
643
- ret = madvise(region->host_mem, npages * vm->page_size,
644
- src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
645
- TEST_ASSERT(ret == 0, "madvise failed,\n"
646
- " addr: %p\n"
647
- " length: 0x%lx\n"
648
- " src_type: %x",
649
- region->host_mem, npages * vm->page_size, src_type);
691
+ struct stat statbuf;
692
+
693
+ ret = stat("/sys/kernel/mm/transparent_hugepage", &statbuf);
694
+ TEST_ASSERT(ret == 0 || (ret == -1 && errno == ENOENT),
695
+ "stat /sys/kernel/mm/transparent_hugepage");
696
+
697
+ TEST_ASSERT(ret == 0 || src_type != VM_MEM_SRC_ANONYMOUS_THP,
698
+ "VM_MEM_SRC_ANONYMOUS_THP requires THP to be configured in the host kernel");
699
+
700
+ if (ret == 0) {
701
+ ret = madvise(region->host_mem, npages * vm->page_size,
702
+ src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
703
+ TEST_ASSERT(ret == 0, "madvise failed, addr: %p length: 0x%lx src_type: %x",
704
+ region->host_mem, npages * vm->page_size, src_type);
705
+ }
650706 }
651707
652708 region->unused_phy_pages = sparsebit_alloc();
....@@ -666,13 +722,11 @@
666722 guest_paddr, (uint64_t) region->region.memory_size);
667723
668724 /* Add to linked-list of memory regions. */
669
- if (vm->userspace_mem_region_head)
670
- vm->userspace_mem_region_head->prev = region;
671
- region->next = vm->userspace_mem_region_head;
672
- vm->userspace_mem_region_head = region;
725
+ list_add(&region->list, &vm->userspace_mem_regions);
673726 }
674727
675
-/* Memslot to region
728
+/*
729
+ * Memslot to region
676730 *
677731 * Input Args:
678732 * vm - Virtual Machine
....@@ -686,28 +740,26 @@
686740 * on error (e.g. currently no memory region using memslot as a KVM
687741 * memory slot ID).
688742 */
689
-static struct userspace_mem_region *memslot2region(struct kvm_vm *vm,
690
- uint32_t memslot)
743
+struct userspace_mem_region *
744
+memslot2region(struct kvm_vm *vm, uint32_t memslot)
691745 {
692746 struct userspace_mem_region *region;
693747
694
- for (region = vm->userspace_mem_region_head; region;
695
- region = region->next) {
748
+ list_for_each_entry(region, &vm->userspace_mem_regions, list) {
696749 if (region->region.slot == memslot)
697
- break;
698
- }
699
- if (region == NULL) {
700
- fprintf(stderr, "No mem region with the requested slot found,\n"
701
- " requested slot: %u\n", memslot);
702
- fputs("---- vm dump ----\n", stderr);
703
- vm_dump(stderr, vm, 2);
704
- TEST_ASSERT(false, "Mem region not found");
750
+ return region;
705751 }
706752
707
- return region;
753
+ fprintf(stderr, "No mem region with the requested slot found,\n"
754
+ " requested slot: %u\n", memslot);
755
+ fputs("---- vm dump ----\n", stderr);
756
+ vm_dump(stderr, vm, 2);
757
+ TEST_FAIL("Mem region not found");
758
+ return NULL;
708759 }
709760
710
-/* VM Memory Region Flags Set
761
+/*
762
+ * VM Memory Region Flags Set
711763 *
712764 * Input Args:
713765 * vm - Virtual Machine
....@@ -725,7 +777,6 @@
725777 int ret;
726778 struct userspace_mem_region *region;
727779
728
- /* Locate memory region. */
729780 region = memslot2region(vm, slot);
730781
731782 region->region.flags = flags;
....@@ -737,7 +788,56 @@
737788 ret, errno, slot, flags);
738789 }
739790
740
-/* VCPU mmap Size
791
+/*
792
+ * VM Memory Region Move
793
+ *
794
+ * Input Args:
795
+ * vm - Virtual Machine
796
+ * slot - Slot of the memory region to move
797
+ * new_gpa - Starting guest physical address
798
+ *
799
+ * Output Args: None
800
+ *
801
+ * Return: None
802
+ *
803
+ * Change the gpa of a memory region.
804
+ */
805
+void vm_mem_region_move(struct kvm_vm *vm, uint32_t slot, uint64_t new_gpa)
806
+{
807
+ struct userspace_mem_region *region;
808
+ int ret;
809
+
810
+ region = memslot2region(vm, slot);
811
+
812
+ region->region.guest_phys_addr = new_gpa;
813
+
814
+ ret = ioctl(vm->fd, KVM_SET_USER_MEMORY_REGION, &region->region);
815
+
816
+ TEST_ASSERT(!ret, "KVM_SET_USER_MEMORY_REGION failed\n"
817
+ "ret: %i errno: %i slot: %u new_gpa: 0x%lx",
818
+ ret, errno, slot, new_gpa);
819
+}
820
+
821
+/*
822
+ * VM Memory Region Delete
823
+ *
824
+ * Input Args:
825
+ * vm - Virtual Machine
826
+ * slot - Slot of the memory region to delete
827
+ *
828
+ * Output Args: None
829
+ *
830
+ * Return: None
831
+ *
832
+ * Delete a memory region.
833
+ */
834
+void vm_mem_region_delete(struct kvm_vm *vm, uint32_t slot)
835
+{
836
+ __vm_mem_region_delete(vm, memslot2region(vm, slot));
837
+}
838
+
839
+/*
840
+ * VCPU mmap Size
741841 *
742842 * Input Args: None
743843 *
....@@ -767,7 +867,8 @@
767867 return ret;
768868 }
769869
770
-/* VM VCPU Add
870
+/*
871
+ * VM VCPU Add
771872 *
772873 * Input Args:
773874 * vm - Virtual Machine
....@@ -777,17 +878,17 @@
777878 *
778879 * Return: None
779880 *
780
- * Creates and adds to the VM specified by vm and virtual CPU with
781
- * the ID given by vcpuid.
881
+ * Adds a virtual CPU to the VM specified by vm with the ID given by vcpuid.
882
+ * No additional VCPU setup is done.
782883 */
783
-void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid, int pgd_memslot, int gdt_memslot)
884
+void vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpuid)
784885 {
785886 struct vcpu *vcpu;
786887
787888 /* Confirm a vcpu with the specified id doesn't already exist. */
788889 vcpu = vcpu_find(vm, vcpuid);
789890 if (vcpu != NULL)
790
- TEST_ASSERT(false, "vcpu with the specified id "
891
+ TEST_FAIL("vcpu with the specified id "
791892 "already exists,\n"
792893 " requested vcpuid: %u\n"
793894 " existing vcpuid: %u state: %p",
....@@ -810,15 +911,11 @@
810911 "vcpu id: %u errno: %i", vcpuid, errno);
811912
812913 /* Add to linked-list of VCPUs. */
813
- if (vm->vcpu_head)
814
- vm->vcpu_head->prev = vcpu;
815
- vcpu->next = vm->vcpu_head;
816
- vm->vcpu_head = vcpu;
817
-
818
- vcpu_setup(vm, vcpuid, pgd_memslot, gdt_memslot);
914
+ list_add(&vcpu->list, &vm->vcpus);
819915 }
820916
821
-/* VM Virtual Address Unused Gap
917
+/*
918
+ * VM Virtual Address Unused Gap
822919 *
823920 * Input Args:
824921 * vm - Virtual Machine
....@@ -838,14 +935,14 @@
838935 * sz unallocated bytes >= vaddr_min is available.
839936 */
840937 static vm_vaddr_t vm_vaddr_unused_gap(struct kvm_vm *vm, size_t sz,
841
- vm_vaddr_t vaddr_min)
938
+ vm_vaddr_t vaddr_min)
842939 {
843940 uint64_t pages = (sz + vm->page_size - 1) >> vm->page_shift;
844941
845942 /* Determine lowest permitted virtual page index. */
846943 uint64_t pgidx_start = (vaddr_min + vm->page_size - 1) >> vm->page_shift;
847944 if ((pgidx_start * vm->page_size) < vaddr_min)
848
- goto no_va_found;
945
+ goto no_va_found;
849946
850947 /* Loop over section with enough valid virtual page indexes. */
851948 if (!sparsebit_is_set_num(vm->vpages_valid,
....@@ -881,8 +978,7 @@
881978 } while (pgidx_start != 0);
882979
883980 no_va_found:
884
- TEST_ASSERT(false, "No vaddr of specified pages available, "
885
- "pages: 0x%lx", pages);
981
+ TEST_FAIL("No vaddr of specified pages available, pages: 0x%lx", pages);
886982
887983 /* NOT REACHED */
888984 return -1;
....@@ -904,7 +1000,8 @@
9041000 return pgidx_start * vm->page_size;
9051001 }
9061002
907
-/* VM Virtual Address Allocate
1003
+/*
1004
+ * VM Virtual Address Allocate
9081005 *
9091006 * Input Args:
9101007 * vm - Virtual Machine
....@@ -925,13 +1022,14 @@
9251022 * a page.
9261023 */
9271024 vm_vaddr_t vm_vaddr_alloc(struct kvm_vm *vm, size_t sz, vm_vaddr_t vaddr_min,
928
- uint32_t data_memslot, uint32_t pgd_memslot)
1025
+ uint32_t data_memslot, uint32_t pgd_memslot)
9291026 {
9301027 uint64_t pages = (sz >> vm->page_shift) + ((sz % vm->page_size) != 0);
9311028
9321029 virt_pgd_alloc(vm, pgd_memslot);
9331030
934
- /* Find an unused range of virtual page addresses of at least
1031
+ /*
1032
+ * Find an unused range of virtual page addresses of at least
9351033 * pages in length.
9361034 */
9371035 vm_vaddr_t vaddr_start = vm_vaddr_unused_gap(vm, sz, vaddr_min);
....@@ -941,7 +1039,8 @@
9411039 pages--, vaddr += vm->page_size) {
9421040 vm_paddr_t paddr;
9431041
944
- paddr = vm_phy_page_alloc(vm, KVM_UTIL_MIN_PADDR, data_memslot);
1042
+ paddr = vm_phy_page_alloc(vm,
1043
+ KVM_UTIL_MIN_PFN * vm->page_size, data_memslot);
9451044
9461045 virt_pg_map(vm, vaddr, paddr, pgd_memslot);
9471046
....@@ -959,21 +1058,21 @@
9591058 * vm - Virtual Machine
9601059 * vaddr - Virtuall address to map
9611060 * paddr - VM Physical Address
962
- * size - The size of the range to map
1061
+ * npages - The number of pages to map
9631062 * pgd_memslot - Memory region slot for new virtual translation tables
9641063 *
9651064 * Output Args: None
9661065 *
9671066 * Return: None
9681067 *
969
- * Within the VM given by vm, creates a virtual translation for the
970
- * page range starting at vaddr to the page range starting at paddr.
1068
+ * Within the VM given by @vm, creates a virtual translation for
1069
+ * @npages starting at @vaddr to the page range starting at @paddr.
9711070 */
9721071 void virt_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
973
- size_t size, uint32_t pgd_memslot)
1072
+ unsigned int npages, uint32_t pgd_memslot)
9741073 {
9751074 size_t page_size = vm->page_size;
976
- size_t npages = size / page_size;
1075
+ size_t size = npages * page_size;
9771076
9781077 TEST_ASSERT(vaddr + size > vaddr, "Vaddr overflow");
9791078 TEST_ASSERT(paddr + size > paddr, "Paddr overflow");
....@@ -985,7 +1084,8 @@
9851084 }
9861085 }
9871086
988
-/* Address VM Physical to Host Virtual
1087
+/*
1088
+ * Address VM Physical to Host Virtual
9891089 *
9901090 * Input Args:
9911091 * vm - Virtual Machine
....@@ -1004,8 +1104,8 @@
10041104 void *addr_gpa2hva(struct kvm_vm *vm, vm_paddr_t gpa)
10051105 {
10061106 struct userspace_mem_region *region;
1007
- for (region = vm->userspace_mem_region_head; region;
1008
- region = region->next) {
1107
+
1108
+ list_for_each_entry(region, &vm->userspace_mem_regions, list) {
10091109 if ((gpa >= region->region.guest_phys_addr)
10101110 && (gpa <= (region->region.guest_phys_addr
10111111 + region->region.memory_size - 1)))
....@@ -1013,11 +1113,12 @@
10131113 + (gpa - region->region.guest_phys_addr));
10141114 }
10151115
1016
- TEST_ASSERT(false, "No vm physical memory at 0x%lx", gpa);
1116
+ TEST_FAIL("No vm physical memory at 0x%lx", gpa);
10171117 return NULL;
10181118 }
10191119
1020
-/* Address Host Virtual to VM Physical
1120
+/*
1121
+ * Address Host Virtual to VM Physical
10211122 *
10221123 * Input Args:
10231124 * vm - Virtual Machine
....@@ -1036,8 +1137,8 @@
10361137 vm_paddr_t addr_hva2gpa(struct kvm_vm *vm, void *hva)
10371138 {
10381139 struct userspace_mem_region *region;
1039
- for (region = vm->userspace_mem_region_head; region;
1040
- region = region->next) {
1140
+
1141
+ list_for_each_entry(region, &vm->userspace_mem_regions, list) {
10411142 if ((hva >= region->host_mem)
10421143 && (hva <= (region->host_mem
10431144 + region->region.memory_size - 1)))
....@@ -1046,12 +1147,12 @@
10461147 + (hva - (uintptr_t) region->host_mem));
10471148 }
10481149
1049
- TEST_ASSERT(false, "No mapping to a guest physical address, "
1050
- "hva: %p", hva);
1150
+ TEST_FAIL("No mapping to a guest physical address, hva: %p", hva);
10511151 return -1;
10521152 }
10531153
1054
-/* VM Create IRQ Chip
1154
+/*
1155
+ * VM Create IRQ Chip
10551156 *
10561157 * Input Args:
10571158 * vm - Virtual Machine
....@@ -1073,7 +1174,8 @@
10731174 vm->has_irqchip = true;
10741175 }
10751176
1076
-/* VM VCPU State
1177
+/*
1178
+ * VM VCPU State
10771179 *
10781180 * Input Args:
10791181 * vm - Virtual Machine
....@@ -1095,7 +1197,8 @@
10951197 return vcpu->state;
10961198 }
10971199
1098
-/* VM VCPU Run
1200
+/*
1201
+ * VM VCPU Run
10991202 *
11001203 * Input Args:
11011204 * vm - Virtual Machine
....@@ -1121,13 +1224,42 @@
11211224 int rc;
11221225
11231226 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1124
- do {
1227
+ do {
11251228 rc = ioctl(vcpu->fd, KVM_RUN, NULL);
11261229 } while (rc == -1 && errno == EINTR);
1230
+
1231
+ assert_on_unhandled_exception(vm, vcpuid);
1232
+
11271233 return rc;
11281234 }
11291235
1130
-/* VM VCPU Set MP State
1236
+void vcpu_run_complete_io(struct kvm_vm *vm, uint32_t vcpuid)
1237
+{
1238
+ struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1239
+ int ret;
1240
+
1241
+ TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1242
+
1243
+ vcpu->state->immediate_exit = 1;
1244
+ ret = ioctl(vcpu->fd, KVM_RUN, NULL);
1245
+ vcpu->state->immediate_exit = 0;
1246
+
1247
+ TEST_ASSERT(ret == -1 && errno == EINTR,
1248
+ "KVM_RUN IOCTL didn't exit immediately, rc: %i, errno: %i",
1249
+ ret, errno);
1250
+}
1251
+
1252
+void vcpu_set_guest_debug(struct kvm_vm *vm, uint32_t vcpuid,
1253
+ struct kvm_guest_debug *debug)
1254
+{
1255
+ struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1256
+ int ret = ioctl(vcpu->fd, KVM_SET_GUEST_DEBUG, debug);
1257
+
1258
+ TEST_ASSERT(ret == 0, "KVM_SET_GUEST_DEBUG failed: %d", ret);
1259
+}
1260
+
1261
+/*
1262
+ * VM VCPU Set MP State
11311263 *
11321264 * Input Args:
11331265 * vm - Virtual Machine
....@@ -1142,7 +1274,7 @@
11421274 * by mp_state.
11431275 */
11441276 void vcpu_set_mp_state(struct kvm_vm *vm, uint32_t vcpuid,
1145
- struct kvm_mp_state *mp_state)
1277
+ struct kvm_mp_state *mp_state)
11461278 {
11471279 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
11481280 int ret;
....@@ -1154,7 +1286,37 @@
11541286 "rc: %i errno: %i", ret, errno);
11551287 }
11561288
1157
-/* VM VCPU Regs Get
1289
+/*
1290
+ * VM VCPU Get Reg List
1291
+ *
1292
+ * Input Args:
1293
+ * vm - Virtual Machine
1294
+ * vcpuid - VCPU ID
1295
+ *
1296
+ * Output Args:
1297
+ * None
1298
+ *
1299
+ * Return:
1300
+ * A pointer to an allocated struct kvm_reg_list
1301
+ *
1302
+ * Get the list of guest registers which are supported for
1303
+ * KVM_GET_ONE_REG/KVM_SET_ONE_REG calls
1304
+ */
1305
+struct kvm_reg_list *vcpu_get_reg_list(struct kvm_vm *vm, uint32_t vcpuid)
1306
+{
1307
+ struct kvm_reg_list reg_list_n = { .n = 0 }, *reg_list;
1308
+ int ret;
1309
+
1310
+ ret = _vcpu_ioctl(vm, vcpuid, KVM_GET_REG_LIST, &reg_list_n);
1311
+ TEST_ASSERT(ret == -1 && errno == E2BIG, "KVM_GET_REG_LIST n=0");
1312
+ reg_list = calloc(1, sizeof(*reg_list) + reg_list_n.n * sizeof(__u64));
1313
+ reg_list->n = reg_list_n.n;
1314
+ vcpu_ioctl(vm, vcpuid, KVM_GET_REG_LIST, reg_list);
1315
+ return reg_list;
1316
+}
1317
+
1318
+/*
1319
+ * VM VCPU Regs Get
11581320 *
11591321 * Input Args:
11601322 * vm - Virtual Machine
....@@ -1168,21 +1330,20 @@
11681330 * Obtains the current register state for the VCPU specified by vcpuid
11691331 * and stores it at the location given by regs.
11701332 */
1171
-void vcpu_regs_get(struct kvm_vm *vm,
1172
- uint32_t vcpuid, struct kvm_regs *regs)
1333
+void vcpu_regs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs)
11731334 {
11741335 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
11751336 int ret;
11761337
11771338 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
11781339
1179
- /* Get the regs. */
11801340 ret = ioctl(vcpu->fd, KVM_GET_REGS, regs);
11811341 TEST_ASSERT(ret == 0, "KVM_GET_REGS failed, rc: %i errno: %i",
11821342 ret, errno);
11831343 }
11841344
1185
-/* VM VCPU Regs Set
1345
+/*
1346
+ * VM VCPU Regs Set
11861347 *
11871348 * Input Args:
11881349 * vm - Virtual Machine
....@@ -1196,165 +1357,82 @@
11961357 * Sets the regs of the VCPU specified by vcpuid to the values
11971358 * given by regs.
11981359 */
1199
-void vcpu_regs_set(struct kvm_vm *vm,
1200
- uint32_t vcpuid, struct kvm_regs *regs)
1360
+void vcpu_regs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_regs *regs)
12011361 {
12021362 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
12031363 int ret;
12041364
12051365 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
12061366
1207
- /* Set the regs. */
12081367 ret = ioctl(vcpu->fd, KVM_SET_REGS, regs);
12091368 TEST_ASSERT(ret == 0, "KVM_SET_REGS failed, rc: %i errno: %i",
12101369 ret, errno);
12111370 }
12121371
1372
+#ifdef __KVM_HAVE_VCPU_EVENTS
12131373 void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
1214
- struct kvm_vcpu_events *events)
1374
+ struct kvm_vcpu_events *events)
12151375 {
12161376 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
12171377 int ret;
12181378
12191379 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
12201380
1221
- /* Get the regs. */
12221381 ret = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, events);
12231382 TEST_ASSERT(ret == 0, "KVM_GET_VCPU_EVENTS, failed, rc: %i errno: %i",
12241383 ret, errno);
12251384 }
12261385
12271386 void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
1228
- struct kvm_vcpu_events *events)
1387
+ struct kvm_vcpu_events *events)
12291388 {
12301389 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
12311390 int ret;
12321391
12331392 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
12341393
1235
- /* Set the regs. */
12361394 ret = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, events);
12371395 TEST_ASSERT(ret == 0, "KVM_SET_VCPU_EVENTS, failed, rc: %i errno: %i",
12381396 ret, errno);
12391397 }
1398
+#endif
12401399
1241
-/* VCPU Get MSR
1242
- *
1243
- * Input Args:
1244
- * vm - Virtual Machine
1245
- * vcpuid - VCPU ID
1246
- * msr_index - Index of MSR
1247
- *
1248
- * Output Args: None
1249
- *
1250
- * Return: On success, value of the MSR. On failure a TEST_ASSERT is produced.
1251
- *
1252
- * Get value of MSR for VCPU.
1253
- */
1254
-uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
1400
+#ifdef __x86_64__
1401
+void vcpu_nested_state_get(struct kvm_vm *vm, uint32_t vcpuid,
1402
+ struct kvm_nested_state *state)
12551403 {
12561404 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1257
- struct {
1258
- struct kvm_msrs header;
1259
- struct kvm_msr_entry entry;
1260
- } buffer = {};
1261
- int r;
1405
+ int ret;
12621406
12631407 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1264
- buffer.header.nmsrs = 1;
1265
- buffer.entry.index = msr_index;
1266
- r = ioctl(vcpu->fd, KVM_GET_MSRS, &buffer.header);
1267
- TEST_ASSERT(r == 1, "KVM_GET_MSRS IOCTL failed,\n"
1268
- " rc: %i errno: %i", r, errno);
12691408
1270
- return buffer.entry.data;
1409
+ ret = ioctl(vcpu->fd, KVM_GET_NESTED_STATE, state);
1410
+ TEST_ASSERT(ret == 0,
1411
+ "KVM_SET_NESTED_STATE failed, ret: %i errno: %i",
1412
+ ret, errno);
12711413 }
12721414
1273
-/* VCPU Set MSR
1274
- *
1275
- * Input Args:
1276
- * vm - Virtual Machine
1277
- * vcpuid - VCPU ID
1278
- * msr_index - Index of MSR
1279
- * msr_value - New value of MSR
1280
- *
1281
- * Output Args: None
1282
- *
1283
- * Return: On success, nothing. On failure a TEST_ASSERT is produced.
1284
- *
1285
- * Set value of MSR for VCPU.
1286
- */
1287
-void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
1288
- uint64_t msr_value)
1415
+int vcpu_nested_state_set(struct kvm_vm *vm, uint32_t vcpuid,
1416
+ struct kvm_nested_state *state, bool ignore_error)
12891417 {
12901418 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1291
- struct {
1292
- struct kvm_msrs header;
1293
- struct kvm_msr_entry entry;
1294
- } buffer = {};
1295
- int r;
1419
+ int ret;
12961420
12971421 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1298
- memset(&buffer, 0, sizeof(buffer));
1299
- buffer.header.nmsrs = 1;
1300
- buffer.entry.index = msr_index;
1301
- buffer.entry.data = msr_value;
1302
- r = ioctl(vcpu->fd, KVM_SET_MSRS, &buffer.header);
1303
- TEST_ASSERT(r == 1, "KVM_SET_MSRS IOCTL failed,\n"
1304
- " rc: %i errno: %i", r, errno);
1422
+
1423
+ ret = ioctl(vcpu->fd, KVM_SET_NESTED_STATE, state);
1424
+ if (!ignore_error) {
1425
+ TEST_ASSERT(ret == 0,
1426
+ "KVM_SET_NESTED_STATE failed, ret: %i errno: %i",
1427
+ ret, errno);
1428
+ }
1429
+
1430
+ return ret;
13051431 }
1432
+#endif
13061433
1307
-/* VM VCPU Args Set
1308
- *
1309
- * Input Args:
1310
- * vm - Virtual Machine
1311
- * vcpuid - VCPU ID
1312
- * num - number of arguments
1313
- * ... - arguments, each of type uint64_t
1314
- *
1315
- * Output Args: None
1316
- *
1317
- * Return: None
1318
- *
1319
- * Sets the first num function input arguments to the values
1320
- * given as variable args. Each of the variable args is expected to
1321
- * be of type uint64_t.
1322
- */
1323
-void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
1324
-{
1325
- va_list ap;
1326
- struct kvm_regs regs;
1327
-
1328
- TEST_ASSERT(num >= 1 && num <= 6, "Unsupported number of args,\n"
1329
- " num: %u\n",
1330
- num);
1331
-
1332
- va_start(ap, num);
1333
- vcpu_regs_get(vm, vcpuid, &regs);
1334
-
1335
- if (num >= 1)
1336
- regs.rdi = va_arg(ap, uint64_t);
1337
-
1338
- if (num >= 2)
1339
- regs.rsi = va_arg(ap, uint64_t);
1340
-
1341
- if (num >= 3)
1342
- regs.rdx = va_arg(ap, uint64_t);
1343
-
1344
- if (num >= 4)
1345
- regs.rcx = va_arg(ap, uint64_t);
1346
-
1347
- if (num >= 5)
1348
- regs.r8 = va_arg(ap, uint64_t);
1349
-
1350
- if (num >= 6)
1351
- regs.r9 = va_arg(ap, uint64_t);
1352
-
1353
- vcpu_regs_set(vm, vcpuid, &regs);
1354
- va_end(ap);
1355
-}
1356
-
1357
-/* VM VCPU System Regs Get
1434
+/*
1435
+ * VM VCPU System Regs Get
13581436 *
13591437 * Input Args:
13601438 * vm - Virtual Machine
....@@ -1368,22 +1446,20 @@
13681446 * Obtains the current system register state for the VCPU specified by
13691447 * vcpuid and stores it at the location given by sregs.
13701448 */
1371
-void vcpu_sregs_get(struct kvm_vm *vm,
1372
- uint32_t vcpuid, struct kvm_sregs *sregs)
1449
+void vcpu_sregs_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
13731450 {
13741451 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
13751452 int ret;
13761453
13771454 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
13781455
1379
- /* Get the regs. */
1380
- /* Get the regs. */
13811456 ret = ioctl(vcpu->fd, KVM_GET_SREGS, sregs);
13821457 TEST_ASSERT(ret == 0, "KVM_GET_SREGS failed, rc: %i errno: %i",
13831458 ret, errno);
13841459 }
13851460
1386
-/* VM VCPU System Regs Set
1461
+/*
1462
+ * VM VCPU System Regs Set
13871463 *
13881464 * Input Args:
13891465 * vm - Virtual Machine
....@@ -1397,27 +1473,60 @@
13971473 * Sets the system regs of the VCPU specified by vcpuid to the values
13981474 * given by sregs.
13991475 */
1400
-void vcpu_sregs_set(struct kvm_vm *vm,
1401
- uint32_t vcpuid, struct kvm_sregs *sregs)
1476
+void vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
14021477 {
14031478 int ret = _vcpu_sregs_set(vm, vcpuid, sregs);
14041479 TEST_ASSERT(ret == 0, "KVM_RUN IOCTL failed, "
14051480 "rc: %i errno: %i", ret, errno);
14061481 }
14071482
1408
-int _vcpu_sregs_set(struct kvm_vm *vm,
1409
- uint32_t vcpuid, struct kvm_sregs *sregs)
1483
+int _vcpu_sregs_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_sregs *sregs)
14101484 {
14111485 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1412
- int ret;
14131486
14141487 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
14151488
1416
- /* Get the regs. */
14171489 return ioctl(vcpu->fd, KVM_SET_SREGS, sregs);
14181490 }
14191491
1420
-/* VCPU Ioctl
1492
+void vcpu_fpu_get(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_fpu *fpu)
1493
+{
1494
+ int ret;
1495
+
1496
+ ret = _vcpu_ioctl(vm, vcpuid, KVM_GET_FPU, fpu);
1497
+ TEST_ASSERT(ret == 0, "KVM_GET_FPU failed, rc: %i errno: %i (%s)",
1498
+ ret, errno, strerror(errno));
1499
+}
1500
+
1501
+void vcpu_fpu_set(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_fpu *fpu)
1502
+{
1503
+ int ret;
1504
+
1505
+ ret = _vcpu_ioctl(vm, vcpuid, KVM_SET_FPU, fpu);
1506
+ TEST_ASSERT(ret == 0, "KVM_SET_FPU failed, rc: %i errno: %i (%s)",
1507
+ ret, errno, strerror(errno));
1508
+}
1509
+
1510
+void vcpu_get_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg)
1511
+{
1512
+ int ret;
1513
+
1514
+ ret = _vcpu_ioctl(vm, vcpuid, KVM_GET_ONE_REG, reg);
1515
+ TEST_ASSERT(ret == 0, "KVM_GET_ONE_REG failed, rc: %i errno: %i (%s)",
1516
+ ret, errno, strerror(errno));
1517
+}
1518
+
1519
+void vcpu_set_reg(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_one_reg *reg)
1520
+{
1521
+ int ret;
1522
+
1523
+ ret = _vcpu_ioctl(vm, vcpuid, KVM_SET_ONE_REG, reg);
1524
+ TEST_ASSERT(ret == 0, "KVM_SET_ONE_REG failed, rc: %i errno: %i (%s)",
1525
+ ret, errno, strerror(errno));
1526
+}
1527
+
1528
+/*
1529
+ * VCPU Ioctl
14211530 *
14221531 * Input Args:
14231532 * vm - Virtual Machine
....@@ -1429,8 +1538,18 @@
14291538 *
14301539 * Issues an arbitrary ioctl on a VCPU fd.
14311540 */
1432
-void vcpu_ioctl(struct kvm_vm *vm,
1433
- uint32_t vcpuid, unsigned long cmd, void *arg)
1541
+void vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid,
1542
+ unsigned long cmd, void *arg)
1543
+{
1544
+ int ret;
1545
+
1546
+ ret = _vcpu_ioctl(vm, vcpuid, cmd, arg);
1547
+ TEST_ASSERT(ret == 0, "vcpu ioctl %lu failed, rc: %i errno: %i (%s)",
1548
+ cmd, ret, errno, strerror(errno));
1549
+}
1550
+
1551
+int _vcpu_ioctl(struct kvm_vm *vm, uint32_t vcpuid,
1552
+ unsigned long cmd, void *arg)
14341553 {
14351554 struct vcpu *vcpu = vcpu_find(vm, vcpuid);
14361555 int ret;
....@@ -1438,11 +1557,12 @@
14381557 TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
14391558
14401559 ret = ioctl(vcpu->fd, cmd, arg);
1441
- TEST_ASSERT(ret == 0, "vcpu ioctl %lu failed, rc: %i errno: %i (%s)",
1442
- cmd, ret, errno, strerror(errno));
1560
+
1561
+ return ret;
14431562 }
14441563
1445
-/* VM Ioctl
1564
+/*
1565
+ * VM Ioctl
14461566 *
14471567 * Input Args:
14481568 * vm - Virtual Machine
....@@ -1462,7 +1582,8 @@
14621582 cmd, ret, errno, strerror(errno));
14631583 }
14641584
1465
-/* VM Dump
1585
+/*
1586
+ * VM Dump
14661587 *
14671588 * Input Args:
14681589 * vm - Virtual Machine
....@@ -1485,8 +1606,7 @@
14851606 fprintf(stream, "%*sfd: %i\n", indent, "", vm->fd);
14861607 fprintf(stream, "%*spage_size: 0x%x\n", indent, "", vm->page_size);
14871608 fprintf(stream, "%*sMem Regions:\n", indent, "");
1488
- for (region = vm->userspace_mem_region_head; region;
1489
- region = region->next) {
1609
+ list_for_each_entry(region, &vm->userspace_mem_regions, list) {
14901610 fprintf(stream, "%*sguest_phys: 0x%lx size: 0x%lx "
14911611 "host_virt: %p\n", indent + 2, "",
14921612 (uint64_t) region->region.guest_phys_addr,
....@@ -1505,40 +1625,8 @@
15051625 virt_dump(stream, vm, indent + 4);
15061626 }
15071627 fprintf(stream, "%*sVCPUs:\n", indent, "");
1508
- for (vcpu = vm->vcpu_head; vcpu; vcpu = vcpu->next)
1628
+ list_for_each_entry(vcpu, &vm->vcpus, list)
15091629 vcpu_dump(stream, vm, vcpu->id, indent + 2);
1510
-}
1511
-
1512
-/* VM VCPU Dump
1513
- *
1514
- * Input Args:
1515
- * vm - Virtual Machine
1516
- * vcpuid - VCPU ID
1517
- * indent - Left margin indent amount
1518
- *
1519
- * Output Args:
1520
- * stream - Output FILE stream
1521
- *
1522
- * Return: None
1523
- *
1524
- * Dumps the current state of the VCPU specified by vcpuid, within the VM
1525
- * given by vm, to the FILE stream given by stream.
1526
- */
1527
-void vcpu_dump(FILE *stream, struct kvm_vm *vm,
1528
- uint32_t vcpuid, uint8_t indent)
1529
-{
1530
- struct kvm_regs regs;
1531
- struct kvm_sregs sregs;
1532
-
1533
- fprintf(stream, "%*scpuid: %u\n", indent, "", vcpuid);
1534
-
1535
- fprintf(stream, "%*sregs:\n", indent + 2, "");
1536
- vcpu_regs_get(vm, vcpuid, &regs);
1537
- regs_dump(stream, &regs, indent + 4);
1538
-
1539
- fprintf(stream, "%*ssregs:\n", indent + 2, "");
1540
- vcpu_sregs_get(vm, vcpuid, &sregs);
1541
- sregs_dump(stream, &sregs, indent + 4);
15421630 }
15431631
15441632 /* Known KVM exit reasons */
....@@ -1571,7 +1659,8 @@
15711659 #endif
15721660 };
15731661
1574
-/* Exit Reason String
1662
+/*
1663
+ * Exit Reason String
15751664 *
15761665 * Input Args:
15771666 * exit_reason - Exit reason
....@@ -1597,10 +1686,12 @@
15971686 return "Unknown";
15981687 }
15991688
1600
-/* Physical Page Allocate
1689
+/*
1690
+ * Physical Contiguous Page Allocator
16011691 *
16021692 * Input Args:
16031693 * vm - Virtual Machine
1694
+ * num - number of pages
16041695 * paddr_min - Physical address minimum
16051696 * memslot - Memory region to allocate page from
16061697 *
....@@ -1609,47 +1700,59 @@
16091700 * Return:
16101701 * Starting physical address
16111702 *
1612
- * Within the VM specified by vm, locates an available physical page
1613
- * at or above paddr_min. If found, the page is marked as in use
1614
- * and its address is returned. A TEST_ASSERT failure occurs if no
1615
- * page is available at or above paddr_min.
1703
+ * Within the VM specified by vm, locates a range of available physical
1704
+ * pages at or above paddr_min. If found, the pages are marked as in use
1705
+ * and their base address is returned. A TEST_ASSERT failure occurs if
1706
+ * not enough pages are available at or above paddr_min.
16161707 */
1617
-vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm,
1618
- vm_paddr_t paddr_min, uint32_t memslot)
1708
+vm_paddr_t vm_phy_pages_alloc(struct kvm_vm *vm, size_t num,
1709
+ vm_paddr_t paddr_min, uint32_t memslot)
16191710 {
16201711 struct userspace_mem_region *region;
1621
- sparsebit_idx_t pg;
1712
+ sparsebit_idx_t pg, base;
1713
+
1714
+ TEST_ASSERT(num > 0, "Must allocate at least one page");
16221715
16231716 TEST_ASSERT((paddr_min % vm->page_size) == 0, "Min physical address "
16241717 "not divisible by page size.\n"
16251718 " paddr_min: 0x%lx page_size: 0x%x",
16261719 paddr_min, vm->page_size);
16271720
1628
- /* Locate memory region. */
16291721 region = memslot2region(vm, memslot);
1722
+ base = pg = paddr_min >> vm->page_shift;
16301723
1631
- /* Locate next available physical page at or above paddr_min. */
1632
- pg = paddr_min >> vm->page_shift;
1633
-
1634
- if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
1635
- pg = sparsebit_next_set(region->unused_phy_pages, pg);
1636
- if (pg == 0) {
1637
- fprintf(stderr, "No guest physical page available, "
1638
- "paddr_min: 0x%lx page_size: 0x%x memslot: %u",
1639
- paddr_min, vm->page_size, memslot);
1640
- fputs("---- vm dump ----\n", stderr);
1641
- vm_dump(stderr, vm, 2);
1642
- abort();
1724
+ do {
1725
+ for (; pg < base + num; ++pg) {
1726
+ if (!sparsebit_is_set(region->unused_phy_pages, pg)) {
1727
+ base = pg = sparsebit_next_set(region->unused_phy_pages, pg);
1728
+ break;
1729
+ }
16431730 }
1731
+ } while (pg && pg != base + num);
1732
+
1733
+ if (pg == 0) {
1734
+ fprintf(stderr, "No guest physical page available, "
1735
+ "paddr_min: 0x%lx page_size: 0x%x memslot: %u\n",
1736
+ paddr_min, vm->page_size, memslot);
1737
+ fputs("---- vm dump ----\n", stderr);
1738
+ vm_dump(stderr, vm, 2);
1739
+ abort();
16441740 }
16451741
1646
- /* Specify page as in use and return its address. */
1647
- sparsebit_clear(region->unused_phy_pages, pg);
1742
+ for (pg = base; pg < base + num; ++pg)
1743
+ sparsebit_clear(region->unused_phy_pages, pg);
16481744
1649
- return pg * vm->page_size;
1745
+ return base * vm->page_size;
16501746 }
16511747
1652
-/* Address Guest Virtual to Host Virtual
1748
+vm_paddr_t vm_phy_page_alloc(struct kvm_vm *vm, vm_paddr_t paddr_min,
1749
+ uint32_t memslot)
1750
+{
1751
+ return vm_phy_pages_alloc(vm, 1, paddr_min, memslot);
1752
+}
1753
+
1754
+/*
1755
+ * Address Guest Virtual to Host Virtual
16531756 *
16541757 * Input Args:
16551758 * vm - Virtual Machine
....@@ -1665,16 +1768,98 @@
16651768 return addr_gpa2hva(vm, addr_gva2gpa(vm, gva));
16661769 }
16671770
1668
-void guest_args_read(struct kvm_vm *vm, uint32_t vcpu_id,
1669
- struct guest_args *args)
1771
+/*
1772
+ * Is Unrestricted Guest
1773
+ *
1774
+ * Input Args:
1775
+ * vm - Virtual Machine
1776
+ *
1777
+ * Output Args: None
1778
+ *
1779
+ * Return: True if the unrestricted guest is set to 'Y', otherwise return false.
1780
+ *
1781
+ * Check if the unrestricted guest flag is enabled.
1782
+ */
1783
+bool vm_is_unrestricted_guest(struct kvm_vm *vm)
16701784 {
1671
- struct kvm_run *run = vcpu_state(vm, vcpu_id);
1672
- struct kvm_regs regs;
1785
+ char val = 'N';
1786
+ size_t count;
1787
+ FILE *f;
16731788
1674
- memset(&regs, 0, sizeof(regs));
1675
- vcpu_regs_get(vm, vcpu_id, &regs);
1789
+ if (vm == NULL) {
1790
+ /* Ensure that the KVM vendor-specific module is loaded. */
1791
+ f = fopen(KVM_DEV_PATH, "r");
1792
+ TEST_ASSERT(f != NULL, "Error in opening KVM dev file: %d",
1793
+ errno);
1794
+ fclose(f);
1795
+ }
16761796
1677
- args->port = run->io.port;
1678
- args->arg0 = regs.rdi;
1679
- args->arg1 = regs.rsi;
1797
+ f = fopen("/sys/module/kvm_intel/parameters/unrestricted_guest", "r");
1798
+ if (f) {
1799
+ count = fread(&val, sizeof(char), 1, f);
1800
+ TEST_ASSERT(count == 1, "Unable to read from param file.");
1801
+ fclose(f);
1802
+ }
1803
+
1804
+ return val == 'Y';
1805
+}
1806
+
1807
+unsigned int vm_get_page_size(struct kvm_vm *vm)
1808
+{
1809
+ return vm->page_size;
1810
+}
1811
+
1812
+unsigned int vm_get_page_shift(struct kvm_vm *vm)
1813
+{
1814
+ return vm->page_shift;
1815
+}
1816
+
1817
+unsigned int vm_get_max_gfn(struct kvm_vm *vm)
1818
+{
1819
+ return vm->max_gfn;
1820
+}
1821
+
1822
+int vm_get_fd(struct kvm_vm *vm)
1823
+{
1824
+ return vm->fd;
1825
+}
1826
+
1827
+static unsigned int vm_calc_num_pages(unsigned int num_pages,
1828
+ unsigned int page_shift,
1829
+ unsigned int new_page_shift,
1830
+ bool ceil)
1831
+{
1832
+ unsigned int n = 1 << (new_page_shift - page_shift);
1833
+
1834
+ if (page_shift >= new_page_shift)
1835
+ return num_pages * (1 << (page_shift - new_page_shift));
1836
+
1837
+ return num_pages / n + !!(ceil && num_pages % n);
1838
+}
1839
+
1840
+static inline int getpageshift(void)
1841
+{
1842
+ return __builtin_ffs(getpagesize()) - 1;
1843
+}
1844
+
1845
+unsigned int
1846
+vm_num_host_pages(enum vm_guest_mode mode, unsigned int num_guest_pages)
1847
+{
1848
+ return vm_calc_num_pages(num_guest_pages,
1849
+ vm_guest_mode_params[mode].page_shift,
1850
+ getpageshift(), true);
1851
+}
1852
+
1853
+unsigned int
1854
+vm_num_guest_pages(enum vm_guest_mode mode, unsigned int num_host_pages)
1855
+{
1856
+ return vm_calc_num_pages(num_host_pages, getpageshift(),
1857
+ vm_guest_mode_params[mode].page_shift, false);
1858
+}
1859
+
1860
+unsigned int vm_calc_num_guest_pages(enum vm_guest_mode mode, size_t size)
1861
+{
1862
+ unsigned int n;
1863
+ n = DIV_ROUND_UP(size, vm_guest_mode_params[mode].page_size);
1864
+ return vm_adjust_num_guest_pages(mode, n);
16801865 }