Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'kvm-x86-selftests-6.19' of https://github.com/kvm-x86/linux into HEAD

KVM selftests changes for 6.19:

- Fix a math goof in mmu_stress_test when running on a single-CPU system/VM.

- Forcefully override ARCH from x86_64 to x86 to play nice with specifying
ARCH=x86_64 on the command line.

- Extend a bunch of nested VMX to validate nested SVM as well.

- Add support for LA57 in the core VM_MODE_xxx macro, and add a test to
verify KVM can save/restore nested VMX state when L1 is using 5-level
paging, but L2 is not.

- Clean up the guest paging code in anticipation of sharing the core logic for
nested EPT and nested NPT.

+477 -162
+1 -1
tools/testing/selftests/kvm/Makefile
··· 6 6 ifeq ($(ARCH),$(filter $(ARCH),arm64 s390 riscv x86 x86_64 loongarch)) 7 7 # Top-level selftests allows ARCH=x86_64 :-( 8 8 ifeq ($(ARCH),x86_64) 9 - ARCH := x86 9 + override ARCH := x86 10 10 endif 11 11 include Makefile.kvm 12 12 else
+5 -3
tools/testing/selftests/kvm/Makefile.kvm
··· 88 88 TEST_GEN_PROGS_x86 += x86/kvm_buslock_test 89 89 TEST_GEN_PROGS_x86 += x86/monitor_mwait_test 90 90 TEST_GEN_PROGS_x86 += x86/msrs_test 91 + TEST_GEN_PROGS_x86 += x86/nested_close_kvm_test 91 92 TEST_GEN_PROGS_x86 += x86/nested_emulation_test 92 93 TEST_GEN_PROGS_x86 += x86/nested_exceptions_test 94 + TEST_GEN_PROGS_x86 += x86/nested_invalid_cr3_test 95 + TEST_GEN_PROGS_x86 += x86/nested_tsc_adjust_test 96 + TEST_GEN_PROGS_x86 += x86/nested_tsc_scaling_test 93 97 TEST_GEN_PROGS_x86 += x86/platform_info_test 94 98 TEST_GEN_PROGS_x86 += x86/pmu_counters_test 95 99 TEST_GEN_PROGS_x86 += x86/pmu_event_filter_test ··· 115 111 TEST_GEN_PROGS_x86 += x86/userspace_io_test 116 112 TEST_GEN_PROGS_x86 += x86/userspace_msr_exit_test 117 113 TEST_GEN_PROGS_x86 += x86/vmx_apic_access_test 118 - TEST_GEN_PROGS_x86 += x86/vmx_close_while_nested_test 119 114 TEST_GEN_PROGS_x86 += x86/vmx_dirty_log_test 120 115 TEST_GEN_PROGS_x86 += x86/vmx_exception_with_invalid_guest_state 121 116 TEST_GEN_PROGS_x86 += x86/vmx_msrs_test 122 117 TEST_GEN_PROGS_x86 += x86/vmx_invalid_nested_guest_state 118 + TEST_GEN_PROGS_x86 += x86/vmx_nested_la57_state_test 123 119 TEST_GEN_PROGS_x86 += x86/vmx_set_nested_state_test 124 - TEST_GEN_PROGS_x86 += x86/vmx_tsc_adjust_test 125 - TEST_GEN_PROGS_x86 += x86/vmx_nested_tsc_scaling_test 126 120 TEST_GEN_PROGS_x86 += x86/apic_bus_clock_test 127 121 TEST_GEN_PROGS_x86 += x86/xapic_ipi_test 128 122 TEST_GEN_PROGS_x86 += x86/xapic_state_test
+3 -2
tools/testing/selftests/kvm/include/kvm_util.h
··· 178 178 VM_MODE_P40V48_4K, 179 179 VM_MODE_P40V48_16K, 180 180 VM_MODE_P40V48_64K, 181 - VM_MODE_PXXV48_4K, /* For 48bits VA but ANY bits PA */ 181 + VM_MODE_PXXVYY_4K, /* For 48-bit or 57-bit VA, depending on host support */ 182 182 VM_MODE_P47V64_4K, 183 183 VM_MODE_P44V64_4K, 184 184 VM_MODE_P36V48_4K, ··· 220 220 221 221 #elif defined(__x86_64__) 222 222 223 - #define VM_MODE_DEFAULT VM_MODE_PXXV48_4K 223 + #define VM_MODE_DEFAULT VM_MODE_PXXVYY_4K 224 224 #define MIN_PAGE_SHIFT 12U 225 225 #define ptes_per_page(page_size) ((page_size) / 8) 226 226 ··· 1203 1203 static inline void virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr) 1204 1204 { 1205 1205 virt_arch_pg_map(vm, vaddr, paddr); 1206 + sparsebit_set(vm->vpages_mapped, vaddr >> vm->page_shift); 1206 1207 } 1207 1208 1208 1209
+1 -1
tools/testing/selftests/kvm/include/x86/processor.h
··· 1441 1441 PG_LEVEL_2M, 1442 1442 PG_LEVEL_1G, 1443 1443 PG_LEVEL_512G, 1444 - PG_LEVEL_NUM 1444 + PG_LEVEL_256T 1445 1445 }; 1446 1446 1447 1447 #define PG_LEVEL_SHIFT(_level) ((_level - 1) * 9 + 12)
+1 -2
tools/testing/selftests/kvm/include/x86/vmx.h
··· 568 568 void nested_identity_map_1g(struct vmx_pages *vmx, struct kvm_vm *vm, 569 569 uint64_t addr, uint64_t size); 570 570 bool kvm_cpu_has_ept(void); 571 - void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm, 572 - uint32_t eptp_memslot); 571 + void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm); 573 572 void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm); 574 573 575 574 #endif /* SELFTEST_KVM_VMX_H */
+1 -1
tools/testing/selftests/kvm/lib/arm64/processor.c
··· 324 324 325 325 /* Configure base granule size */ 326 326 switch (vm->mode) { 327 - case VM_MODE_PXXV48_4K: 327 + case VM_MODE_PXXVYY_4K: 328 328 TEST_FAIL("AArch64 does not support 4K sized pages " 329 329 "with ANY-bit physical address ranges"); 330 330 case VM_MODE_P52V48_64K:
+16 -17
tools/testing/selftests/kvm/lib/kvm_util.c
··· 201 201 [VM_MODE_P40V48_4K] = "PA-bits:40, VA-bits:48, 4K pages", 202 202 [VM_MODE_P40V48_16K] = "PA-bits:40, VA-bits:48, 16K pages", 203 203 [VM_MODE_P40V48_64K] = "PA-bits:40, VA-bits:48, 64K pages", 204 - [VM_MODE_PXXV48_4K] = "PA-bits:ANY, VA-bits:48, 4K pages", 204 + [VM_MODE_PXXVYY_4K] = "PA-bits:ANY, VA-bits:48 or 57, 4K pages", 205 205 [VM_MODE_P47V64_4K] = "PA-bits:47, VA-bits:64, 4K pages", 206 206 [VM_MODE_P44V64_4K] = "PA-bits:44, VA-bits:64, 4K pages", 207 207 [VM_MODE_P36V48_4K] = "PA-bits:36, VA-bits:48, 4K pages", ··· 228 228 [VM_MODE_P40V48_4K] = { 40, 48, 0x1000, 12 }, 229 229 [VM_MODE_P40V48_16K] = { 40, 48, 0x4000, 14 }, 230 230 [VM_MODE_P40V48_64K] = { 40, 48, 0x10000, 16 }, 231 - [VM_MODE_PXXV48_4K] = { 0, 0, 0x1000, 12 }, 231 + [VM_MODE_PXXVYY_4K] = { 0, 0, 0x1000, 12 }, 232 232 [VM_MODE_P47V64_4K] = { 47, 64, 0x1000, 12 }, 233 233 [VM_MODE_P44V64_4K] = { 44, 64, 0x1000, 12 }, 234 234 [VM_MODE_P36V48_4K] = { 36, 48, 0x1000, 12 }, ··· 310 310 case VM_MODE_P36V47_16K: 311 311 vm->pgtable_levels = 3; 312 312 break; 313 - case VM_MODE_PXXV48_4K: 313 + case VM_MODE_PXXVYY_4K: 314 314 #ifdef __x86_64__ 315 315 kvm_get_cpu_address_width(&vm->pa_bits, &vm->va_bits); 316 316 kvm_init_vm_address_properties(vm); 317 - /* 318 - * Ignore KVM support for 5-level paging (vm->va_bits == 57), 319 - * it doesn't take effect unless a CR4.LA57 is set, which it 320 - * isn't for this mode (48-bit virtual address space). 321 - */ 322 - TEST_ASSERT(vm->va_bits == 48 || vm->va_bits == 57, 323 - "Linear address width (%d bits) not supported", 324 - vm->va_bits); 317 + 325 318 pr_debug("Guest physical address width detected: %d\n", 326 319 vm->pa_bits); 327 - vm->pgtable_levels = 4; 328 - vm->va_bits = 48; 320 + pr_debug("Guest virtual address width detected: %d\n", 321 + vm->va_bits); 322 + 323 + if (vm->va_bits == 57) { 324 + vm->pgtable_levels = 5; 325 + } else { 326 + TEST_ASSERT(vm->va_bits == 48, 327 + "Unexpected guest virtual address width: %d", 328 + vm->va_bits); 329 + vm->pgtable_levels = 4; 330 + } 329 331 #else 330 - TEST_FAIL("VM_MODE_PXXV48_4K not supported on non-x86 platforms"); 332 + TEST_FAIL("VM_MODE_PXXVYY_4K not supported on non-x86 platforms"); 331 333 #endif 332 334 break; 333 335 case VM_MODE_P47V64_4K: ··· 1439 1437 pages--, vaddr += vm->page_size, paddr += vm->page_size) { 1440 1438 1441 1439 virt_pg_map(vm, vaddr, paddr); 1442 - 1443 - sparsebit_set(vm->vpages_mapped, vaddr >> vm->page_shift); 1444 1440 } 1445 1441 1446 1442 return vaddr_start; ··· 1552 1552 1553 1553 while (npages--) { 1554 1554 virt_pg_map(vm, vaddr, paddr); 1555 - sparsebit_set(vm->vpages_mapped, vaddr >> vm->page_shift); 1556 1555 1557 1556 vaddr += page_size; 1558 1557 paddr += page_size;
+1 -1
tools/testing/selftests/kvm/lib/x86/memstress.c
··· 63 63 { 64 64 uint64_t start, end; 65 65 66 - prepare_eptp(vmx, vm, 0); 66 + prepare_eptp(vmx, vm); 67 67 68 68 /* 69 69 * Identity map the first 4G and the test region with 1G pages so that
+40 -40
tools/testing/selftests/kvm/lib/x86/processor.c
··· 158 158 159 159 void virt_arch_pgd_alloc(struct kvm_vm *vm) 160 160 { 161 - TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use " 162 - "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 161 + TEST_ASSERT(vm->mode == VM_MODE_PXXVYY_4K, 162 + "Unknown or unsupported guest mode: 0x%x", vm->mode); 163 163 164 - /* If needed, create page map l4 table. */ 164 + /* If needed, create the top-level page table. */ 165 165 if (!vm->pgd_created) { 166 166 vm->pgd = vm_alloc_page_table(vm); 167 167 vm->pgd_created = true; ··· 218 218 void __virt_pg_map(struct kvm_vm *vm, uint64_t vaddr, uint64_t paddr, int level) 219 219 { 220 220 const uint64_t pg_size = PG_LEVEL_SIZE(level); 221 - uint64_t *pml4e, *pdpe, *pde; 222 - uint64_t *pte; 221 + uint64_t *pte = &vm->pgd; 222 + int current_level; 223 223 224 - TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, 225 - "Unknown or unsupported guest mode, mode: 0x%x", vm->mode); 224 + TEST_ASSERT(vm->mode == VM_MODE_PXXVYY_4K, 225 + "Unknown or unsupported guest mode: 0x%x", vm->mode); 226 226 227 227 TEST_ASSERT((vaddr % pg_size) == 0, 228 228 "Virtual address not aligned,\n" ··· 243 243 * Allocate upper level page tables, if not already present. Return 244 244 * early if a hugepage was created. 245 245 */ 246 - pml4e = virt_create_upper_pte(vm, &vm->pgd, vaddr, paddr, PG_LEVEL_512G, level); 247 - if (*pml4e & PTE_LARGE_MASK) 248 - return; 249 - 250 - pdpe = virt_create_upper_pte(vm, pml4e, vaddr, paddr, PG_LEVEL_1G, level); 251 - if (*pdpe & PTE_LARGE_MASK) 252 - return; 253 - 254 - pde = virt_create_upper_pte(vm, pdpe, vaddr, paddr, PG_LEVEL_2M, level); 255 - if (*pde & PTE_LARGE_MASK) 256 - return; 246 + for (current_level = vm->pgtable_levels; 247 + current_level > PG_LEVEL_4K; 248 + current_level--) { 249 + pte = virt_create_upper_pte(vm, pte, vaddr, paddr, 250 + current_level, level); 251 + if (*pte & PTE_LARGE_MASK) 252 + return; 253 + } 257 254 258 255 /* Fill in page table entry. */ 259 - pte = virt_get_pte(vm, pde, vaddr, PG_LEVEL_4K); 256 + pte = virt_get_pte(vm, pte, vaddr, PG_LEVEL_4K); 260 257 TEST_ASSERT(!(*pte & PTE_PRESENT_MASK), 261 258 "PTE already present for 4k page at vaddr: 0x%lx", vaddr); 262 259 *pte = PTE_PRESENT_MASK | PTE_WRITABLE_MASK | (paddr & PHYSICAL_PAGE_MASK); ··· 286 289 287 290 for (i = 0; i < nr_pages; i++) { 288 291 __virt_pg_map(vm, vaddr, paddr, level); 292 + sparsebit_set_num(vm->vpages_mapped, vaddr >> vm->page_shift, 293 + nr_bytes / PAGE_SIZE); 289 294 290 295 vaddr += pg_size; 291 296 paddr += pg_size; ··· 309 310 uint64_t *__vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr, 310 311 int *level) 311 312 { 312 - uint64_t *pml4e, *pdpe, *pde; 313 + int va_width = 12 + (vm->pgtable_levels) * 9; 314 + uint64_t *pte = &vm->pgd; 315 + int current_level; 313 316 314 317 TEST_ASSERT(!vm->arch.is_pt_protected, 315 318 "Walking page tables of protected guests is impossible"); 316 319 317 - TEST_ASSERT(*level >= PG_LEVEL_NONE && *level < PG_LEVEL_NUM, 320 + TEST_ASSERT(*level >= PG_LEVEL_NONE && *level <= vm->pgtable_levels, 318 321 "Invalid PG_LEVEL_* '%d'", *level); 319 322 320 - TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use " 321 - "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 323 + TEST_ASSERT(vm->mode == VM_MODE_PXXVYY_4K, 324 + "Unknown or unsupported guest mode: 0x%x", vm->mode); 322 325 TEST_ASSERT(sparsebit_is_set(vm->vpages_valid, 323 326 (vaddr >> vm->page_shift)), 324 327 "Invalid virtual address, vaddr: 0x%lx", 325 328 vaddr); 326 329 /* 327 - * Based on the mode check above there are 48 bits in the vaddr, so 328 - * shift 16 to sign extend the last bit (bit-47), 330 + * Check that the vaddr is a sign-extended va_width value. 329 331 */ 330 - TEST_ASSERT(vaddr == (((int64_t)vaddr << 16) >> 16), 331 - "Canonical check failed. The virtual address is invalid."); 332 + TEST_ASSERT(vaddr == 333 + (((int64_t)vaddr << (64 - va_width) >> (64 - va_width))), 334 + "Canonical check failed. The virtual address is invalid."); 332 335 333 - pml4e = virt_get_pte(vm, &vm->pgd, vaddr, PG_LEVEL_512G); 334 - if (vm_is_target_pte(pml4e, level, PG_LEVEL_512G)) 335 - return pml4e; 336 + for (current_level = vm->pgtable_levels; 337 + current_level > PG_LEVEL_4K; 338 + current_level--) { 339 + pte = virt_get_pte(vm, pte, vaddr, current_level); 340 + if (vm_is_target_pte(pte, level, current_level)) 341 + return pte; 342 + } 336 343 337 - pdpe = virt_get_pte(vm, pml4e, vaddr, PG_LEVEL_1G); 338 - if (vm_is_target_pte(pdpe, level, PG_LEVEL_1G)) 339 - return pdpe; 340 - 341 - pde = virt_get_pte(vm, pdpe, vaddr, PG_LEVEL_2M); 342 - if (vm_is_target_pte(pde, level, PG_LEVEL_2M)) 343 - return pde; 344 - 345 - return virt_get_pte(vm, pde, vaddr, PG_LEVEL_4K); 344 + return virt_get_pte(vm, pte, vaddr, PG_LEVEL_4K); 346 345 } 347 346 348 347 uint64_t *vm_get_page_table_entry(struct kvm_vm *vm, uint64_t vaddr) ··· 523 526 { 524 527 struct kvm_sregs sregs; 525 528 526 - TEST_ASSERT_EQ(vm->mode, VM_MODE_PXXV48_4K); 529 + TEST_ASSERT(vm->mode == VM_MODE_PXXVYY_4K, 530 + "Unknown or unsupported guest mode: 0x%x", vm->mode); 527 531 528 532 /* Set mode specific system register values. */ 529 533 vcpu_sregs_get(vcpu, &sregs); ··· 538 540 sregs.cr4 |= X86_CR4_PAE | X86_CR4_OSFXSR; 539 541 if (kvm_cpu_has(X86_FEATURE_XSAVE)) 540 542 sregs.cr4 |= X86_CR4_OSXSAVE; 543 + if (vm->pgtable_levels == 5) 544 + sregs.cr4 |= X86_CR4_LA57; 541 545 sregs.efer |= (EFER_LME | EFER_LMA | EFER_NX); 542 546 543 547 kvm_seg_set_unusable(&sregs.ldt);
+4 -5
tools/testing/selftests/kvm/lib/x86/vmx.c
··· 401 401 struct eptPageTableEntry *pt = vmx->eptp_hva, *pte; 402 402 uint16_t index; 403 403 404 - TEST_ASSERT(vm->mode == VM_MODE_PXXV48_4K, "Attempt to use " 405 - "unknown or unsupported guest mode, mode: 0x%x", vm->mode); 404 + TEST_ASSERT(vm->mode == VM_MODE_PXXVYY_4K, 405 + "Unknown or unsupported guest mode: 0x%x", vm->mode); 406 406 407 407 TEST_ASSERT((nested_paddr >> 48) == 0, 408 - "Nested physical address 0x%lx requires 5-level paging", 408 + "Nested physical address 0x%lx is > 48-bits and requires 5-level EPT", 409 409 nested_paddr); 410 410 TEST_ASSERT((nested_paddr % page_size) == 0, 411 411 "Nested physical address not on page boundary,\n" ··· 534 534 return ctrl & SECONDARY_EXEC_ENABLE_EPT; 535 535 } 536 536 537 - void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm, 538 - uint32_t eptp_memslot) 537 + void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm) 539 538 { 540 539 TEST_ASSERT(kvm_cpu_has_ept(), "KVM doesn't support nested EPT"); 541 540
+5 -5
tools/testing/selftests/kvm/mmu_stress_test.c
··· 263 263 TEST_ASSERT(!r, "sched_getaffinity failed, errno = %d (%s)", 264 264 errno, strerror(errno)); 265 265 266 - nr_vcpus = CPU_COUNT(&possible_mask) * 3/4; 266 + nr_vcpus = CPU_COUNT(&possible_mask); 267 267 TEST_ASSERT(nr_vcpus > 0, "Uh, no CPUs?"); 268 + if (nr_vcpus >= 2) 269 + nr_vcpus = nr_vcpus * 3/4; 268 270 } 269 271 270 272 int main(int argc, char *argv[]) ··· 362 360 363 361 #ifdef __x86_64__ 364 362 /* Identity map memory in the guest using 1gb pages. */ 365 - for (i = 0; i < slot_size; i += SZ_1G) 366 - __virt_pg_map(vm, gpa + i, gpa + i, PG_LEVEL_1G); 363 + virt_map_level(vm, gpa, gpa, slot_size, PG_LEVEL_1G); 367 364 #else 368 - for (i = 0; i < slot_size; i += vm->page_size) 369 - virt_pg_map(vm, gpa + i, gpa + i); 365 + virt_map(vm, gpa, gpa, slot_size >> vm->page_shift); 370 366 #endif 371 367 } 372 368
+14 -18
tools/testing/selftests/kvm/pre_fault_memory_test.c
··· 17 17 #define TEST_NPAGES (TEST_SIZE / PAGE_SIZE) 18 18 #define TEST_SLOT 10 19 19 20 - static void guest_code(uint64_t base_gpa) 20 + static void guest_code(uint64_t base_gva) 21 21 { 22 22 volatile uint64_t val __used; 23 23 int i; 24 24 25 25 for (i = 0; i < TEST_NPAGES; i++) { 26 - uint64_t *src = (uint64_t *)(base_gpa + i * PAGE_SIZE); 26 + uint64_t *src = (uint64_t *)(base_gva + i * PAGE_SIZE); 27 27 28 28 val = *src; 29 29 } ··· 161 161 162 162 static void __test_pre_fault_memory(unsigned long vm_type, bool private) 163 163 { 164 + uint64_t gpa, gva, alignment, guest_page_size; 164 165 const struct vm_shape shape = { 165 166 .mode = VM_MODE_DEFAULT, 166 167 .type = vm_type, ··· 171 170 struct kvm_vm *vm; 172 171 struct ucall uc; 173 172 174 - uint64_t guest_test_phys_mem; 175 - uint64_t guest_test_virt_mem; 176 - uint64_t alignment, guest_page_size; 177 - 178 173 vm = vm_create_shape_with_one_vcpu(shape, &vcpu, guest_code); 179 174 180 175 alignment = guest_page_size = vm_guest_mode_params[VM_MODE_DEFAULT].page_size; 181 - guest_test_phys_mem = (vm->max_gfn - TEST_NPAGES) * guest_page_size; 176 + gpa = (vm->max_gfn - TEST_NPAGES) * guest_page_size; 182 177 #ifdef __s390x__ 183 178 alignment = max(0x100000UL, guest_page_size); 184 179 #else 185 180 alignment = SZ_2M; 186 181 #endif 187 - guest_test_phys_mem = align_down(guest_test_phys_mem, alignment); 188 - guest_test_virt_mem = guest_test_phys_mem & ((1ULL << (vm->va_bits - 1)) - 1); 182 + gpa = align_down(gpa, alignment); 183 + gva = gpa & ((1ULL << (vm->va_bits - 1)) - 1); 189 184 190 - vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 191 - guest_test_phys_mem, TEST_SLOT, TEST_NPAGES, 192 - private ? KVM_MEM_GUEST_MEMFD : 0); 193 - virt_map(vm, guest_test_virt_mem, guest_test_phys_mem, TEST_NPAGES); 185 + vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, gpa, TEST_SLOT, 186 + TEST_NPAGES, private ? KVM_MEM_GUEST_MEMFD : 0); 187 + virt_map(vm, gva, gpa, TEST_NPAGES); 194 188 195 189 if (private) 196 - vm_mem_set_private(vm, guest_test_phys_mem, TEST_SIZE); 190 + vm_mem_set_private(vm, gpa, TEST_SIZE); 197 191 198 - pre_fault_memory(vcpu, guest_test_phys_mem, 0, SZ_2M, 0, private); 199 - pre_fault_memory(vcpu, guest_test_phys_mem, SZ_2M, PAGE_SIZE * 2, PAGE_SIZE, private); 200 - pre_fault_memory(vcpu, guest_test_phys_mem, TEST_SIZE, PAGE_SIZE, PAGE_SIZE, private); 192 + pre_fault_memory(vcpu, gpa, 0, SZ_2M, 0, private); 193 + pre_fault_memory(vcpu, gpa, SZ_2M, PAGE_SIZE * 2, PAGE_SIZE, private); 194 + pre_fault_memory(vcpu, gpa, TEST_SIZE, PAGE_SIZE, PAGE_SIZE, private); 201 195 202 - vcpu_args_set(vcpu, 1, guest_test_virt_mem); 196 + vcpu_args_set(vcpu, 1, gva); 203 197 vcpu_run(vcpu); 204 198 205 199 run = vcpu->run;
+1 -1
tools/testing/selftests/kvm/x86/hyperv_features.c
··· 94 94 95 95 if (!(hcall->control & HV_HYPERCALL_FAST_BIT)) { 96 96 input = pgs_gpa; 97 - output = pgs_gpa + 4096; 97 + output = pgs_gpa + PAGE_SIZE; 98 98 } else { 99 99 input = output = 0; 100 100 }
+9 -9
tools/testing/selftests/kvm/x86/hyperv_ipi.c
··· 102 102 /* 'Slow' HvCallSendSyntheticClusterIpi to RECEIVER_VCPU_ID_1 */ 103 103 ipi->vector = IPI_VECTOR; 104 104 ipi->cpu_mask = 1 << RECEIVER_VCPU_ID_1; 105 - hyperv_hypercall(HVCALL_SEND_IPI, pgs_gpa, pgs_gpa + 4096); 105 + hyperv_hypercall(HVCALL_SEND_IPI, pgs_gpa, pgs_gpa + PAGE_SIZE); 106 106 nop_loop(); 107 107 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_1] == ++ipis_expected[0]); 108 108 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_2] == ipis_expected[1]); ··· 116 116 GUEST_SYNC(stage++); 117 117 118 118 /* 'Slow' HvCallSendSyntheticClusterIpiEx to RECEIVER_VCPU_ID_1 */ 119 - memset(hcall_page, 0, 4096); 119 + memset(hcall_page, 0, PAGE_SIZE); 120 120 ipi_ex->vector = IPI_VECTOR; 121 121 ipi_ex->vp_set.format = HV_GENERIC_SET_SPARSE_4K; 122 122 ipi_ex->vp_set.valid_bank_mask = 1 << 0; 123 123 ipi_ex->vp_set.bank_contents[0] = BIT(RECEIVER_VCPU_ID_1); 124 124 hyperv_hypercall(HVCALL_SEND_IPI_EX | (1 << HV_HYPERCALL_VARHEAD_OFFSET), 125 - pgs_gpa, pgs_gpa + 4096); 125 + pgs_gpa, pgs_gpa + PAGE_SIZE); 126 126 nop_loop(); 127 127 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_1] == ++ipis_expected[0]); 128 128 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_2] == ipis_expected[1]); ··· 138 138 GUEST_SYNC(stage++); 139 139 140 140 /* 'Slow' HvCallSendSyntheticClusterIpiEx to RECEIVER_VCPU_ID_2 */ 141 - memset(hcall_page, 0, 4096); 141 + memset(hcall_page, 0, PAGE_SIZE); 142 142 ipi_ex->vector = IPI_VECTOR; 143 143 ipi_ex->vp_set.format = HV_GENERIC_SET_SPARSE_4K; 144 144 ipi_ex->vp_set.valid_bank_mask = 1 << 1; 145 145 ipi_ex->vp_set.bank_contents[0] = BIT(RECEIVER_VCPU_ID_2 - 64); 146 146 hyperv_hypercall(HVCALL_SEND_IPI_EX | (1 << HV_HYPERCALL_VARHEAD_OFFSET), 147 - pgs_gpa, pgs_gpa + 4096); 147 + pgs_gpa, pgs_gpa + PAGE_SIZE); 148 148 nop_loop(); 149 149 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_1] == ipis_expected[0]); 150 150 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_2] == ++ipis_expected[1]); ··· 160 160 GUEST_SYNC(stage++); 161 161 162 162 /* 'Slow' HvCallSendSyntheticClusterIpiEx to both RECEIVER_VCPU_ID_{1,2} */ 163 - memset(hcall_page, 0, 4096); 163 + memset(hcall_page, 0, PAGE_SIZE); 164 164 ipi_ex->vector = IPI_VECTOR; 165 165 ipi_ex->vp_set.format = HV_GENERIC_SET_SPARSE_4K; 166 166 ipi_ex->vp_set.valid_bank_mask = 1 << 1 | 1; 167 167 ipi_ex->vp_set.bank_contents[0] = BIT(RECEIVER_VCPU_ID_1); 168 168 ipi_ex->vp_set.bank_contents[1] = BIT(RECEIVER_VCPU_ID_2 - 64); 169 169 hyperv_hypercall(HVCALL_SEND_IPI_EX | (2 << HV_HYPERCALL_VARHEAD_OFFSET), 170 - pgs_gpa, pgs_gpa + 4096); 170 + pgs_gpa, pgs_gpa + PAGE_SIZE); 171 171 nop_loop(); 172 172 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_1] == ++ipis_expected[0]); 173 173 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_2] == ++ipis_expected[1]); ··· 183 183 GUEST_SYNC(stage++); 184 184 185 185 /* 'Slow' HvCallSendSyntheticClusterIpiEx to HV_GENERIC_SET_ALL */ 186 - memset(hcall_page, 0, 4096); 186 + memset(hcall_page, 0, PAGE_SIZE); 187 187 ipi_ex->vector = IPI_VECTOR; 188 188 ipi_ex->vp_set.format = HV_GENERIC_SET_ALL; 189 - hyperv_hypercall(HVCALL_SEND_IPI_EX, pgs_gpa, pgs_gpa + 4096); 189 + hyperv_hypercall(HVCALL_SEND_IPI_EX, pgs_gpa, pgs_gpa + PAGE_SIZE); 190 190 nop_loop(); 191 191 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_1] == ++ipis_expected[0]); 192 192 GUEST_ASSERT(ipis_rcvd[RECEIVER_VCPU_ID_2] == ++ipis_expected[1]);
+1 -1
tools/testing/selftests/kvm/x86/hyperv_tlb_flush.c
··· 621 621 for (i = 0; i < NTEST_PAGES; i++) { 622 622 pte = vm_get_page_table_entry(vm, data->test_pages + i * PAGE_SIZE); 623 623 gpa = addr_hva2gpa(vm, pte); 624 - __virt_pg_map(vm, gva + PAGE_SIZE * i, gpa & PAGE_MASK, PG_LEVEL_4K); 624 + virt_pg_map(vm, gva + PAGE_SIZE * i, gpa & PAGE_MASK); 625 625 data->test_pages_pte[i] = gva + (gpa & ~PAGE_MASK); 626 626 } 627 627
+116
tools/testing/selftests/kvm/x86/nested_invalid_cr3_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2025, Google LLC. 4 + * 5 + * This test verifies that L1 fails to enter L2 with an invalid CR3, and 6 + * succeeds otherwise. 7 + */ 8 + #include "kvm_util.h" 9 + #include "vmx.h" 10 + #include "svm_util.h" 11 + #include "kselftest.h" 12 + 13 + 14 + #define L2_GUEST_STACK_SIZE 64 15 + 16 + static void l2_guest_code(void) 17 + { 18 + vmcall(); 19 + } 20 + 21 + static void l1_svm_code(struct svm_test_data *svm) 22 + { 23 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 24 + uintptr_t save_cr3; 25 + 26 + generic_svm_setup(svm, l2_guest_code, 27 + &l2_guest_stack[L2_GUEST_STACK_SIZE]); 28 + 29 + /* Try to run L2 with invalid CR3 and make sure it fails */ 30 + save_cr3 = svm->vmcb->save.cr3; 31 + svm->vmcb->save.cr3 = -1ull; 32 + run_guest(svm->vmcb, svm->vmcb_gpa); 33 + GUEST_ASSERT(svm->vmcb->control.exit_code == SVM_EXIT_ERR); 34 + 35 + /* Now restore CR3 and make sure L2 runs successfully */ 36 + svm->vmcb->save.cr3 = save_cr3; 37 + run_guest(svm->vmcb, svm->vmcb_gpa); 38 + GUEST_ASSERT(svm->vmcb->control.exit_code == SVM_EXIT_VMMCALL); 39 + 40 + GUEST_DONE(); 41 + } 42 + 43 + static void l1_vmx_code(struct vmx_pages *vmx_pages) 44 + { 45 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 46 + uintptr_t save_cr3; 47 + 48 + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); 49 + GUEST_ASSERT(load_vmcs(vmx_pages)); 50 + 51 + prepare_vmcs(vmx_pages, l2_guest_code, 52 + &l2_guest_stack[L2_GUEST_STACK_SIZE]); 53 + 54 + /* Try to run L2 with invalid CR3 and make sure it fails */ 55 + save_cr3 = vmreadz(GUEST_CR3); 56 + vmwrite(GUEST_CR3, -1ull); 57 + GUEST_ASSERT(!vmlaunch()); 58 + GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == 59 + (EXIT_REASON_FAILED_VMENTRY | EXIT_REASON_INVALID_STATE)); 60 + 61 + /* Now restore CR3 and make sure L2 runs successfully */ 62 + vmwrite(GUEST_CR3, save_cr3); 63 + GUEST_ASSERT(!vmlaunch()); 64 + GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL); 65 + 66 + GUEST_DONE(); 67 + } 68 + 69 + static void l1_guest_code(void *data) 70 + { 71 + if (this_cpu_has(X86_FEATURE_VMX)) 72 + l1_vmx_code(data); 73 + else 74 + l1_svm_code(data); 75 + } 76 + 77 + int main(int argc, char *argv[]) 78 + { 79 + struct kvm_vcpu *vcpu; 80 + struct kvm_vm *vm; 81 + vm_vaddr_t guest_gva = 0; 82 + 83 + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX) || 84 + kvm_cpu_has(X86_FEATURE_SVM)); 85 + 86 + vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); 87 + 88 + if (kvm_cpu_has(X86_FEATURE_VMX)) 89 + vcpu_alloc_vmx(vm, &guest_gva); 90 + else 91 + vcpu_alloc_svm(vm, &guest_gva); 92 + 93 + vcpu_args_set(vcpu, 1, guest_gva); 94 + 95 + for (;;) { 96 + struct ucall uc; 97 + 98 + vcpu_run(vcpu); 99 + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); 100 + 101 + switch (get_ucall(vcpu, &uc)) { 102 + case UCALL_ABORT: 103 + REPORT_GUEST_ASSERT(uc); 104 + case UCALL_SYNC: 105 + break; 106 + case UCALL_DONE: 107 + goto done; 108 + default: 109 + TEST_FAIL("Unknown ucall %lu", uc.cmd); 110 + } 111 + } 112 + 113 + done: 114 + kvm_vm_free(vm); 115 + return 0; 116 + }
+1 -1
tools/testing/selftests/kvm/x86/sev_smoke_test.c
··· 104 104 vm_sev_launch(vm, policy, NULL); 105 105 106 106 /* This page is shared, so make it decrypted. */ 107 - memset(hva, 0, 4096); 107 + memset(hva, 0, PAGE_SIZE); 108 108 109 109 vcpu_run(vcpu); 110 110
+1 -1
tools/testing/selftests/kvm/x86/state_test.c
··· 141 141 142 142 if (this_cpu_has(X86_FEATURE_XSAVE)) { 143 143 uint64_t supported_xcr0 = this_cpu_supported_xcr0(); 144 - uint8_t buffer[4096]; 144 + uint8_t buffer[PAGE_SIZE]; 145 145 146 146 memset(buffer, 0xcc, sizeof(buffer)); 147 147
+1 -1
tools/testing/selftests/kvm/x86/userspace_io_test.c
··· 85 85 regs.rcx = 1; 86 86 if (regs.rcx == 3) 87 87 regs.rcx = 8192; 88 - memset((void *)run + run->io.data_offset, 0xaa, 4096); 88 + memset((void *)run + run->io.data_offset, 0xaa, PAGE_SIZE); 89 89 vcpu_regs_set(vcpu, &regs); 90 90 } 91 91
+33 -9
tools/testing/selftests/kvm/x86/vmx_close_while_nested_test.c tools/testing/selftests/kvm/x86/nested_close_kvm_test.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * vmx_close_while_nested 4 - * 5 3 * Copyright (C) 2019, Red Hat, Inc. 6 4 * 7 5 * Verify that nothing bad happens if a KVM user exits with open ··· 10 12 #include "kvm_util.h" 11 13 #include "processor.h" 12 14 #include "vmx.h" 15 + #include "svm_util.h" 13 16 14 17 #include <string.h> 15 18 #include <sys/ioctl.h> ··· 21 22 PORT_L0_EXIT = 0x2000, 22 23 }; 23 24 25 + #define L2_GUEST_STACK_SIZE 64 26 + 24 27 static void l2_guest_code(void) 25 28 { 26 29 /* Exit to L0 */ ··· 30 29 : : [port] "d" (PORT_L0_EXIT) : "rax"); 31 30 } 32 31 33 - static void l1_guest_code(struct vmx_pages *vmx_pages) 32 + static void l1_vmx_code(struct vmx_pages *vmx_pages) 34 33 { 35 - #define L2_GUEST_STACK_SIZE 64 36 34 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 37 35 38 36 GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); ··· 45 45 GUEST_ASSERT(0); 46 46 } 47 47 48 + static void l1_svm_code(struct svm_test_data *svm) 49 + { 50 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 51 + 52 + /* Prepare the VMCB for L2 execution. */ 53 + generic_svm_setup(svm, l2_guest_code, 54 + &l2_guest_stack[L2_GUEST_STACK_SIZE]); 55 + 56 + run_guest(svm->vmcb, svm->vmcb_gpa); 57 + GUEST_ASSERT(0); 58 + } 59 + 60 + static void l1_guest_code(void *data) 61 + { 62 + if (this_cpu_has(X86_FEATURE_VMX)) 63 + l1_vmx_code(data); 64 + else 65 + l1_svm_code(data); 66 + } 67 + 48 68 int main(int argc, char *argv[]) 49 69 { 50 - vm_vaddr_t vmx_pages_gva; 70 + vm_vaddr_t guest_gva; 51 71 struct kvm_vcpu *vcpu; 52 72 struct kvm_vm *vm; 53 73 54 - TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); 74 + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX) || 75 + kvm_cpu_has(X86_FEATURE_SVM)); 55 76 56 77 vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); 57 78 58 - /* Allocate VMX pages and shared descriptors (vmx_pages). */ 59 - vcpu_alloc_vmx(vm, &vmx_pages_gva); 60 - vcpu_args_set(vcpu, 1, vmx_pages_gva); 79 + if (kvm_cpu_has(X86_FEATURE_VMX)) 80 + vcpu_alloc_vmx(vm, &guest_gva); 81 + else 82 + vcpu_alloc_svm(vm, &guest_gva); 83 + 84 + vcpu_args_set(vcpu, 1, guest_gva); 61 85 62 86 for (;;) { 63 87 volatile struct kvm_run *run = vcpu->run;
+6 -6
tools/testing/selftests/kvm/x86/vmx_dirty_log_test.c
··· 120 120 * GPAs as the EPT enabled case. 121 121 */ 122 122 if (enable_ept) { 123 - prepare_eptp(vmx, vm, 0); 123 + prepare_eptp(vmx, vm); 124 124 nested_map_memslot(vmx, vm, 0); 125 - nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096); 126 - nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096); 125 + nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, PAGE_SIZE); 126 + nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, PAGE_SIZE); 127 127 } 128 128 129 129 bmap = bitmap_zalloc(TEST_MEM_PAGES); 130 130 host_test_mem = addr_gpa2hva(vm, GUEST_TEST_MEM); 131 131 132 132 while (!done) { 133 - memset(host_test_mem, 0xaa, TEST_MEM_PAGES * 4096); 133 + memset(host_test_mem, 0xaa, TEST_MEM_PAGES * PAGE_SIZE); 134 134 vcpu_run(vcpu); 135 135 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); 136 136 ··· 153 153 } 154 154 155 155 TEST_ASSERT(!test_bit(1, bmap), "Page 1 incorrectly reported dirty"); 156 - TEST_ASSERT(host_test_mem[4096 / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 1 written by guest"); 156 + TEST_ASSERT(host_test_mem[PAGE_SIZE / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 1 written by guest"); 157 157 TEST_ASSERT(!test_bit(2, bmap), "Page 2 incorrectly reported dirty"); 158 - TEST_ASSERT(host_test_mem[8192 / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 2 written by guest"); 158 + TEST_ASSERT(host_test_mem[PAGE_SIZE*2 / 8] == 0xaaaaaaaaaaaaaaaaULL, "Page 2 written by guest"); 159 159 break; 160 160 case UCALL_DONE: 161 161 done = true;
+132
tools/testing/selftests/kvm/x86/vmx_nested_la57_state_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2025, Google LLC. 4 + * 5 + * Test KVM's ability to save and restore nested state when the L1 guest 6 + * is using 5-level paging and the L2 guest is using 4-level paging. 7 + * 8 + * This test would have failed prior to commit 9245fd6b8531 ("KVM: x86: 9 + * model canonical checks more precisely"). 10 + */ 11 + #include "test_util.h" 12 + #include "kvm_util.h" 13 + #include "processor.h" 14 + #include "vmx.h" 15 + 16 + #define LA57_GS_BASE 0xff2bc0311fb00000ull 17 + 18 + static void l2_guest_code(void) 19 + { 20 + /* 21 + * Sync with L0 to trigger save/restore. After 22 + * resuming, execute VMCALL to exit back to L1. 23 + */ 24 + GUEST_SYNC(1); 25 + vmcall(); 26 + } 27 + 28 + static void l1_guest_code(struct vmx_pages *vmx_pages) 29 + { 30 + #define L2_GUEST_STACK_SIZE 64 31 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 32 + u64 guest_cr4; 33 + vm_paddr_t pml5_pa, pml4_pa; 34 + u64 *pml5; 35 + u64 exit_reason; 36 + 37 + /* Set GS_BASE to a value that is only canonical with LA57. */ 38 + wrmsr(MSR_GS_BASE, LA57_GS_BASE); 39 + GUEST_ASSERT(rdmsr(MSR_GS_BASE) == LA57_GS_BASE); 40 + 41 + GUEST_ASSERT(vmx_pages->vmcs_gpa); 42 + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); 43 + GUEST_ASSERT(load_vmcs(vmx_pages)); 44 + 45 + prepare_vmcs(vmx_pages, l2_guest_code, 46 + &l2_guest_stack[L2_GUEST_STACK_SIZE]); 47 + 48 + /* 49 + * Set up L2 with a 4-level page table by pointing its CR3 to 50 + * L1's first PML4 table and clearing CR4.LA57. This creates 51 + * the CR4.LA57 mismatch that exercises the bug. 52 + */ 53 + pml5_pa = get_cr3() & PHYSICAL_PAGE_MASK; 54 + pml5 = (u64 *)pml5_pa; 55 + pml4_pa = pml5[0] & PHYSICAL_PAGE_MASK; 56 + vmwrite(GUEST_CR3, pml4_pa); 57 + 58 + guest_cr4 = vmreadz(GUEST_CR4); 59 + guest_cr4 &= ~X86_CR4_LA57; 60 + vmwrite(GUEST_CR4, guest_cr4); 61 + 62 + GUEST_ASSERT(!vmlaunch()); 63 + 64 + exit_reason = vmreadz(VM_EXIT_REASON); 65 + GUEST_ASSERT(exit_reason == EXIT_REASON_VMCALL); 66 + } 67 + 68 + void guest_code(struct vmx_pages *vmx_pages) 69 + { 70 + l1_guest_code(vmx_pages); 71 + GUEST_DONE(); 72 + } 73 + 74 + int main(int argc, char *argv[]) 75 + { 76 + vm_vaddr_t vmx_pages_gva = 0; 77 + struct kvm_vm *vm; 78 + struct kvm_vcpu *vcpu; 79 + struct kvm_x86_state *state; 80 + struct ucall uc; 81 + int stage; 82 + 83 + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); 84 + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_LA57)); 85 + TEST_REQUIRE(kvm_has_cap(KVM_CAP_NESTED_STATE)); 86 + 87 + vm = vm_create_with_one_vcpu(&vcpu, guest_code); 88 + 89 + /* 90 + * L1 needs to read its own PML5 table to set up L2. Identity map 91 + * the PML5 table to facilitate this. 92 + */ 93 + virt_map(vm, vm->pgd, vm->pgd, 1); 94 + 95 + vcpu_alloc_vmx(vm, &vmx_pages_gva); 96 + vcpu_args_set(vcpu, 1, vmx_pages_gva); 97 + 98 + for (stage = 1;; stage++) { 99 + vcpu_run(vcpu); 100 + TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); 101 + 102 + switch (get_ucall(vcpu, &uc)) { 103 + case UCALL_ABORT: 104 + REPORT_GUEST_ASSERT(uc); 105 + /* NOT REACHED */ 106 + case UCALL_SYNC: 107 + break; 108 + case UCALL_DONE: 109 + goto done; 110 + default: 111 + TEST_FAIL("Unknown ucall %lu", uc.cmd); 112 + } 113 + 114 + TEST_ASSERT(uc.args[1] == stage, 115 + "Expected stage %d, got stage %lu", stage, (ulong)uc.args[1]); 116 + if (stage == 1) { 117 + pr_info("L2 is active; performing save/restore.\n"); 118 + state = vcpu_save_state(vcpu); 119 + 120 + kvm_vm_release(vm); 121 + 122 + /* Restore state in a new VM. */ 123 + vcpu = vm_recreate_with_one_vcpu(vm); 124 + vcpu_load_state(vcpu, state); 125 + kvm_x86_state_cleanup(state); 126 + } 127 + } 128 + 129 + done: 130 + kvm_vm_free(vm); 131 + return 0; 132 + }
+43 -5
tools/testing/selftests/kvm/x86/vmx_nested_tsc_scaling_test.c tools/testing/selftests/kvm/x86/nested_tsc_scaling_test.c
··· 13 13 14 14 #include "kvm_util.h" 15 15 #include "vmx.h" 16 + #include "svm_util.h" 16 17 #include "kselftest.h" 17 18 18 19 /* L2 is scaled up (from L1's perspective) by this factor */ ··· 80 79 __asm__ __volatile__("vmcall"); 81 80 } 82 81 83 - static void l1_guest_code(struct vmx_pages *vmx_pages) 82 + static void l1_svm_code(struct svm_test_data *svm) 83 + { 84 + unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 85 + 86 + /* check that L1's frequency looks alright before launching L2 */ 87 + check_tsc_freq(UCHECK_L1); 88 + 89 + generic_svm_setup(svm, l2_guest_code, 90 + &l2_guest_stack[L2_GUEST_STACK_SIZE]); 91 + 92 + /* enable TSC scaling for L2 */ 93 + wrmsr(MSR_AMD64_TSC_RATIO, L2_SCALE_FACTOR << 32); 94 + 95 + /* launch L2 */ 96 + run_guest(svm->vmcb, svm->vmcb_gpa); 97 + GUEST_ASSERT(svm->vmcb->control.exit_code == SVM_EXIT_VMMCALL); 98 + 99 + /* check that L1's frequency still looks good */ 100 + check_tsc_freq(UCHECK_L1); 101 + 102 + GUEST_DONE(); 103 + } 104 + 105 + static void l1_vmx_code(struct vmx_pages *vmx_pages) 84 106 { 85 107 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 86 108 uint32_t control; ··· 140 116 GUEST_DONE(); 141 117 } 142 118 119 + static void l1_guest_code(void *data) 120 + { 121 + if (this_cpu_has(X86_FEATURE_VMX)) 122 + l1_vmx_code(data); 123 + else 124 + l1_svm_code(data); 125 + } 126 + 143 127 int main(int argc, char *argv[]) 144 128 { 145 129 struct kvm_vcpu *vcpu; 146 130 struct kvm_vm *vm; 147 - vm_vaddr_t vmx_pages_gva; 131 + vm_vaddr_t guest_gva = 0; 148 132 149 133 uint64_t tsc_start, tsc_end; 150 134 uint64_t tsc_khz; ··· 161 129 uint64_t l1_tsc_freq = 0; 162 130 uint64_t l2_tsc_freq = 0; 163 131 164 - TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); 132 + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX) || 133 + kvm_cpu_has(X86_FEATURE_SVM)); 165 134 TEST_REQUIRE(kvm_has_cap(KVM_CAP_TSC_CONTROL)); 166 135 TEST_REQUIRE(sys_clocksource_is_based_on_tsc()); 167 136 ··· 185 152 printf("real TSC frequency is around: %"PRIu64"\n", l0_tsc_freq); 186 153 187 154 vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); 188 - vcpu_alloc_vmx(vm, &vmx_pages_gva); 189 - vcpu_args_set(vcpu, 1, vmx_pages_gva); 155 + 156 + if (kvm_cpu_has(X86_FEATURE_VMX)) 157 + vcpu_alloc_vmx(vm, &guest_gva); 158 + else 159 + vcpu_alloc_svm(vm, &guest_gva); 160 + 161 + vcpu_args_set(vcpu, 1, guest_gva); 190 162 191 163 tsc_khz = __vcpu_ioctl(vcpu, KVM_GET_TSC_KHZ, NULL); 192 164 TEST_ASSERT(tsc_khz != -1, "vcpu ioctl KVM_GET_TSC_KHZ failed");
+41 -32
tools/testing/selftests/kvm/x86/vmx_tsc_adjust_test.c tools/testing/selftests/kvm/x86/nested_tsc_adjust_test.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0-only 2 2 /* 3 - * vmx_tsc_adjust_test 4 - * 5 3 * Copyright (C) 2018, Google LLC. 6 4 * 7 5 * IA32_TSC_ADJUST test ··· 20 22 #include "kvm_util.h" 21 23 #include "processor.h" 22 24 #include "vmx.h" 25 + #include "svm_util.h" 23 26 24 27 #include <string.h> 25 28 #include <sys/ioctl.h> ··· 33 34 34 35 #define TSC_ADJUST_VALUE (1ll << 32) 35 36 #define TSC_OFFSET_VALUE -(1ll << 48) 37 + 38 + #define L2_GUEST_STACK_SIZE 64 36 39 37 40 enum { 38 41 PORT_ABORT = 0x1000, ··· 73 72 __asm__ __volatile__("vmcall"); 74 73 } 75 74 76 - static void l1_guest_code(struct vmx_pages *vmx_pages) 75 + static void l1_guest_code(void *data) 77 76 { 78 - #define L2_GUEST_STACK_SIZE 64 79 77 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; 80 - uint32_t control; 81 - uintptr_t save_cr3; 82 78 79 + /* Set TSC from L1 and make sure TSC_ADJUST is updated correctly */ 83 80 GUEST_ASSERT(rdtsc() < TSC_ADJUST_VALUE); 84 81 wrmsr(MSR_IA32_TSC, rdtsc() - TSC_ADJUST_VALUE); 85 82 check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE); 86 83 87 - GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); 88 - GUEST_ASSERT(load_vmcs(vmx_pages)); 84 + /* 85 + * Run L2 with TSC_OFFSET. L2 will write to TSC, and L1 is not 86 + * intercepting the write so it should update L1's TSC_ADJUST. 87 + */ 88 + if (this_cpu_has(X86_FEATURE_VMX)) { 89 + struct vmx_pages *vmx_pages = data; 90 + uint32_t control; 89 91 90 - /* Prepare the VMCS for L2 execution. */ 91 - prepare_vmcs(vmx_pages, l2_guest_code, 92 - &l2_guest_stack[L2_GUEST_STACK_SIZE]); 93 - control = vmreadz(CPU_BASED_VM_EXEC_CONTROL); 94 - control |= CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_USE_TSC_OFFSETTING; 95 - vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); 96 - vmwrite(TSC_OFFSET, TSC_OFFSET_VALUE); 92 + GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages)); 93 + GUEST_ASSERT(load_vmcs(vmx_pages)); 97 94 98 - /* Jump into L2. First, test failure to load guest CR3. */ 99 - save_cr3 = vmreadz(GUEST_CR3); 100 - vmwrite(GUEST_CR3, -1ull); 101 - GUEST_ASSERT(!vmlaunch()); 102 - GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == 103 - (EXIT_REASON_FAILED_VMENTRY | EXIT_REASON_INVALID_STATE)); 104 - check_ia32_tsc_adjust(-1 * TSC_ADJUST_VALUE); 105 - vmwrite(GUEST_CR3, save_cr3); 95 + prepare_vmcs(vmx_pages, l2_guest_code, 96 + &l2_guest_stack[L2_GUEST_STACK_SIZE]); 97 + control = vmreadz(CPU_BASED_VM_EXEC_CONTROL); 98 + control |= CPU_BASED_USE_MSR_BITMAPS | CPU_BASED_USE_TSC_OFFSETTING; 99 + vmwrite(CPU_BASED_VM_EXEC_CONTROL, control); 100 + vmwrite(TSC_OFFSET, TSC_OFFSET_VALUE); 106 101 107 - GUEST_ASSERT(!vmlaunch()); 108 - GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL); 102 + GUEST_ASSERT(!vmlaunch()); 103 + GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL); 104 + } else { 105 + struct svm_test_data *svm = data; 106 + 107 + generic_svm_setup(svm, l2_guest_code, 108 + &l2_guest_stack[L2_GUEST_STACK_SIZE]); 109 + 110 + svm->vmcb->control.tsc_offset = TSC_OFFSET_VALUE; 111 + run_guest(svm->vmcb, svm->vmcb_gpa); 112 + GUEST_ASSERT(svm->vmcb->control.exit_code == SVM_EXIT_VMMCALL); 113 + } 109 114 110 115 check_ia32_tsc_adjust(-2 * TSC_ADJUST_VALUE); 111 - 112 116 GUEST_DONE(); 113 117 } 114 118 ··· 125 119 126 120 int main(int argc, char *argv[]) 127 121 { 128 - vm_vaddr_t vmx_pages_gva; 122 + vm_vaddr_t nested_gva; 129 123 struct kvm_vcpu *vcpu; 130 124 131 - TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); 125 + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX) || 126 + kvm_cpu_has(X86_FEATURE_SVM)); 132 127 133 - vm = vm_create_with_one_vcpu(&vcpu, (void *) l1_guest_code); 128 + vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); 129 + if (kvm_cpu_has(X86_FEATURE_VMX)) 130 + vcpu_alloc_vmx(vm, &nested_gva); 131 + else 132 + vcpu_alloc_svm(vm, &nested_gva); 134 133 135 - /* Allocate VMX pages and shared descriptors (vmx_pages). */ 136 - vcpu_alloc_vmx(vm, &vmx_pages_gva); 137 - vcpu_args_set(vcpu, 1, vmx_pages_gva); 134 + vcpu_args_set(vcpu, 1, nested_gva); 138 135 139 136 for (;;) { 140 137 struct ucall uc;