diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-27 15:44:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-27 15:44:26 -0400 |
commit | 8bbe0dec38e147a50e9dd5f585295f7e68e0f2d0 (patch) | |
tree | 0781fd7dd090bbccd88f1f58caf6387a585b9ebe /tools/testing/selftests | |
parent | e37e3bc7e265d05d00f14079767537699cf6bd46 (diff) | |
parent | fd3edd4a9066f28de99a16685a586d68a9f551f8 (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.c | 79 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/include/kvm_util.h | 18 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/include/x86_64/processor.h | 3 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/lib/aarch64/processor.c | 3 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/lib/kvm_util.c | 67 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/lib/x86_64/processor.c | 30 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/lib/x86_64/ucall.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c | 27 |
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 | ||
251 | static struct kvm_vm *create_vm(enum vm_guest_mode mode, uint32_t vcpuid, | 249 | static 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 | |||
268 | static void run_test(enum vm_guest_mode mode, unsigned long iterations, | 267 | static 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; | |||
24 | typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ | 24 | typedef uint64_t vm_paddr_t; /* Virtual Machine (Guest) physical address */ |
25 | typedef uint64_t vm_vaddr_t; /* Virtual Machine (Guest) virtual address */ | 25 | typedef 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); | |||
60 | int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap); | 69 | int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap); |
61 | 70 | ||
62 | struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm); | 71 | struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm); |
63 | struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, | 72 | struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm); |
64 | int perm, unsigned long type); | ||
65 | void kvm_vm_free(struct kvm_vm *vmp); | 73 | void kvm_vm_free(struct kvm_vm *vmp); |
66 | void kvm_vm_restart(struct kvm_vm *vmp, int perm); | 74 | void kvm_vm_restart(struct kvm_vm *vmp, int perm); |
67 | void kvm_vm_release(struct kvm_vm *vmp); | 75 | void 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 | ||
147 | bool vm_is_unrestricted_guest(struct kvm_vm *vm); | 155 | bool vm_is_unrestricted_guest(struct kvm_vm *vm); |
148 | 156 | ||
157 | unsigned int vm_get_page_size(struct kvm_vm *vm); | ||
158 | unsigned int vm_get_page_shift(struct kvm_vm *vm); | ||
159 | unsigned int vm_get_max_gfn(struct kvm_vm *vm); | ||
160 | |||
149 | struct kvm_userspace_memory_region * | 161 | struct kvm_userspace_memory_region * |
150 | kvm_userspace_memory_region_find(struct kvm_vm *vm, uint64_t start, | 162 | kvm_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); | |||
325 | void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index, | 325 | void 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 | ||
328 | uint32_t kvm_get_cpuid_max(void); | ||
329 | void 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 | ||
87 | static void vm_open(struct kvm_vm *vm, int perm, unsigned long type) | 88 | static 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 | ||
103 | const char * const vm_guest_mode_string[] = { | 104 | const 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 | */ |
133 | struct kvm_vm *_vm_create(enum vm_guest_mode mode, uint64_t phy_pages, | 135 | struct 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 | ||
213 | struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm) | 237 | struct 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 | |||
1656 | unsigned int vm_get_page_size(struct kvm_vm *vm) | ||
1657 | { | ||
1658 | return vm->page_size; | ||
1659 | } | ||
1660 | |||
1661 | unsigned int vm_get_page_shift(struct kvm_vm *vm) | ||
1662 | { | ||
1663 | return vm->page_shift; | ||
1664 | } | ||
1665 | |||
1666 | unsigned 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 | ||
229 | void virt_pgd_alloc(struct kvm_vm *vm, uint32_t pgd_memslot) | 229 | void 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 | |||
1161 | uint32_t kvm_get_cpuid_max(void) | ||
1162 | { | ||
1163 | return kvm_get_supported_cpuid_entry(0x80000000)->eax; | ||
1164 | } | ||
1165 | |||
1166 | void 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 | ||
38 | uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc) | 38 | uint64_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 | ||
29 | static 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 | |||
29 | static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries, | 48 | static 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, |