xref: /linux/tools/testing/selftests/kvm/x86/nested_dirty_log_test.c (revision 67f8bc848ee31831336bd478e57d2f993551902e)
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