1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <errno.h> 6 #include <sys/types.h> 7 #include <time.h> 8 #include <pthread.h> 9 #include <signal.h> 10 #include <unistd.h> 11 #include <getopt.h> 12 13 #include "test_util.h" 14 #include "kvm_util.h" 15 #include "processor.h" 16 #include "svm_util.h" 17 #include "vmx.h" 18 19 #define NR_ITERATIONS 500 20 21 #define PTRS_PER_PTE 512 22 #define PXD_INDEX(vaddr, level) (((vaddr) >> PG_LEVEL_SHIFT(level)) & (PTRS_PER_PTE - 1)) 23 24 #define TEST_MEM_BASE_GVA 0xc0000000ULL 25 #define TEST_PGTABLE_GVA_OFFSET 0xd0000000ULL 26 #define PATTERN 0xabcdefabcdefabcdULL 27 28 static u64 expected_vaddr; 29 static u64 guest_faults; 30 31 static u64 *guest_get_pte(u64 vaddr) 32 { 33 u64 pgtable_pa, pte; 34 u64 *pgtable; 35 int level; 36 37 level = (get_cr4() & X86_CR4_LA57) ? PG_LEVEL_256T : PG_LEVEL_512G; 38 39 pgtable_pa = get_cr3() & PHYSICAL_PAGE_MASK; 40 for (; level > PG_LEVEL_4K; level--) { 41 pgtable = (u64 *)(pgtable_pa + TEST_PGTABLE_GVA_OFFSET); 42 pte = pgtable[PXD_INDEX(vaddr, level)]; 43 GUEST_ASSERT(pte & PTE_PRESENT_MASK(&guest_mmu)); 44 GUEST_ASSERT(!(pte & PTE_HUGE_MASK(&guest_mmu))); 45 pgtable_pa = PTE_GET_PA(pte); 46 } 47 48 pgtable = (u64 *)(pgtable_pa + TEST_PGTABLE_GVA_OFFSET); 49 return &pgtable[PXD_INDEX(vaddr, PG_LEVEL_4K)]; 50 } 51 52 static void guest_pf_handler(struct ex_regs *regs) 53 { 54 u64 fault_addr; 55 u64 *ptep; 56 57 fault_addr = get_cr2(); 58 GUEST_ASSERT_EQ(fault_addr, READ_ONCE(expected_vaddr)); 59 60 ptep = guest_get_pte(fault_addr); 61 GUEST_ASSERT(ptep); 62 GUEST_ASSERT(!(*ptep & PTE_PRESENT_MASK(&guest_mmu))); 63 64 *ptep |= PTE_PRESENT_MASK(&guest_mmu); 65 guest_faults++; 66 } 67 68 static void guest_access_memory(void *arg) 69 { 70 u64 vaddr, val; 71 int i; 72 73 for (i = 0; ; i++) { 74 vaddr = TEST_MEM_BASE_GVA + (i % PTRS_PER_PTE) * PAGE_SIZE; 75 WRITE_ONCE(expected_vaddr, vaddr); 76 77 /* Read to trigger #PF */ 78 val = READ_ONCE(*(u64 *)vaddr); 79 GUEST_ASSERT_EQ(val, PATTERN); 80 81 /* Clear the present bit again so it faults next time */ 82 *guest_get_pte(vaddr) &= ~PTE_PRESENT_MASK(&guest_mmu); 83 invlpg(vaddr); 84 } 85 } 86 87 static void l1_svm_code(struct svm_test_data *svm) 88 { 89 generic_svm_setup(svm, guest_access_memory); 90 svm->vmcb->control.intercept_exceptions |= BIT(UD_VECTOR); 91 92 while (1) { 93 run_guest(svm->vmcb, svm->vmcb_gpa); 94 GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, 95 (SVM_EXIT_EXCP_BASE + UD_VECTOR)); 96 } 97 } 98 99 static void l1_vmx_code(struct vmx_pages *vmx) 100 { 101 GUEST_ASSERT(prepare_for_vmx_operation(vmx)); 102 GUEST_ASSERT(load_vmcs(vmx)); 103 prepare_vmcs(vmx, guest_access_memory); 104 105 GUEST_ASSERT(!vmwrite(EXCEPTION_BITMAP, BIT(UD_VECTOR))); 106 107 GUEST_ASSERT(!vmlaunch()); 108 while (1) { 109 GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_EXCEPTION_NMI); 110 GUEST_ASSERT_EQ(vmreadz(VM_EXIT_INTR_INFO) & 0xff, UD_VECTOR); 111 GUEST_ASSERT(!vmresume()); 112 } 113 } 114 115 static void l1_guest_code(void *test_data) 116 { 117 if (this_cpu_has(X86_FEATURE_SVM)) 118 l1_svm_code(test_data); 119 else 120 l1_vmx_code(test_data); 121 } 122 123 static void *sigusr_thread_fn(void *arg) 124 { 125 pthread_t vcpu_thread = (pthread_t)arg; 126 127 for (;;) { 128 pthread_testcancel(); 129 pthread_kill(vcpu_thread, SIGUSR1); 130 usleep(msecs_to_usecs(1)); 131 } 132 return NULL; 133 } 134 135 static void dummy_signal_handler(int signo) {} 136 static struct sigaction sa; 137 138 static void vcpu_sigusr_listen(void) 139 { 140 sa.sa_handler = dummy_signal_handler; 141 sigaction(SIGUSR1, &sa, NULL); 142 } 143 144 static void vcpu_sigusr_ignore(void) 145 { 146 sa.sa_handler = SIG_IGN; 147 sigaction(SIGUSR1, &sa, NULL); 148 } 149 150 static void kvm_x86_state_queue_ud(struct kvm_x86_state *state) 151 { 152 if (state->events.exception.pending || state->events.exception.injected) 153 return; 154 155 state->events.flags |= KVM_VCPUEVENT_VALID_PAYLOAD; 156 state->events.exception.pending = true; 157 state->events.exception.injected = false; 158 state->events.exception.nr = UD_VECTOR; 159 state->events.exception.has_error_code = false; 160 state->events.exception_has_payload = false; 161 } 162 163 static void run_test(bool nested) 164 { 165 struct kvm_x86_state *state; 166 int r, i, level; 167 pthread_t sigusr_thread; 168 gpa_t gpa, pgtable_gpa; 169 struct kvm_vcpu *vcpu; 170 struct kvm_vm *vm; 171 struct ucall uc; 172 u64 *pgtable; 173 gva_t gva; 174 u64 pte; 175 176 vm = vm_create_with_one_vcpu(&vcpu, nested ? l1_guest_code : guest_access_memory); 177 vm_install_exception_handler(vm, PF_VECTOR, guest_pf_handler); 178 179 if (nested) { 180 vm_enable_cap(vm, KVM_CAP_EXCEPTION_PAYLOAD, -2ul); 181 if (kvm_cpu_has(X86_FEATURE_SVM)) 182 vcpu_alloc_svm(vm, &gva); 183 else 184 vcpu_alloc_vmx(vm, &gva); 185 vcpu_args_set(vcpu, 1, gva); 186 } 187 188 /* Allocate a page and write the pattern to it */ 189 gva = vm_alloc_page(vm); 190 *(u64 *)addr_gva2hva(vm, gva) = PATTERN; 191 gpa = addr_gva2gpa(vm, gva); 192 193 /* 194 * Map all virtual addresses to the pattern page and clear the present 195 * bit such that guest accesses will cause a #PF. 196 */ 197 for (i = 0; i < PTRS_PER_PTE; i++) { 198 gva = TEST_MEM_BASE_GVA + i * getpagesize(); 199 virt_pg_map(vm, gva, gpa); 200 *vm_get_pte(vm, gva) &= ~PTE_PRESENT_MASK(&vm->mmu); 201 } 202 203 /* 204 * Now create mappings for the page tables created above so that the 205 * guest #PF handler can walk them. All PTEs for test virtual addresses 206 * should lie on the same PTE page, so one page is mapped for each page 207 * table level. 208 * 209 * Use an offset for the GVA instead of creating identity mappings to 210 * avoid collision with existing mappings at low GVAs (e.g. ELF). 211 */ 212 pgtable_gpa = vm->mmu.pgd; 213 for (level = vm->mmu.pgtable_levels; level >= PG_LEVEL_4K; level--) { 214 virt_map(vm, pgtable_gpa + TEST_PGTABLE_GVA_OFFSET, pgtable_gpa, 1); 215 pgtable = addr_gpa2hva(vm, pgtable_gpa); 216 pte = pgtable[PXD_INDEX(TEST_MEM_BASE_GVA, level)]; 217 pgtable_gpa = PTE_GET_PA(pte); 218 } 219 220 /* Initialize the thread sending SIGUSR and install the handler */ 221 vcpu_sigusr_ignore(); 222 r = pthread_create(&sigusr_thread, NULL, sigusr_thread_fn, 223 (void *)pthread_self()); 224 TEST_ASSERT(!r, "pthread_create() failed: %d", r); 225 226 for (i = 1; i <= NR_ITERATIONS; i++) { 227 /* 228 * Only handle SIGUSR while the vCPU is running, otherwise 229 * ignore it to avoid interrupting other ioctls/syscalls. 230 */ 231 vcpu_sigusr_listen(); 232 r = __vcpu_run(vcpu); 233 TEST_ASSERT(!r || errno == EINTR, "Expected success or SIGUSR1"); 234 vcpu_sigusr_ignore(); 235 236 /* The guest only exits due to a signal or failed assertion */ 237 if (!r) { 238 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); 239 TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_ABORT); 240 REPORT_GUEST_ASSERT(uc); 241 break; 242 } 243 244 state = vcpu_save_state(vcpu); 245 246 /* 247 * If the vCPU is in guest mode, inject a #UD to trigger an 248 * L2->L1 VM-Exit every other iteration. 249 */ 250 if (kvm_x86_state_is_guest_mode(state) && i % 2 == 0) 251 kvm_x86_state_queue_ud(state); 252 253 kvm_vm_release(vm); 254 vcpu = vm_recreate_with_one_vcpu(vm); 255 if (nested) 256 vm_enable_cap(vm, KVM_CAP_EXCEPTION_PAYLOAD, -2ul); 257 vcpu_load_state(vcpu, state); 258 kvm_x86_state_cleanup(state); 259 260 pr_info("\rSave+restore iterations: %d", i); 261 } 262 pr_info("\n"); 263 264 sync_global_from_guest(vm, guest_faults); 265 TEST_ASSERT(guest_faults, "No guest page faults triggered"); 266 pr_info("Guest page faults%s: %lu\n", nested ? " (in L2)" : "", guest_faults); 267 268 pthread_cancel(sigusr_thread); 269 pthread_join(sigusr_thread, NULL); 270 kvm_vm_free(vm); 271 } 272 273 int main(int argc, char *argv[]) 274 { 275 pr_info("Running save+restore stress test...\n"); 276 run_test(/*nested=*/false); 277 278 if (!kvm_has_cap(KVM_CAP_EXCEPTION_PAYLOAD) || 279 !kvm_has_cap(KVM_CAP_NESTED_STATE) || 280 (!kvm_cpu_has(X86_FEATURE_SVM) && !kvm_cpu_has(X86_FEATURE_VMX))) { 281 pr_info("Nested virtualization not supported, skipping nested test\n"); 282 return 0; 283 } 284 285 pr_info("Running save+restore stress test with a nested guest...\n"); 286 run_test(/*nested=*/true); 287 return 0; 288 } 289