summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-27 15:44:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-27 15:44:26 -0400
commit8bbe0dec38e147a50e9dd5f585295f7e68e0f2d0 (patch)
tree0781fd7dd090bbccd88f1f58caf6387a585b9ebe /tools/testing/selftests
parente37e3bc7e265d05d00f14079767537699cf6bd46 (diff)
parentfd3edd4a9066f28de99a16685a586d68a9f551f8 (diff)
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull more KVM updates from Paolo Bonzini: "x86 KVM changes: - The usual accuracy improvements for nested virtualization - The usual round of code cleanups from Sean - Added back optimizations that were prematurely removed in 5.2 (the bare minimum needed to fix the regression was in 5.3-rc8, here comes the rest) - Support for UMWAIT/UMONITOR/TPAUSE - Direct L2->L0 TLB flushing when L0 is Hyper-V and L1 is KVM - Tell Windows guests if SMT is disabled on the host - More accurate detection of vmexit cost - Revert a pvqspinlock pessimization" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: (56 commits) KVM: nVMX: cleanup and fix host 64-bit mode checks KVM: vmx: fix build warnings in hv_enable_direct_tlbflush() on i386 KVM: x86: Don't check kvm_rebooting in __kvm_handle_fault_on_reboot() KVM: x86: Drop ____kvm_handle_fault_on_reboot() KVM: VMX: Add error handling to VMREAD helper KVM: VMX: Optimize VMX instruction error and fault handling KVM: x86: Check kvm_rebooting in kvm_spurious_fault() KVM: selftests: fix ucall on x86 Revert "locking/pvqspinlock: Don't wait if vCPU is preempted" kvm: nvmx: limit atomic switch MSRs kvm: svm: Intercept RDPRU kvm: x86: Add "significant index" flag to a few CPUID leaves KVM: x86/mmu: Skip invalid pages during zapping iff root_count is zero KVM: x86/mmu: Explicitly track only a single invalid mmu generation KVM: x86/mmu: Revert "KVM: x86/mmu: Remove is_obsolete() call" KVM: x86/mmu: Revert "Revert "KVM: MMU: reclaim the zapped-obsolete page first"" KVM: x86/mmu: Revert "Revert "KVM: MMU: collapse TLB flushes when zap all pages"" KVM: x86/mmu: Revert "Revert "KVM: MMU: zap pages in batch"" KVM: x86/mmu: Revert "Revert "KVM: MMU: add tracepoint for kvm_mmu_invalidate_all_pages"" KVM: x86/mmu: Revert "Revert "KVM: MMU: show mmu_valid_gen in shadow page related tracepoints"" ...
Diffstat (limited to 'tools/testing/selftests')
-rw-r--r--tools/testing/selftests/kvm/dirty_log_test.c79
-rw-r--r--tools/testing/selftests/kvm/include/kvm_util.h18
-rw-r--r--tools/testing/selftests/kvm/include/x86_64/processor.h3
-rw-r--r--tools/testing/selftests/kvm/lib/aarch64/processor.c3
-rw-r--r--tools/testing/selftests/kvm/lib/kvm_util.c67
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/processor.c30
-rw-r--r--tools/testing/selftests/kvm/lib/x86_64/ucall.c2
-rw-r--r--tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c27
8 files changed, 149 insertions, 80 deletions
diff --git a/tools/testing/selftests/kvm/dirty_log_test.c b/tools/testing/selftests/kvm/dirty_log_test.c
index dc3346e090f5..5614222a6628 100644
--- a/tools/testing/selftests/kvm/dirty_log_test.c
+++ b/tools/testing/selftests/kvm/dirty_log_test.c
@@ -19,8 +19,6 @@
19#include "kvm_util.h" 19#include "kvm_util.h"
20#include "processor.h" 20#include "processor.h"
21 21
22#define DEBUG printf
23
24#define VCPU_ID 1 22#define VCPU_ID 1
25 23
26/* The memory slot index to track dirty pages */ 24/* The memory slot index to track dirty pages */
@@ -249,14 +247,12 @@ static void vm_dirty_log_verify(unsigned long *bmap)
249} 247}
250 248
251static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid, 249static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid,
252 uint64_t extra_mem_pages, void *guest_code, 250 uint64_t extra_mem_pages, void *guest_code)
253 unsigned long type)
254{ 251{
255 struct kvm_vm *vm; 252 struct kvm_vm *vm;
256 uint64_t extra_pg_pages = extra_mem_pages / 512 * 2; 253 uint64_t extra_pg_pages = extra_mem_pages / 512 * 2;
257 254
258 vm = _vm_create(mode, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, 255 vm = _vm_create(mode, DEFAULT_GUEST_PHY_PAGES + extra_pg_pages, O_RDWR);
259 O_RDWR, type);
260 kvm_vm_elf_load(vm, program_invocation_name, 0, 0); 256 kvm_vm_elf_load(vm, program_invocation_name, 0, 0);
261#ifdef __x86_64__ 257#ifdef __x86_64__
262 vm_create_irqchip(vm); 258 vm_create_irqchip(vm);
@@ -265,67 +261,35 @@ static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid,
265 return vm; 261 return vm;
266} 262}
267 263
264#define DIRTY_MEM_BITS 30 /* 1G */
265#define PAGE_SHIFT_4K 12
266
268static void run_test(enum vm_guest_mode mode, unsigned long iterations, 267static void run_test(enum vm_guest_mode mode, unsigned long iterations,
269 unsigned long interval, uint64_t phys_offset) 268 unsigned long interval, uint64_t phys_offset)
270{ 269{
271 unsigned int guest_pa_bits, guest_page_shift;
272 pthread_t vcpu_thread; 270 pthread_t vcpu_thread;
273 struct kvm_vm *vm; 271 struct kvm_vm *vm;
274 uint64_t max_gfn;
275 unsigned long *bmap; 272 unsigned long *bmap;
276 unsigned long type = 0;
277
278 switch (mode) {
279 case VM_MODE_P52V48_4K:
280 guest_pa_bits = 52;
281 guest_page_shift = 12;
282 break;
283 case VM_MODE_P52V48_64K:
284 guest_pa_bits = 52;
285 guest_page_shift = 16;
286 break;
287 case VM_MODE_P48V48_4K:
288 guest_pa_bits = 48;
289 guest_page_shift = 12;
290 break;
291 case VM_MODE_P48V48_64K:
292 guest_pa_bits = 48;
293 guest_page_shift = 16;
294 break;
295 case VM_MODE_P40V48_4K:
296 guest_pa_bits = 40;
297 guest_page_shift = 12;
298 break;
299 case VM_MODE_P40V48_64K:
300 guest_pa_bits = 40;
301 guest_page_shift = 16;
302 break;
303 default:
304 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
305 }
306 273
307 DEBUG("Testing guest mode: %s\n", vm_guest_mode_string(mode));
308
309#ifdef __x86_64__
310 /* 274 /*
311 * FIXME 275 * We reserve page table for 2 times of extra dirty mem which
312 * The x86_64 kvm selftests framework currently only supports a 276 * will definitely cover the original (1G+) test range. Here
313 * single PML4 which restricts the number of physical address 277 * we do the calculation with 4K page size which is the
314 * bits we can change to 39. 278 * smallest so the page number will be enough for all archs
279 * (e.g., 64K page size guest will need even less memory for
280 * page tables).
315 */ 281 */
316 guest_pa_bits = 39; 282 vm = create_vm(mode, VCPU_ID,
317#endif 283 2ul << (DIRTY_MEM_BITS - PAGE_SHIFT_4K),
318#ifdef __aarch64__ 284 guest_code);
319 if (guest_pa_bits != 40) 285
320 type = KVM_VM_TYPE_ARM_IPA_SIZE(guest_pa_bits); 286 guest_page_size = vm_get_page_size(vm);
321#endif
322 max_gfn = (1ul << (guest_pa_bits - guest_page_shift)) - 1;
323 guest_page_size = (1ul << guest_page_shift);
324 /* 287 /*
325 * A little more than 1G of guest page sized pages. Cover the 288 * A little more than 1G of guest page sized pages. Cover the
326 * case where the size is not aligned to 64 pages. 289 * case where the size is not aligned to 64 pages.
327 */ 290 */
328 guest_num_pages = (1ul << (30 - guest_page_shift)) + 16; 291 guest_num_pages = (1ul << (DIRTY_MEM_BITS -
292 vm_get_page_shift(vm))) + 16;
329#ifdef __s390x__ 293#ifdef __s390x__
330 /* Round up to multiple of 1M (segment size) */ 294 /* Round up to multiple of 1M (segment size) */
331 guest_num_pages = (guest_num_pages + 0xff) & ~0xffUL; 295 guest_num_pages = (guest_num_pages + 0xff) & ~0xffUL;
@@ -335,7 +299,8 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations,
335 !!((guest_num_pages * guest_page_size) % host_page_size); 299 !!((guest_num_pages * guest_page_size) % host_page_size);
336 300
337 if (!phys_offset) { 301 if (!phys_offset) {
338 guest_test_phys_mem = (max_gfn - guest_num_pages) * guest_page_size; 302 guest_test_phys_mem = (vm_get_max_gfn(vm) -
303 guest_num_pages) * guest_page_size;
339 guest_test_phys_mem &= ~(host_page_size - 1); 304 guest_test_phys_mem &= ~(host_page_size - 1);
340 } else { 305 } else {
341 guest_test_phys_mem = phys_offset; 306 guest_test_phys_mem = phys_offset;
@@ -351,8 +316,6 @@ static void run_test(enum vm_guest_mode mode, unsigned long iterations,
351 bmap = bitmap_alloc(host_num_pages); 316 bmap = bitmap_alloc(host_num_pages);
352 host_bmap_track = bitmap_alloc(host_num_pages); 317 host_bmap_track = bitmap_alloc(host_num_pages);
353 318
354 vm = create_vm(mode, VCPU_ID, guest_num_pages, guest_code, type);
355
356#ifdef USE_CLEAR_DIRTY_LOG 319#ifdef USE_CLEAR_DIRTY_LOG
357 struct kvm_enable_cap cap = {}; 320 struct kvm_enable_cap cap = {};
358 321
@@ -482,7 +445,7 @@ int main(int argc, char *argv[])
482#endif 445#endif
483 446
484#ifdef __x86_64__ 447#ifdef __x86_64__
485 vm_guest_mode_params_init(VM_MODE_P52V48_4K, true, true); 448 vm_guest_mode_params_init(VM_MODE_PXXV48_4K, true, true);
486#endif 449#endif
487#ifdef __aarch64__ 450#ifdef __aarch64__
488 vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true); 451 vm_guest_mode_params_init(VM_MODE_P40V48_4K, true, true);
diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
index 5463b7896a0a..29cccaf96baf 100644
--- a/tools/testing/selftests/kvm/include/kvm_util.h
+++ b/tools/testing/selftests/kvm/include/kvm_util.h
@@ -24,6 +24,12 @@ struct kvm_vm;
24typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ 24typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */
25typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ 25typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */
26 26
27#ifndef NDEBUG
28#define DEBUG(...) printf(__VA_ARGS__);
29#else
30#define DEBUG(...)
31#endif
32
27/* Minimum allocated guest virtual and physical addresses */ 33/* Minimum allocated guest virtual and physical addresses */
28#define KVM_UTIL_MIN_VADDR 0x2000 34#define KVM_UTIL_MIN_VADDR 0x2000
29 35
@@ -38,11 +44,14 @@ enum vm_guest_mode {
38 VM_MODE_P48V48_64K, 44 VM_MODE_P48V48_64K,
39 VM_MODE_P40V48_4K, 45 VM_MODE_P40V48_4K,
40 VM_MODE_P40V48_64K, 46 VM_MODE_P40V48_64K,
47 VM_MODE_PXXV48_4K, /* For 48bits VA but ANY bits PA */
41 NUM_VM_MODES, 48 NUM_VM_MODES,
42}; 49};
43 50
44#ifdef __aarch64__ 51#if defined(__aarch64__)
45#define VM_MODE_DEFAULT VM_MODE_P40V48_4K 52#define VM_MODE_DEFAULT VM_MODE_P40V48_4K
53#elif defined(__x86_64__)
54#define VM_MODE_DEFAULT VM_MODE_PXXV48_4K
46#else 55#else
47#define VM_MODE_DEFAULT VM_MODE_P52V48_4K 56#define VM_MODE_DEFAULT VM_MODE_P52V48_4K
48#endif 57#endif
@@ -60,8 +69,7 @@ int kvm_check_cap(long cap);
60int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap); 69int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap);
61 70
62struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm); 71struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
63struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, 72struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
64 int perm, unsigned long type);
65void kvm_vm_free(struct kvm_vm *vmp); 73void kvm_vm_free(struct kvm_vm *vmp);
66void kvm_vm_restart(struct kvm_vm *vmp, int perm); 74void kvm_vm_restart(struct kvm_vm *vmp, int perm);
67void kvm_vm_release(struct kvm_vm *vmp); 75void kvm_vm_release(struct kvm_vm *vmp);
@@ -146,6 +154,10 @@ void vm_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid, void *guest_code);
146 154
147bool vm_is_unrestricted_guest(struct kvm_vm *vm); 155bool vm_is_unrestricted_guest(struct kvm_vm *vm);
148 156
157unsigned int vm_get_page_size(struct kvm_vm *vm);
158unsigned int vm_get_page_shift(struct kvm_vm *vm);
159unsigned int vm_get_max_gfn(struct kvm_vm *vm);
160
149struct kvm_userspace_memory_region * 161struct kvm_userspace_memory_region *
150kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start, 162kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start,
151 uint64_t end); 163 uint64_t end);
diff --git a/tools/testing/selftests/kvm/include/x86_64/processor.h b/tools/testing/selftests/kvm/include/x86_64/processor.h
index 80d19740d2dc..0c17f2ee685e 100644
--- a/tools/testing/selftests/kvm/include/x86_64/processor.h
+++ b/tools/testing/selftests/kvm/include/x86_64/processor.h
@@ -325,6 +325,9 @@ uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
325void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index, 325void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
326 uint64_t msr_value); 326 uint64_t msr_value);
327 327
328uint32_t kvm_get_cpuid_max(void);
329void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits);
330
328/* 331/*
329 * Basic CPU control in CR0 332 * Basic CPU control in CR0
330 */ 333 */
diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c
index 486400a97374..86036a59a668 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/processor.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c
@@ -264,6 +264,9 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, int vcpuid, struct kvm_vcpu_init *ini
264 case VM_MODE_P52V48_4K: 264 case VM_MODE_P52V48_4K:
265 TEST_ASSERT(false, "AArch64 does not support 4K sized pages " 265 TEST_ASSERT(false, "AArch64 does not support 4K sized pages "
266 "with 52-bit physical address ranges"); 266 "with 52-bit physical address ranges");
267 case VM_MODE_PXXV48_4K:
268 TEST_ASSERT(false, "AArch64 does not support 4K sized pages "
269 "with ANY-bit physical address ranges");
267 case VM_MODE_P52V48_64K: 270 case VM_MODE_P52V48_64K:
268 tcr_el1 |= 1ul << 14; /* TG0 = 64KB */ 271 tcr_el1 |= 1ul << 14; /* TG0 = 64KB */
269 tcr_el1 |= 6ul << 32; /* IPS = 52 bits */ 272 tcr_el1 |= 6ul << 32; /* IPS = 52 bits */
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index 6e49bb039376..80a338b5403c 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -8,6 +8,7 @@
8#include "test_util.h" 8#include "test_util.h"
9#include "kvm_util.h" 9#include "kvm_util.h"
10#include "kvm_util_internal.h" 10#include "kvm_util_internal.h"
11#include "processor.h"
11 12
12#include <assert.h> 13#include <assert.h>
13#include <sys/mman.h> 14#include <sys/mman.h>
@@ -84,7 +85,7 @@ int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap)
84 return ret; 85 return ret;
85} 86}
86 87
87static void vm_open(struct kvm_vm *vm, int perm, unsigned long type) 88static void vm_open(struct kvm_vm *vm, int perm)
88{ 89{
89 vm->kvm_fd = open(KVM_DEV_PATH, perm); 90 vm->kvm_fd = open(KVM_DEV_PATH, perm);
90 if (vm->kvm_fd < 0) 91 if (vm->kvm_fd < 0)
@@ -95,18 +96,19 @@ static void vm_open(struct kvm_vm *vm, int perm, unsigned long type)
95 exit(KSFT_SKIP); 96 exit(KSFT_SKIP);
96 } 97 }
97 98
98 vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, type); 99 vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, vm->type);
99 TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, " 100 TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, "
100 "rc: %i errno: %i", vm->fd, errno); 101 "rc: %i errno: %i", vm->fd, errno);
101} 102}
102 103
103const char * const vm_guest_mode_string[] = { 104const char * const vm_guest_mode_string[] = {
104 "PA-bits:52, VA-bits:48, 4K pages", 105 "PA-bits:52, VA-bits:48, 4K pages",
105 "PA-bits:52, VA-bits:48, 64K pages", 106 "PA-bits:52, VA-bits:48, 64K pages",
106 "PA-bits:48, VA-bits:48, 4K pages", 107 "PA-bits:48, VA-bits:48, 4K pages",
107 "PA-bits:48, VA-bits:48, 64K pages", 108 "PA-bits:48, VA-bits:48, 64K pages",
108 "PA-bits:40, VA-bits:48, 4K pages", 109 "PA-bits:40, VA-bits:48, 4K pages",
109 "PA-bits:40, VA-bits:48, 64K pages", 110 "PA-bits:40, VA-bits:48, 64K pages",
111 "PA-bits:ANY, VA-bits:48, 4K pages",
110}; 112};
111_Static_assert(sizeof(vm_guest_mode_string)/sizeof(char *) == NUM_VM_MODES, 113_Static_assert(sizeof(vm_guest_mode_string)/sizeof(char *) == NUM_VM_MODES,
112 "Missing new mode strings?"); 114 "Missing new mode strings?");
@@ -130,17 +132,17 @@ _Static_assert(sizeof(vm_guest_mode_string)/sizeof(char *) == NUM_VM_MODES,
130 * descriptor to control the created VM is created with the permissions 132 * descriptor to control the created VM is created with the permissions
131 * given by perm (e.g. O_RDWR). 133 * given by perm (e.g. O_RDWR).
132 */ 134 */
133struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, 135struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
134 int perm, unsigned long type)
135{ 136{
136 struct kvm_vm *vm; 137 struct kvm_vm *vm;
137 138
139 DEBUG("Testing guest mode: %s\n", vm_guest_mode_string(mode));
140
138 vm = calloc(1, sizeof(*vm)); 141 vm = calloc(1, sizeof(*vm));
139 TEST_ASSERT(vm != NULL, "Insufficient Memory"); 142 TEST_ASSERT(vm != NULL, "Insufficient Memory");
140 143
141 vm->mode = mode; 144 vm->mode = mode;
142 vm->type = type; 145 vm->type = 0;
143 vm_open(vm, perm, type);
144 146
145 /* Setup mode specific traits. */ 147 /* Setup mode specific traits. */
146 switch (vm->mode) { 148 switch (vm->mode) {
@@ -186,10 +188,32 @@ struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages,
186 vm->page_size = 0x10000; 188 vm->page_size = 0x10000;
187 vm->page_shift = 16; 189 vm->page_shift = 16;
188 break; 190 break;
191 case VM_MODE_PXXV48_4K:
192#ifdef __x86_64__
193 kvm_get_cpu_address_width(&vm->pa_bits, &vm->va_bits);
194 TEST_ASSERT(vm->va_bits == 48, "Linear address width "
195 "(%d bits) not supported", vm->va_bits);
196 vm->pgtable_levels = 4;
197 vm->page_size = 0x1000;
198 vm->page_shift = 12;
199 DEBUG("Guest physical address width detected: %d\n",
200 vm->pa_bits);
201#else
202 TEST_ASSERT(false, "VM_MODE_PXXV48_4K not supported on "
203 "non-x86 platforms");
204#endif
205 break;
189 default: 206 default:
190 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode); 207 TEST_ASSERT(false, "Unknown guest mode, mode: 0x%x", mode);
191 } 208 }
192 209
210#ifdef __aarch64__
211 if (vm->pa_bits != 40)
212 vm->type = KVM_VM_TYPE_ARM_IPA_SIZE(vm->pa_bits);
213#endif
214
215 vm_open(vm, perm);
216
193 /* Limit to VA-bit canonical virtual addresses. */ 217 /* Limit to VA-bit canonical virtual addresses. */
194 vm->vpages_valid = sparsebit_alloc(); 218 vm->vpages_valid = sparsebit_alloc();
195 sparsebit_set_num(vm->vpages_valid, 219 sparsebit_set_num(vm->vpages_valid,
@@ -212,7 +236,7 @@ struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages,
212 236
213struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) 237struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm)
214{ 238{
215 return _vm_create(mode, phy_pages, perm, 0); 239 return _vm_create(mode, phy_pages, perm);
216} 240}
217 241
218/* 242/*
@@ -232,7 +256,7 @@ void kvm_vm_restart(struct kvm_vm *vmp, int perm)
232{ 256{
233 struct userspace_mem_region *region; 257 struct userspace_mem_region *region;
234 258
235 vm_open(vmp, perm, vmp->type); 259 vm_open(vmp, perm);
236 if (vmp->has_irqchip) 260 if (vmp->has_irqchip)
237 vm_create_irqchip(vmp); 261 vm_create_irqchip(vmp);
238 262
@@ -1628,3 +1652,18 @@ bool vm_is_unrestricted_guest(struct kvm_vm *vm)
1628 1652
1629 return val == 'Y'; 1653 return val == 'Y';
1630} 1654}
1655
1656unsigned int vm_get_page_size(struct kvm_vm *vm)
1657{
1658 return vm->page_size;
1659}
1660
1661unsigned int vm_get_page_shift(struct kvm_vm *vm)
1662{
1663 return vm->page_shift;
1664}
1665
1666unsigned int vm_get_max_gfn(struct kvm_vm *vm)
1667{
1668 return vm->max_gfn;
1669}
diff --git a/tools/testing/selftests/kvm/lib/x86_64/processor.c b/tools/testing/selftests/kvm/lib/x86_64/processor.c
index 0a5e487dbc50..c53dbc6bc568 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/processor.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/processor.c
@@ -228,7 +228,7 @@ void sregs_dump(FILE *stream, struct kvm_sregs *sregs,
228 228
229void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot) 229void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot)
230{ 230{
231 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use " 231 TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
232 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 232 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
233 233
234 /* If needed, create page map l4 table. */ 234 /* If needed, create page map l4 table. */
@@ -261,7 +261,7 @@ void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr,
261 uint16_t index[4]; 261 uint16_t index[4];
262 struct pageMapL4Entry *pml4e; 262 struct pageMapL4Entry *pml4e;
263 263
264 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use " 264 TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
265 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 265 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
266 266
267 TEST_ASSERT((vaddr % vm->page_size) == 0, 267 TEST_ASSERT((vaddr % vm->page_size) == 0,
@@ -547,7 +547,7 @@ vm_paddr_t addr_gva2gpa(struct kvm_vm *vm, vm_vaddr_t gva)
547 struct pageDirectoryEntry *pde; 547 struct pageDirectoryEntry *pde;
548 struct pageTableEntry *pte; 548 struct pageTableEntry *pte;
549 549
550 TEST_ASSERT(vm->mode == VM_MODE_P52V48_4K, "Attempt to use " 550 TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use "
551 "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 551 "unknown or unsupported guest mode, mode: 0x%x", vm->mode);
552 552
553 index[0] = (gva >> 12) & 0x1ffu; 553 index[0] = (gva >> 12) & 0x1ffu;
@@ -621,7 +621,7 @@ static void vcpu_setup(struct kvm_vm *vm, int vcpuid, int pgd_memslot, int gdt_m
621 kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot); 621 kvm_setup_gdt(vm, &sregs.gdt, gdt_memslot, pgd_memslot);
622 622
623 switch (vm->mode) { 623 switch (vm->mode) {
624 case VM_MODE_P52V48_4K: 624 case VM_MODE_PXXV48_4K:
625 sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG; 625 sregs.cr0 = X86_CR0_PE | X86_CR0_NE | X86_CR0_PG;
626 sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; 626 sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR;
627 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX); 627 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX);
@@ -1157,3 +1157,25 @@ bool is_intel_cpu(void)
1157 chunk = (const uint32_t *)("GenuineIntel"); 1157 chunk = (const uint32_t *)("GenuineIntel");
1158 return (ebx == chunk[0] && edx == chunk[1] && ecx == chunk[2]); 1158 return (ebx == chunk[0] && edx == chunk[1] && ecx == chunk[2]);
1159} 1159}
1160
1161uint32_t kvm_get_cpuid_max(void)
1162{
1163 return kvm_get_supported_cpuid_entry(0x80000000)->eax;
1164}
1165
1166void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits)
1167{
1168 struct kvm_cpuid_entry2 *entry;
1169 bool pae;
1170
1171 /* SDM 4.1.4 */
1172 if (kvm_get_cpuid_max() < 0x80000008) {
1173 pae = kvm_get_supported_cpuid_entry(1)->edx & (1 << 6);
1174 *pa_bits = pae ? 36 : 32;
1175 *va_bits = 32;
1176 } else {
1177 entry = kvm_get_supported_cpuid_entry(0x80000008);
1178 *pa_bits = entry->eax & 0xff;
1179 *va_bits = (entry->eax >> 8) & 0xff;
1180 }
1181}
diff --git a/tools/testing/selftests/kvm/lib/x86_64/ucall.c b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
index 4bfc9a90b1de..da4d89ad5419 100644
--- a/tools/testing/selftests/kvm/lib/x86_64/ucall.c
+++ b/tools/testing/selftests/kvm/lib/x86_64/ucall.c
@@ -32,7 +32,7 @@ void ucall(uint64_t cmd, int nargs, ...)
32 va_end(va); 32 va_end(va);
33 33
34 asm volatile("in %[port], %%al" 34 asm volatile("in %[port], %%al"
35 : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax"); 35 : : [port] "d" (UCALL_PIO_PORT), "D" (&uc) : "rax", "memory");
36} 36}
37 37
38uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) 38uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc)
diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
index ee59831fbc98..443a2b54645b 100644
--- a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
+++ b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
@@ -26,6 +26,25 @@ static void guest_code(void)
26{ 26{
27} 27}
28 28
29static int smt_possible(void)
30{
31 char buf[16];
32 FILE *f;
33 bool res = 1;
34
35 f = fopen("/sys/devices/system/cpu/smt/control", "r");
36 if (f) {
37 if (fread(buf, sizeof(*buf), sizeof(buf), f) > 0) {
38 if (!strncmp(buf, "forceoff", 8) ||
39 !strncmp(buf, "notsupported", 12))
40 res = 0;
41 }
42 fclose(f);
43 }
44
45 return res;
46}
47
29static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries, 48static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries,
30 int evmcs_enabled) 49 int evmcs_enabled)
31{ 50{
@@ -59,6 +78,14 @@ static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries,
59 TEST_ASSERT(!entry->padding[0] && !entry->padding[1] && 78 TEST_ASSERT(!entry->padding[0] && !entry->padding[1] &&
60 !entry->padding[2], "padding should be zero"); 79 !entry->padding[2], "padding should be zero");
61 80
81 if (entry->function == 0x40000004) {
82 int nononarchcs = !!(entry->eax & (1UL << 18));
83
84 TEST_ASSERT(nononarchcs == !smt_possible(),
85 "NoNonArchitecturalCoreSharing bit"
86 " doesn't reflect SMT setting");
87 }
88
62 /* 89 /*
63 * If needed for debug: 90 * If needed for debug:
64 * fprintf(stdout, 91 * fprintf(stdout,