1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * KVM dirty page logging test 4 * 5 * Copyright (C) 2018, Red Hat, Inc. 6 */ 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <linux/bitmap.h> 10 #include <linux/bitops.h> 11 12 #include "test_util.h" 13 #include "kvm_util.h" 14 #include "processor.h" 15 #include "svm_util.h" 16 #include "vmx.h" 17 18 /* The memory slot index to track dirty pages */ 19 #define TEST_MEM_SLOT_INDEX 1 20 21 /* 22 * Allocate four pages total. Two pages are used to verify that the KVM marks 23 * the accessed page/GFN as marked dirty, but not the "other" page. Times two 24 * so that each "normal" page can be accessed from L2 via an aliased L2 GVA+GPA 25 * (when TDP is enabled), to verify KVM marks _L1's_ page/GFN as dirty (to 26 * detect failures, L2 => L1 GPAs can't be identity mapped in the TDP page 27 * tables, as marking L2's GPA dirty would get a false pass if L1 == L2). 28 */ 29 #define TEST_MEM_PAGES 4 30 31 #define TEST_MEM_BASE 0xc0000000 32 #define TEST_MEM_ALIAS_BASE 0xc0002000 33 34 #define TEST_GUEST_ADDR(base, idx) ((base) + (idx) * PAGE_SIZE) 35 36 #define TEST_GVA(idx) TEST_GUEST_ADDR(TEST_MEM_BASE, idx) 37 #define TEST_GPA(idx) TEST_GUEST_ADDR(TEST_MEM_BASE, idx) 38 39 #define TEST_ALIAS_GPA(idx) TEST_GUEST_ADDR(TEST_MEM_ALIAS_BASE, idx) 40 41 #define TEST_HVA(vm, idx) addr_gpa2hva(vm, TEST_GPA(idx)) 42 43 /* Use the page offset bits to communicate the access+fault type. */ 44 #define TEST_SYNC_READ_FAULT BIT(0) 45 #define TEST_SYNC_WRITE_FAULT BIT(1) 46 #define TEST_SYNC_NO_FAULT BIT(2) 47 48 static void l2_guest_code(gva_t base) 49 { 50 gva_t page0 = TEST_GUEST_ADDR(base, 0); 51 gva_t page1 = TEST_GUEST_ADDR(base, 1); 52 53 READ_ONCE(*(u64 *)page0); 54 GUEST_SYNC(page0 | TEST_SYNC_READ_FAULT); 55 WRITE_ONCE(*(u64 *)page0, 1); 56 GUEST_SYNC(page0 | TEST_SYNC_WRITE_FAULT); 57 READ_ONCE(*(u64 *)page0); 58 GUEST_SYNC(page0 | TEST_SYNC_NO_FAULT); 59 60 WRITE_ONCE(*(u64 *)page1, 1); 61 GUEST_SYNC(page1 | TEST_SYNC_WRITE_FAULT); 62 WRITE_ONCE(*(u64 *)page1, 1); 63 GUEST_SYNC(page1 | TEST_SYNC_WRITE_FAULT); 64 READ_ONCE(*(u64 *)page1); 65 GUEST_SYNC(page1 | TEST_SYNC_NO_FAULT); 66 67 /* Exit to L1 and never come back. */ 68 vmcall(); 69 } 70 71 static void l2_guest_code_tdp_enabled(void) 72 { 73 /* 74 * Use the aliased virtual addresses when running with TDP to verify 75 * that KVM correctly handles the case where a page is dirtied via a 76 * different GPA than would be used by L1. 77 */ 78 l2_guest_code(TEST_MEM_ALIAS_BASE); 79 } 80 81 static void l2_guest_code_tdp_disabled(void) 82 { 83 /* 84 * Use the "normal" virtual addresses when running without TDP enabled, 85 * in which case L2 will use the same page tables as L1, and thus needs 86 * to use the same virtual addresses that are mapped into L1. 87 */ 88 l2_guest_code(TEST_MEM_BASE); 89 } 90 91 void l1_vmx_code(struct vmx_pages *vmx) 92 { 93 void *l2_rip; 94 95 GUEST_ASSERT(vmx->vmcs_gpa); 96 GUEST_ASSERT(prepare_for_vmx_operation(vmx)); 97 GUEST_ASSERT(load_vmcs(vmx)); 98 99 if (vmx->eptp_gpa) 100 l2_rip = l2_guest_code_tdp_enabled; 101 else 102 l2_rip = l2_guest_code_tdp_disabled; 103 104 prepare_vmcs(vmx, l2_rip); 105 106 GUEST_SYNC(TEST_SYNC_NO_FAULT); 107 GUEST_ASSERT(!vmlaunch()); 108 GUEST_SYNC(TEST_SYNC_NO_FAULT); 109 GUEST_ASSERT_EQ(vmreadz(VM_EXIT_REASON), EXIT_REASON_VMCALL); 110 GUEST_DONE(); 111 } 112 113 static void l1_svm_code(struct svm_test_data *svm) 114 { 115 void *l2_rip; 116 117 if (svm->ncr3_gpa) 118 l2_rip = l2_guest_code_tdp_enabled; 119 else 120 l2_rip = l2_guest_code_tdp_disabled; 121 122 generic_svm_setup(svm, l2_rip); 123 124 GUEST_SYNC(TEST_SYNC_NO_FAULT); 125 run_guest(svm->vmcb, svm->vmcb_gpa); 126 GUEST_SYNC(TEST_SYNC_NO_FAULT); 127 GUEST_ASSERT_EQ(svm->vmcb->control.exit_code, SVM_EXIT_VMMCALL); 128 GUEST_DONE(); 129 } 130 131 static void l1_guest_code(void *data) 132 { 133 if (this_cpu_has(X86_FEATURE_VMX)) 134 l1_vmx_code(data); 135 else 136 l1_svm_code(data); 137 } 138 139 static void test_handle_ucall_sync(struct kvm_vm *vm, u64 arg, 140 unsigned long *bmap) 141 { 142 gva_t gva = arg & ~(PAGE_SIZE - 1); 143 int page_nr, i; 144 145 /* 146 * Extract the page number of underlying physical page, which is also 147 * the _L1_ page number. The dirty bitmap _must_ be updated based on 148 * the L1 GPA, not L2 GPA, i.e. whether or not L2 used an aliased GPA 149 * (i.e. if TDP enabled for L2) is irrelevant with respect to the dirty 150 * bitmap and which underlying physical page is accessed. 151 * 152 * Note, gva will be '0' if there was no access, i.e. if the purpose of 153 * the sync is to verify all pages are clean. 154 */ 155 if (!gva) 156 page_nr = 0; 157 else if (gva >= TEST_MEM_ALIAS_BASE) 158 page_nr = (gva - TEST_MEM_ALIAS_BASE) >> PAGE_SHIFT; 159 else 160 page_nr = (gva - TEST_MEM_BASE) >> PAGE_SHIFT; 161 TEST_ASSERT(page_nr == 0 || page_nr == 1, 162 "Test bug, unexpected frame number '%u' for arg = %lx", page_nr, arg); 163 TEST_ASSERT(gva || (arg & TEST_SYNC_NO_FAULT), 164 "Test bug, gva must be valid if a fault is expected"); 165 166 kvm_vm_get_dirty_log(vm, TEST_MEM_SLOT_INDEX, bmap); 167 168 /* 169 * Check all pages to verify the correct physical page was modified (or 170 * not), and that all pages are clean/dirty as expected. 171 * 172 * If a fault of any kind is expected, the target page should be dirty 173 * as the Dirty bit is set in the gPTE. KVM should create a writable 174 * SPTE even on a read fault, *and* KVM must mark the GFN as dirty 175 * when doing so. 176 */ 177 for (i = 0; i < TEST_MEM_PAGES; i++) { 178 if (i == page_nr && (arg & TEST_SYNC_WRITE_FAULT)) 179 TEST_ASSERT(*(u64 *)TEST_HVA(vm, i) == 1, 180 "Page %u incorrectly not written by guest", i); 181 else 182 TEST_ASSERT(*(u64 *)TEST_HVA(vm, i) == 0xaaaaaaaaaaaaaaaaULL, 183 "Page %u incorrectly written by guest", i); 184 185 if (i == page_nr && !(arg & TEST_SYNC_NO_FAULT)) 186 TEST_ASSERT(test_bit(i, bmap), 187 "Page %u incorrectly reported clean on %s fault", 188 i, arg & TEST_SYNC_READ_FAULT ? "read" : "write"); 189 else 190 TEST_ASSERT(!test_bit(i, bmap), 191 "Page %u incorrectly reported dirty", i); 192 } 193 } 194 195 static void test_dirty_log(bool nested_tdp) 196 { 197 gva_t nested_gva = 0; 198 unsigned long *bmap; 199 struct kvm_vcpu *vcpu; 200 struct kvm_vm *vm; 201 struct ucall uc; 202 bool done = false; 203 204 pr_info("Nested TDP: %s\n", nested_tdp ? "enabled" : "disabled"); 205 206 /* Create VM */ 207 vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); 208 if (nested_tdp) 209 vm_enable_tdp(vm); 210 211 if (kvm_cpu_has(X86_FEATURE_VMX)) 212 vcpu_alloc_vmx(vm, &nested_gva); 213 else 214 vcpu_alloc_svm(vm, &nested_gva); 215 216 vcpu_args_set(vcpu, 1, nested_gva); 217 218 /* Add an extra memory slot for testing dirty logging */ 219 vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 220 TEST_MEM_BASE, 221 TEST_MEM_SLOT_INDEX, 222 TEST_MEM_PAGES, 223 KVM_MEM_LOG_DIRTY_PAGES); 224 225 /* 226 * Add an identity map for GVA range [0xc0000000, 0xc0004000). This 227 * affects both L1 and L2. However... 228 */ 229 virt_map(vm, TEST_MEM_BASE, TEST_MEM_BASE, TEST_MEM_PAGES); 230 231 /* 232 * ... pages in the L2 GPA address range [0xc0002000, 0xc0004000) will 233 * map to [0xc0000000, 0xc0002000) when TDP is enabled (for L2). 234 * 235 * When TDP is disabled, the L2 guest code will still access the same L1 236 * GPAs as the TDP enabled case. 237 * 238 * Set the Dirty bit in the PTEs used by L2 so that KVM will create 239 * writable SPTEs when handling read faults (if the Dirty bit isn't 240 * set, KVM must intercept the next write to emulate the Dirty bit 241 * update). 242 */ 243 if (nested_tdp) { 244 tdp_identity_map_default_memslots(vm); 245 tdp_map(vm, TEST_ALIAS_GPA(0), TEST_GPA(0), PAGE_SIZE); 246 tdp_map(vm, TEST_ALIAS_GPA(1), TEST_GPA(1), PAGE_SIZE); 247 248 *tdp_get_pte(vm, TEST_ALIAS_GPA(0)) |= PTE_DIRTY_MASK(&vm->stage2_mmu); 249 *tdp_get_pte(vm, TEST_ALIAS_GPA(1)) |= PTE_DIRTY_MASK(&vm->stage2_mmu); 250 } else { 251 *vm_get_pte(vm, TEST_GVA(0)) |= PTE_DIRTY_MASK(&vm->mmu); 252 *vm_get_pte(vm, TEST_GVA(1)) |= PTE_DIRTY_MASK(&vm->mmu); 253 } 254 255 bmap = bitmap_zalloc(TEST_MEM_PAGES); 256 257 while (!done) { 258 memset(TEST_HVA(vm, 0), 0xaa, TEST_MEM_PAGES * PAGE_SIZE); 259 260 vcpu_run(vcpu); 261 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO); 262 263 switch (get_ucall(vcpu, &uc)) { 264 case UCALL_ABORT: 265 REPORT_GUEST_ASSERT(uc); 266 /* NOT REACHED */ 267 case UCALL_SYNC: 268 test_handle_ucall_sync(vm, uc.args[1], bmap); 269 break; 270 case UCALL_DONE: 271 done = true; 272 break; 273 default: 274 TEST_FAIL("Unknown ucall %lu", uc.cmd); 275 } 276 } 277 } 278 279 int main(int argc, char *argv[]) 280 { 281 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX) || kvm_cpu_has(X86_FEATURE_SVM)); 282 283 test_dirty_log(/*nested_tdp=*/false); 284 285 if (kvm_cpu_has_tdp()) 286 test_dirty_log(/*nested_tdp=*/true); 287 288 return 0; 289 } 290