xref: /openbmc/linux/tools/testing/selftests/kvm/s390x/cmma_test.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1e325ba22SNico Boehr // SPDX-License-Identifier: GPL-2.0-only
2e325ba22SNico Boehr /*
3e325ba22SNico Boehr  * Test for s390x CMMA migration
4e325ba22SNico Boehr  *
5e325ba22SNico Boehr  * Copyright IBM Corp. 2023
6e325ba22SNico Boehr  *
7e325ba22SNico Boehr  * Authors:
8e325ba22SNico Boehr  *  Nico Boehr <nrb@linux.ibm.com>
9e325ba22SNico Boehr  */
10e325ba22SNico Boehr 
11e325ba22SNico Boehr #define _GNU_SOURCE /* for program_invocation_short_name */
12e325ba22SNico Boehr #include <fcntl.h>
13e325ba22SNico Boehr #include <stdio.h>
14e325ba22SNico Boehr #include <stdlib.h>
15e325ba22SNico Boehr #include <string.h>
16e325ba22SNico Boehr #include <sys/ioctl.h>
17e325ba22SNico Boehr 
18e325ba22SNico Boehr #include "test_util.h"
19e325ba22SNico Boehr #include "kvm_util.h"
20e325ba22SNico Boehr #include "kselftest.h"
21e325ba22SNico Boehr 
22e325ba22SNico Boehr #define MAIN_PAGE_COUNT 512
23e325ba22SNico Boehr 
24e325ba22SNico Boehr #define TEST_DATA_PAGE_COUNT 512
25e325ba22SNico Boehr #define TEST_DATA_MEMSLOT 1
26e325ba22SNico Boehr #define TEST_DATA_START_GFN 4096
27e325ba22SNico Boehr 
28e325ba22SNico Boehr #define TEST_DATA_TWO_PAGE_COUNT 256
29e325ba22SNico Boehr #define TEST_DATA_TWO_MEMSLOT 2
30e325ba22SNico Boehr #define TEST_DATA_TWO_START_GFN 8192
31e325ba22SNico Boehr 
32e325ba22SNico Boehr static char cmma_value_buf[MAIN_PAGE_COUNT + TEST_DATA_PAGE_COUNT];
33e325ba22SNico Boehr 
34e325ba22SNico Boehr /**
35e325ba22SNico Boehr  * Dirty CMMA attributes of exactly one page in the TEST_DATA memslot,
36e325ba22SNico Boehr  * so use_cmma goes on and the CMMA related ioctls do something.
37e325ba22SNico Boehr  */
guest_do_one_essa(void)38e325ba22SNico Boehr static void guest_do_one_essa(void)
39e325ba22SNico Boehr {
40e325ba22SNico Boehr 	asm volatile(
41e325ba22SNico Boehr 		/* load TEST_DATA_START_GFN into r1 */
42e325ba22SNico Boehr 		"	llilf 1,%[start_gfn]\n"
43e325ba22SNico Boehr 		/* calculate the address from the gfn */
44e325ba22SNico Boehr 		"	sllg 1,1,12(0)\n"
45e325ba22SNico Boehr 		/* set the first page in TEST_DATA memslot to STABLE */
46e325ba22SNico Boehr 		"	.insn rrf,0xb9ab0000,2,1,1,0\n"
47e325ba22SNico Boehr 		/* hypercall */
48e325ba22SNico Boehr 		"	diag 0,0,0x501\n"
49e325ba22SNico Boehr 		"0:	j 0b"
50e325ba22SNico Boehr 		:
51e325ba22SNico Boehr 		: [start_gfn] "L"(TEST_DATA_START_GFN)
52e325ba22SNico Boehr 		: "r1", "r2", "memory", "cc"
53e325ba22SNico Boehr 	);
54e325ba22SNico Boehr }
55e325ba22SNico Boehr 
56e325ba22SNico Boehr /**
57e325ba22SNico Boehr  * Touch CMMA attributes of all pages in TEST_DATA memslot. Set them to stable
58e325ba22SNico Boehr  * state.
59e325ba22SNico Boehr  */
guest_dirty_test_data(void)60e325ba22SNico Boehr static void guest_dirty_test_data(void)
61e325ba22SNico Boehr {
62e325ba22SNico Boehr 	asm volatile(
63e325ba22SNico Boehr 		/* r1 = TEST_DATA_START_GFN */
64e325ba22SNico Boehr 		"	xgr 1,1\n"
65e325ba22SNico Boehr 		"	llilf 1,%[start_gfn]\n"
66e325ba22SNico Boehr 		/* r5 = TEST_DATA_PAGE_COUNT */
67e325ba22SNico Boehr 		"	lghi 5,%[page_count]\n"
68e325ba22SNico Boehr 		/* r5 += r1 */
69e325ba22SNico Boehr 		"2:	agfr 5,1\n"
70e325ba22SNico Boehr 		/* r2 = r1 << 12 */
71e325ba22SNico Boehr 		"1:	sllg 2,1,12(0)\n"
72e325ba22SNico Boehr 		/* essa(r4, r2, SET_STABLE) */
73e325ba22SNico Boehr 		"	.insn rrf,0xb9ab0000,4,2,1,0\n"
74e325ba22SNico Boehr 		/* i++ */
75e325ba22SNico Boehr 		"	agfi 1,1\n"
76e325ba22SNico Boehr 		/* if r1 < r5 goto 1 */
77e325ba22SNico Boehr 		"	cgrjl 1,5,1b\n"
78e325ba22SNico Boehr 		/* hypercall */
79e325ba22SNico Boehr 		"	diag 0,0,0x501\n"
80e325ba22SNico Boehr 		"0:	j 0b"
81e325ba22SNico Boehr 		:
82e325ba22SNico Boehr 		: [start_gfn] "L"(TEST_DATA_START_GFN),
83e325ba22SNico Boehr 		  [page_count] "L"(TEST_DATA_PAGE_COUNT)
84e325ba22SNico Boehr 		:
85e325ba22SNico Boehr 			/* the counter in our loop over the pages */
86e325ba22SNico Boehr 			"r1",
87e325ba22SNico Boehr 			/* the calculated page physical address */
88e325ba22SNico Boehr 			"r2",
89e325ba22SNico Boehr 			/* ESSA output register */
90e325ba22SNico Boehr 			"r4",
91e325ba22SNico Boehr 			/* last page */
92e325ba22SNico Boehr 			"r5",
93e325ba22SNico Boehr 			"cc", "memory"
94e325ba22SNico Boehr 	);
95e325ba22SNico Boehr }
96e325ba22SNico Boehr 
create_vm(void)97e325ba22SNico Boehr static struct kvm_vm *create_vm(void)
98e325ba22SNico Boehr {
99e325ba22SNico Boehr 	return ____vm_create(VM_MODE_DEFAULT);
100e325ba22SNico Boehr }
101e325ba22SNico Boehr 
create_main_memslot(struct kvm_vm * vm)102e325ba22SNico Boehr static void create_main_memslot(struct kvm_vm *vm)
103e325ba22SNico Boehr {
104e325ba22SNico Boehr 	int i;
105e325ba22SNico Boehr 
106e325ba22SNico Boehr 	vm_userspace_mem_region_add(vm, VM_MEM_SRC_ANONYMOUS, 0, 0, MAIN_PAGE_COUNT, 0);
107e325ba22SNico Boehr 	/* set the array of memslots to zero like __vm_create does */
108e325ba22SNico Boehr 	for (i = 0; i < NR_MEM_REGIONS; i++)
109e325ba22SNico Boehr 		vm->memslots[i] = 0;
110e325ba22SNico Boehr }
111e325ba22SNico Boehr 
create_test_memslot(struct kvm_vm * vm)112e325ba22SNico Boehr static void create_test_memslot(struct kvm_vm *vm)
113e325ba22SNico Boehr {
114e325ba22SNico Boehr 	vm_userspace_mem_region_add(vm,
115e325ba22SNico Boehr 				    VM_MEM_SRC_ANONYMOUS,
116e325ba22SNico Boehr 				    TEST_DATA_START_GFN << vm->page_shift,
117e325ba22SNico Boehr 				    TEST_DATA_MEMSLOT,
118e325ba22SNico Boehr 				    TEST_DATA_PAGE_COUNT,
119e325ba22SNico Boehr 				    0
120e325ba22SNico Boehr 				   );
121e325ba22SNico Boehr 	vm->memslots[MEM_REGION_TEST_DATA] = TEST_DATA_MEMSLOT;
122e325ba22SNico Boehr }
123e325ba22SNico Boehr 
create_memslots(struct kvm_vm * vm)124e325ba22SNico Boehr static void create_memslots(struct kvm_vm *vm)
125e325ba22SNico Boehr {
126e325ba22SNico Boehr 	/*
127e325ba22SNico Boehr 	 * Our VM has the following memory layout:
128e325ba22SNico Boehr 	 * +------+---------------------------+
129e325ba22SNico Boehr 	 * | GFN  | Memslot                   |
130e325ba22SNico Boehr 	 * +------+---------------------------+
131e325ba22SNico Boehr 	 * | 0    |                           |
132e325ba22SNico Boehr 	 * | ...  | MAIN (Code, Stack, ...)   |
133e325ba22SNico Boehr 	 * | 511  |                           |
134e325ba22SNico Boehr 	 * +------+---------------------------+
135e325ba22SNico Boehr 	 * | 4096 |                           |
136e325ba22SNico Boehr 	 * | ...  | TEST_DATA                 |
137e325ba22SNico Boehr 	 * | 4607 |                           |
138e325ba22SNico Boehr 	 * +------+---------------------------+
139e325ba22SNico Boehr 	 */
140e325ba22SNico Boehr 	create_main_memslot(vm);
141e325ba22SNico Boehr 	create_test_memslot(vm);
142e325ba22SNico Boehr }
143e325ba22SNico Boehr 
finish_vm_setup(struct kvm_vm * vm)144e325ba22SNico Boehr static void finish_vm_setup(struct kvm_vm *vm)
145e325ba22SNico Boehr {
146e325ba22SNico Boehr 	struct userspace_mem_region *slot0;
147e325ba22SNico Boehr 
148e325ba22SNico Boehr 	kvm_vm_elf_load(vm, program_invocation_name);
149e325ba22SNico Boehr 
150e325ba22SNico Boehr 	slot0 = memslot2region(vm, 0);
151e325ba22SNico Boehr 	ucall_init(vm, slot0->region.guest_phys_addr + slot0->region.memory_size);
152e325ba22SNico Boehr 
153e325ba22SNico Boehr 	kvm_arch_vm_post_create(vm);
154e325ba22SNico Boehr }
155e325ba22SNico Boehr 
create_vm_two_memslots(void)156e325ba22SNico Boehr static struct kvm_vm *create_vm_two_memslots(void)
157e325ba22SNico Boehr {
158e325ba22SNico Boehr 	struct kvm_vm *vm;
159e325ba22SNico Boehr 
160e325ba22SNico Boehr 	vm = create_vm();
161e325ba22SNico Boehr 
162e325ba22SNico Boehr 	create_memslots(vm);
163e325ba22SNico Boehr 
164e325ba22SNico Boehr 	finish_vm_setup(vm);
165e325ba22SNico Boehr 
166e325ba22SNico Boehr 	return vm;
167e325ba22SNico Boehr }
168e325ba22SNico Boehr 
enable_cmma(struct kvm_vm * vm)169e325ba22SNico Boehr static void enable_cmma(struct kvm_vm *vm)
170e325ba22SNico Boehr {
171e325ba22SNico Boehr 	int r;
172e325ba22SNico Boehr 
173e325ba22SNico Boehr 	r = __kvm_device_attr_set(vm->fd, KVM_S390_VM_MEM_CTRL, KVM_S390_VM_MEM_ENABLE_CMMA, NULL);
174e325ba22SNico Boehr 	TEST_ASSERT(!r, "enabling cmma failed r=%d errno=%d", r, errno);
175e325ba22SNico Boehr }
176e325ba22SNico Boehr 
enable_dirty_tracking(struct kvm_vm * vm)177e325ba22SNico Boehr static void enable_dirty_tracking(struct kvm_vm *vm)
178e325ba22SNico Boehr {
179e325ba22SNico Boehr 	vm_mem_region_set_flags(vm, 0, KVM_MEM_LOG_DIRTY_PAGES);
180e325ba22SNico Boehr 	vm_mem_region_set_flags(vm, TEST_DATA_MEMSLOT, KVM_MEM_LOG_DIRTY_PAGES);
181e325ba22SNico Boehr }
182e325ba22SNico Boehr 
__enable_migration_mode(struct kvm_vm * vm)183e325ba22SNico Boehr static int __enable_migration_mode(struct kvm_vm *vm)
184e325ba22SNico Boehr {
185e325ba22SNico Boehr 	return __kvm_device_attr_set(vm->fd,
186e325ba22SNico Boehr 				     KVM_S390_VM_MIGRATION,
187e325ba22SNico Boehr 				     KVM_S390_VM_MIGRATION_START,
188e325ba22SNico Boehr 				     NULL
189e325ba22SNico Boehr 				    );
190e325ba22SNico Boehr }
191e325ba22SNico Boehr 
enable_migration_mode(struct kvm_vm * vm)192e325ba22SNico Boehr static void enable_migration_mode(struct kvm_vm *vm)
193e325ba22SNico Boehr {
194e325ba22SNico Boehr 	int r = __enable_migration_mode(vm);
195e325ba22SNico Boehr 
196e325ba22SNico Boehr 	TEST_ASSERT(!r, "enabling migration mode failed r=%d errno=%d", r, errno);
197e325ba22SNico Boehr }
198e325ba22SNico Boehr 
is_migration_mode_on(struct kvm_vm * vm)199e325ba22SNico Boehr static bool is_migration_mode_on(struct kvm_vm *vm)
200e325ba22SNico Boehr {
201e325ba22SNico Boehr 	u64 out;
202e325ba22SNico Boehr 	int r;
203e325ba22SNico Boehr 
204e325ba22SNico Boehr 	r = __kvm_device_attr_get(vm->fd,
205e325ba22SNico Boehr 				  KVM_S390_VM_MIGRATION,
206e325ba22SNico Boehr 				  KVM_S390_VM_MIGRATION_STATUS,
207e325ba22SNico Boehr 				  &out
208e325ba22SNico Boehr 				 );
209e325ba22SNico Boehr 	TEST_ASSERT(!r, "getting migration mode status failed r=%d errno=%d", r, errno);
210e325ba22SNico Boehr 	return out;
211e325ba22SNico Boehr }
212e325ba22SNico Boehr 
vm_get_cmma_bits(struct kvm_vm * vm,u64 flags,int * errno_out)213e325ba22SNico Boehr static int vm_get_cmma_bits(struct kvm_vm *vm, u64 flags, int *errno_out)
214e325ba22SNico Boehr {
215e325ba22SNico Boehr 	struct kvm_s390_cmma_log args;
216e325ba22SNico Boehr 	int rc;
217e325ba22SNico Boehr 
218e325ba22SNico Boehr 	errno = 0;
219e325ba22SNico Boehr 
220e325ba22SNico Boehr 	args = (struct kvm_s390_cmma_log){
221e325ba22SNico Boehr 		.start_gfn = 0,
222e325ba22SNico Boehr 		.count = sizeof(cmma_value_buf),
223e325ba22SNico Boehr 		.flags = flags,
224e325ba22SNico Boehr 		.values = (__u64)&cmma_value_buf[0]
225e325ba22SNico Boehr 	};
226e325ba22SNico Boehr 	rc = __vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args);
227e325ba22SNico Boehr 
228e325ba22SNico Boehr 	*errno_out = errno;
229e325ba22SNico Boehr 	return rc;
230e325ba22SNico Boehr }
231e325ba22SNico Boehr 
test_get_cmma_basic(void)232e325ba22SNico Boehr static void test_get_cmma_basic(void)
233e325ba22SNico Boehr {
234e325ba22SNico Boehr 	struct kvm_vm *vm = create_vm_two_memslots();
235e325ba22SNico Boehr 	struct kvm_vcpu *vcpu;
236e325ba22SNico Boehr 	int rc, errno_out;
237e325ba22SNico Boehr 
238e325ba22SNico Boehr 	/* GET_CMMA_BITS without CMMA enabled should fail */
239e325ba22SNico Boehr 	rc = vm_get_cmma_bits(vm, 0, &errno_out);
240*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, -1);
241*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(errno_out, ENXIO);
242e325ba22SNico Boehr 
243e325ba22SNico Boehr 	enable_cmma(vm);
244e325ba22SNico Boehr 	vcpu = vm_vcpu_add(vm, 1, guest_do_one_essa);
245e325ba22SNico Boehr 
246e325ba22SNico Boehr 	vcpu_run(vcpu);
247e325ba22SNico Boehr 
248e325ba22SNico Boehr 	/* GET_CMMA_BITS without migration mode and without peeking should fail */
249e325ba22SNico Boehr 	rc = vm_get_cmma_bits(vm, 0, &errno_out);
250*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, -1);
251*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(errno_out, EINVAL);
252e325ba22SNico Boehr 
253e325ba22SNico Boehr 	/* GET_CMMA_BITS without migration mode and with peeking should work */
254e325ba22SNico Boehr 	rc = vm_get_cmma_bits(vm, KVM_S390_CMMA_PEEK, &errno_out);
255*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, 0);
256*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(errno_out, 0);
257e325ba22SNico Boehr 
258e325ba22SNico Boehr 	enable_dirty_tracking(vm);
259e325ba22SNico Boehr 	enable_migration_mode(vm);
260e325ba22SNico Boehr 
261e325ba22SNico Boehr 	/* GET_CMMA_BITS with invalid flags */
262e325ba22SNico Boehr 	rc = vm_get_cmma_bits(vm, 0xfeedc0fe, &errno_out);
263*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, -1);
264*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(errno_out, EINVAL);
265e325ba22SNico Boehr 
266e325ba22SNico Boehr 	kvm_vm_free(vm);
267e325ba22SNico Boehr }
268e325ba22SNico Boehr 
assert_exit_was_hypercall(struct kvm_vcpu * vcpu)269e325ba22SNico Boehr static void assert_exit_was_hypercall(struct kvm_vcpu *vcpu)
270e325ba22SNico Boehr {
271*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(vcpu->run->exit_reason, 13);
272*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(vcpu->run->s390_sieic.icptcode, 4);
273*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipa, 0x8300);
274*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(vcpu->run->s390_sieic.ipb, 0x5010000);
275e325ba22SNico Boehr }
276e325ba22SNico Boehr 
test_migration_mode(void)277e325ba22SNico Boehr static void test_migration_mode(void)
278e325ba22SNico Boehr {
279e325ba22SNico Boehr 	struct kvm_vm *vm = create_vm();
280e325ba22SNico Boehr 	struct kvm_vcpu *vcpu;
281e325ba22SNico Boehr 	u64 orig_psw;
282e325ba22SNico Boehr 	int rc;
283e325ba22SNico Boehr 
284e325ba22SNico Boehr 	/* enabling migration mode on a VM without memory should fail */
285e325ba22SNico Boehr 	rc = __enable_migration_mode(vm);
286*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, -1);
287*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(errno, EINVAL);
288e325ba22SNico Boehr 	TEST_ASSERT(!is_migration_mode_on(vm), "migration mode should still be off");
289e325ba22SNico Boehr 	errno = 0;
290e325ba22SNico Boehr 
291e325ba22SNico Boehr 	create_memslots(vm);
292e325ba22SNico Boehr 	finish_vm_setup(vm);
293e325ba22SNico Boehr 
294e325ba22SNico Boehr 	enable_cmma(vm);
295e325ba22SNico Boehr 	vcpu = vm_vcpu_add(vm, 1, guest_do_one_essa);
296e325ba22SNico Boehr 	orig_psw = vcpu->run->psw_addr;
297e325ba22SNico Boehr 
298e325ba22SNico Boehr 	/*
299e325ba22SNico Boehr 	 * Execute one essa instruction in the guest. Otherwise the guest will
300e325ba22SNico Boehr 	 * not have use_cmm enabled and GET_CMMA_BITS will return no pages.
301e325ba22SNico Boehr 	 */
302e325ba22SNico Boehr 	vcpu_run(vcpu);
303e325ba22SNico Boehr 	assert_exit_was_hypercall(vcpu);
304e325ba22SNico Boehr 
305e325ba22SNico Boehr 	/* migration mode when memslots have dirty tracking off should fail */
306e325ba22SNico Boehr 	rc = __enable_migration_mode(vm);
307*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, -1);
308*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(errno, EINVAL);
309e325ba22SNico Boehr 	TEST_ASSERT(!is_migration_mode_on(vm), "migration mode should still be off");
310e325ba22SNico Boehr 	errno = 0;
311e325ba22SNico Boehr 
312e325ba22SNico Boehr 	/* enable dirty tracking */
313e325ba22SNico Boehr 	enable_dirty_tracking(vm);
314e325ba22SNico Boehr 
315e325ba22SNico Boehr 	/* enabling migration mode should work now */
316e325ba22SNico Boehr 	rc = __enable_migration_mode(vm);
317*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, 0);
318e325ba22SNico Boehr 	TEST_ASSERT(is_migration_mode_on(vm), "migration mode should be on");
319e325ba22SNico Boehr 	errno = 0;
320e325ba22SNico Boehr 
321e325ba22SNico Boehr 	/* execute another ESSA instruction to see this goes fine */
322e325ba22SNico Boehr 	vcpu->run->psw_addr = orig_psw;
323e325ba22SNico Boehr 	vcpu_run(vcpu);
324e325ba22SNico Boehr 	assert_exit_was_hypercall(vcpu);
325e325ba22SNico Boehr 
326e325ba22SNico Boehr 	/*
327e325ba22SNico Boehr 	 * With migration mode on, create a new memslot with dirty tracking off.
328e325ba22SNico Boehr 	 * This should turn off migration mode.
329e325ba22SNico Boehr 	 */
330e325ba22SNico Boehr 	TEST_ASSERT(is_migration_mode_on(vm), "migration mode should be on");
331e325ba22SNico Boehr 	vm_userspace_mem_region_add(vm,
332e325ba22SNico Boehr 				    VM_MEM_SRC_ANONYMOUS,
333e325ba22SNico Boehr 				    TEST_DATA_TWO_START_GFN << vm->page_shift,
334e325ba22SNico Boehr 				    TEST_DATA_TWO_MEMSLOT,
335e325ba22SNico Boehr 				    TEST_DATA_TWO_PAGE_COUNT,
336e325ba22SNico Boehr 				    0
337e325ba22SNico Boehr 				   );
338e325ba22SNico Boehr 	TEST_ASSERT(!is_migration_mode_on(vm),
339e325ba22SNico Boehr 		    "creating memslot without dirty tracking turns off migration mode"
340e325ba22SNico Boehr 		   );
341e325ba22SNico Boehr 
342e325ba22SNico Boehr 	/* ESSA instructions should still execute fine */
343e325ba22SNico Boehr 	vcpu->run->psw_addr = orig_psw;
344e325ba22SNico Boehr 	vcpu_run(vcpu);
345e325ba22SNico Boehr 	assert_exit_was_hypercall(vcpu);
346e325ba22SNico Boehr 
347e325ba22SNico Boehr 	/*
348e325ba22SNico Boehr 	 * Turn on dirty tracking on the new memslot.
349e325ba22SNico Boehr 	 * It should be possible to turn migration mode back on again.
350e325ba22SNico Boehr 	 */
351e325ba22SNico Boehr 	vm_mem_region_set_flags(vm, TEST_DATA_TWO_MEMSLOT, KVM_MEM_LOG_DIRTY_PAGES);
352e325ba22SNico Boehr 	rc = __enable_migration_mode(vm);
353*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(rc, 0);
354e325ba22SNico Boehr 	TEST_ASSERT(is_migration_mode_on(vm), "migration mode should be on");
355e325ba22SNico Boehr 	errno = 0;
356e325ba22SNico Boehr 
357e325ba22SNico Boehr 	/*
358e325ba22SNico Boehr 	 * Turn off dirty tracking again, this time with just a flag change.
359e325ba22SNico Boehr 	 * Again, migration mode should turn off.
360e325ba22SNico Boehr 	 */
361e325ba22SNico Boehr 	TEST_ASSERT(is_migration_mode_on(vm), "migration mode should be on");
362e325ba22SNico Boehr 	vm_mem_region_set_flags(vm, TEST_DATA_TWO_MEMSLOT, 0);
363e325ba22SNico Boehr 	TEST_ASSERT(!is_migration_mode_on(vm),
364e325ba22SNico Boehr 		    "disabling dirty tracking should turn off migration mode"
365e325ba22SNico Boehr 		   );
366e325ba22SNico Boehr 
367e325ba22SNico Boehr 	/* ESSA instructions should still execute fine */
368e325ba22SNico Boehr 	vcpu->run->psw_addr = orig_psw;
369e325ba22SNico Boehr 	vcpu_run(vcpu);
370e325ba22SNico Boehr 	assert_exit_was_hypercall(vcpu);
371e325ba22SNico Boehr 
372e325ba22SNico Boehr 	kvm_vm_free(vm);
373e325ba22SNico Boehr }
374e325ba22SNico Boehr 
375e325ba22SNico Boehr /**
376e325ba22SNico Boehr  * Given a VM with the MAIN and TEST_DATA memslot, assert that both slots have
377e325ba22SNico Boehr  * CMMA attributes of all pages in both memslots and nothing more dirty.
378e325ba22SNico Boehr  * This has the useful side effect of ensuring nothing is CMMA dirty after this
379e325ba22SNico Boehr  * function.
380e325ba22SNico Boehr  */
assert_all_slots_cmma_dirty(struct kvm_vm * vm)381e325ba22SNico Boehr static void assert_all_slots_cmma_dirty(struct kvm_vm *vm)
382e325ba22SNico Boehr {
383e325ba22SNico Boehr 	struct kvm_s390_cmma_log args;
384e325ba22SNico Boehr 
385e325ba22SNico Boehr 	/*
386e325ba22SNico Boehr 	 * First iteration - everything should be dirty.
387e325ba22SNico Boehr 	 * Start at the main memslot...
388e325ba22SNico Boehr 	 */
389e325ba22SNico Boehr 	args = (struct kvm_s390_cmma_log){
390e325ba22SNico Boehr 		.start_gfn = 0,
391e325ba22SNico Boehr 		.count = sizeof(cmma_value_buf),
392e325ba22SNico Boehr 		.flags = 0,
393e325ba22SNico Boehr 		.values = (__u64)&cmma_value_buf[0]
394e325ba22SNico Boehr 	};
395e325ba22SNico Boehr 	memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf));
396e325ba22SNico Boehr 	vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args);
397*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.count, MAIN_PAGE_COUNT);
398*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.remaining, TEST_DATA_PAGE_COUNT);
399*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.start_gfn, 0);
400e325ba22SNico Boehr 
401e325ba22SNico Boehr 	/* ...and then - after a hole - the TEST_DATA memslot should follow */
402e325ba22SNico Boehr 	args = (struct kvm_s390_cmma_log){
403e325ba22SNico Boehr 		.start_gfn = MAIN_PAGE_COUNT,
404e325ba22SNico Boehr 		.count = sizeof(cmma_value_buf),
405e325ba22SNico Boehr 		.flags = 0,
406e325ba22SNico Boehr 		.values = (__u64)&cmma_value_buf[0]
407e325ba22SNico Boehr 	};
408e325ba22SNico Boehr 	memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf));
409e325ba22SNico Boehr 	vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args);
410*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.count, TEST_DATA_PAGE_COUNT);
411*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.start_gfn, TEST_DATA_START_GFN);
412*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.remaining, 0);
413e325ba22SNico Boehr 
414e325ba22SNico Boehr 	/* ...and nothing else should be there */
415e325ba22SNico Boehr 	args = (struct kvm_s390_cmma_log){
416e325ba22SNico Boehr 		.start_gfn = TEST_DATA_START_GFN + TEST_DATA_PAGE_COUNT,
417e325ba22SNico Boehr 		.count = sizeof(cmma_value_buf),
418e325ba22SNico Boehr 		.flags = 0,
419e325ba22SNico Boehr 		.values = (__u64)&cmma_value_buf[0]
420e325ba22SNico Boehr 	};
421e325ba22SNico Boehr 	memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf));
422e325ba22SNico Boehr 	vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args);
423*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.count, 0);
424*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.start_gfn, 0);
425*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(args.remaining, 0);
426e325ba22SNico Boehr }
427e325ba22SNico Boehr 
428e325ba22SNico Boehr /**
429e325ba22SNico Boehr  * Given a VM, assert no pages are CMMA dirty.
430e325ba22SNico Boehr  */
assert_no_pages_cmma_dirty(struct kvm_vm * vm)431e325ba22SNico Boehr static void assert_no_pages_cmma_dirty(struct kvm_vm *vm)
432e325ba22SNico Boehr {
433e325ba22SNico Boehr 	struct kvm_s390_cmma_log args;
434e325ba22SNico Boehr 
435e325ba22SNico Boehr 	/* If we start from GFN 0 again, nothing should be dirty. */
436e325ba22SNico Boehr 	args = (struct kvm_s390_cmma_log){
437e325ba22SNico Boehr 		.start_gfn = 0,
438e325ba22SNico Boehr 		.count = sizeof(cmma_value_buf),
439e325ba22SNico Boehr 		.flags = 0,
440e325ba22SNico Boehr 		.values = (__u64)&cmma_value_buf[0]
441e325ba22SNico Boehr 	};
442e325ba22SNico Boehr 	memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf));
443e325ba22SNico Boehr 	vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, &args);
444e325ba22SNico Boehr 	if (args.count || args.remaining || args.start_gfn)
445e325ba22SNico Boehr 		TEST_FAIL("pages are still dirty start_gfn=0x%llx count=%u remaining=%llu",
446e325ba22SNico Boehr 			  args.start_gfn,
447e325ba22SNico Boehr 			  args.count,
448e325ba22SNico Boehr 			  args.remaining
449e325ba22SNico Boehr 			 );
450e325ba22SNico Boehr }
451e325ba22SNico Boehr 
test_get_inital_dirty(void)452e325ba22SNico Boehr static void test_get_inital_dirty(void)
453e325ba22SNico Boehr {
454e325ba22SNico Boehr 	struct kvm_vm *vm = create_vm_two_memslots();
455e325ba22SNico Boehr 	struct kvm_vcpu *vcpu;
456e325ba22SNico Boehr 
457e325ba22SNico Boehr 	enable_cmma(vm);
458e325ba22SNico Boehr 	vcpu = vm_vcpu_add(vm, 1, guest_do_one_essa);
459e325ba22SNico Boehr 
460e325ba22SNico Boehr 	/*
461e325ba22SNico Boehr 	 * Execute one essa instruction in the guest. Otherwise the guest will
462e325ba22SNico Boehr 	 * not have use_cmm enabled and GET_CMMA_BITS will return no pages.
463e325ba22SNico Boehr 	 */
464e325ba22SNico Boehr 	vcpu_run(vcpu);
465e325ba22SNico Boehr 	assert_exit_was_hypercall(vcpu);
466e325ba22SNico Boehr 
467e325ba22SNico Boehr 	enable_dirty_tracking(vm);
468e325ba22SNico Boehr 	enable_migration_mode(vm);
469e325ba22SNico Boehr 
470e325ba22SNico Boehr 	assert_all_slots_cmma_dirty(vm);
471e325ba22SNico Boehr 
472e325ba22SNico Boehr 	/* Start from the beginning again and make sure nothing else is dirty */
473e325ba22SNico Boehr 	assert_no_pages_cmma_dirty(vm);
474e325ba22SNico Boehr 
475e325ba22SNico Boehr 	kvm_vm_free(vm);
476e325ba22SNico Boehr }
477e325ba22SNico Boehr 
query_cmma_range(struct kvm_vm * vm,u64 start_gfn,u64 gfn_count,struct kvm_s390_cmma_log * res_out)478e325ba22SNico Boehr static void query_cmma_range(struct kvm_vm *vm,
479e325ba22SNico Boehr 			     u64 start_gfn, u64 gfn_count,
480e325ba22SNico Boehr 			     struct kvm_s390_cmma_log *res_out)
481e325ba22SNico Boehr {
482e325ba22SNico Boehr 	*res_out = (struct kvm_s390_cmma_log){
483e325ba22SNico Boehr 		.start_gfn = start_gfn,
484e325ba22SNico Boehr 		.count = gfn_count,
485e325ba22SNico Boehr 		.flags = 0,
486e325ba22SNico Boehr 		.values = (__u64)&cmma_value_buf[0]
487e325ba22SNico Boehr 	};
488e325ba22SNico Boehr 	memset(cmma_value_buf, 0xff, sizeof(cmma_value_buf));
489e325ba22SNico Boehr 	vm_ioctl(vm, KVM_S390_GET_CMMA_BITS, res_out);
490e325ba22SNico Boehr }
491e325ba22SNico Boehr 
492e325ba22SNico Boehr /**
493e325ba22SNico Boehr  * Assert the given cmma_log struct that was executed by query_cmma_range()
494e325ba22SNico Boehr  * indicates the first dirty gfn is at first_dirty_gfn and contains exactly
495e325ba22SNico Boehr  * dirty_gfn_count CMMA values.
496e325ba22SNico Boehr  */
assert_cmma_dirty(u64 first_dirty_gfn,u64 dirty_gfn_count,const struct kvm_s390_cmma_log * res)497e325ba22SNico Boehr static void assert_cmma_dirty(u64 first_dirty_gfn,
498e325ba22SNico Boehr 			      u64 dirty_gfn_count,
499e325ba22SNico Boehr 			      const struct kvm_s390_cmma_log *res)
500e325ba22SNico Boehr {
501*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(res->start_gfn, first_dirty_gfn);
502*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(res->count, dirty_gfn_count);
503e325ba22SNico Boehr 	for (size_t i = 0; i < dirty_gfn_count; i++)
504*6d85f51aSThomas Huth 		TEST_ASSERT_EQ(cmma_value_buf[0], 0x0); /* stable state */
505*6d85f51aSThomas Huth 	TEST_ASSERT_EQ(cmma_value_buf[dirty_gfn_count], 0xff); /* not touched */
506e325ba22SNico Boehr }
507e325ba22SNico Boehr 
test_get_skip_holes(void)508e325ba22SNico Boehr static void test_get_skip_holes(void)
509e325ba22SNico Boehr {
510e325ba22SNico Boehr 	size_t gfn_offset;
511e325ba22SNico Boehr 	struct kvm_vm *vm = create_vm_two_memslots();
512e325ba22SNico Boehr 	struct kvm_s390_cmma_log log;
513e325ba22SNico Boehr 	struct kvm_vcpu *vcpu;
514e325ba22SNico Boehr 	u64 orig_psw;
515e325ba22SNico Boehr 
516e325ba22SNico Boehr 	enable_cmma(vm);
517e325ba22SNico Boehr 	vcpu = vm_vcpu_add(vm, 1, guest_dirty_test_data);
518e325ba22SNico Boehr 
519e325ba22SNico Boehr 	orig_psw = vcpu->run->psw_addr;
520e325ba22SNico Boehr 
521e325ba22SNico Boehr 	/*
522e325ba22SNico Boehr 	 * Execute some essa instructions in the guest. Otherwise the guest will
523e325ba22SNico Boehr 	 * not have use_cmm enabled and GET_CMMA_BITS will return no pages.
524e325ba22SNico Boehr 	 */
525e325ba22SNico Boehr 	vcpu_run(vcpu);
526e325ba22SNico Boehr 	assert_exit_was_hypercall(vcpu);
527e325ba22SNico Boehr 
528e325ba22SNico Boehr 	enable_dirty_tracking(vm);
529e325ba22SNico Boehr 	enable_migration_mode(vm);
530e325ba22SNico Boehr 
531e325ba22SNico Boehr 	/* un-dirty all pages */
532e325ba22SNico Boehr 	assert_all_slots_cmma_dirty(vm);
533e325ba22SNico Boehr 
534e325ba22SNico Boehr 	/* Then, dirty just the TEST_DATA memslot */
535e325ba22SNico Boehr 	vcpu->run->psw_addr = orig_psw;
536e325ba22SNico Boehr 	vcpu_run(vcpu);
537e325ba22SNico Boehr 
538e325ba22SNico Boehr 	gfn_offset = TEST_DATA_START_GFN;
539e325ba22SNico Boehr 	/**
540e325ba22SNico Boehr 	 * Query CMMA attributes of one page, starting at page 0. Since the
541e325ba22SNico Boehr 	 * main memslot was not touched by the VM, this should yield the first
542e325ba22SNico Boehr 	 * page of the TEST_DATA memslot.
543e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
544e325ba22SNico Boehr 	 * 0: not dirty
545e325ba22SNico Boehr 	 * [0x1, 0x200): dirty
546e325ba22SNico Boehr 	 */
547e325ba22SNico Boehr 	query_cmma_range(vm, 0, 1, &log);
548e325ba22SNico Boehr 	assert_cmma_dirty(gfn_offset, 1, &log);
549e325ba22SNico Boehr 	gfn_offset++;
550e325ba22SNico Boehr 
551e325ba22SNico Boehr 	/**
552e325ba22SNico Boehr 	 * Query CMMA attributes of 32 (0x20) pages past the end of the TEST_DATA
553e325ba22SNico Boehr 	 * memslot. This should wrap back to the beginning of the TEST_DATA
554e325ba22SNico Boehr 	 * memslot, page 1.
555e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
556e325ba22SNico Boehr 	 * [0, 0x21): not dirty
557e325ba22SNico Boehr 	 * [0x21, 0x200): dirty
558e325ba22SNico Boehr 	 */
559e325ba22SNico Boehr 	query_cmma_range(vm, TEST_DATA_START_GFN + TEST_DATA_PAGE_COUNT, 0x20, &log);
560e325ba22SNico Boehr 	assert_cmma_dirty(gfn_offset, 0x20, &log);
561e325ba22SNico Boehr 	gfn_offset += 0x20;
562e325ba22SNico Boehr 
563e325ba22SNico Boehr 	/* Skip 32 pages */
564e325ba22SNico Boehr 	gfn_offset += 0x20;
565e325ba22SNico Boehr 
566e325ba22SNico Boehr 	/**
567e325ba22SNico Boehr 	 * After skipping 32 pages, query the next 32 (0x20) pages.
568e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
569e325ba22SNico Boehr 	 * [0, 0x21): not dirty
570e325ba22SNico Boehr 	 * [0x21, 0x41): dirty
571e325ba22SNico Boehr 	 * [0x41, 0x61): not dirty
572e325ba22SNico Boehr 	 * [0x61, 0x200): dirty
573e325ba22SNico Boehr 	 */
574e325ba22SNico Boehr 	query_cmma_range(vm, gfn_offset, 0x20, &log);
575e325ba22SNico Boehr 	assert_cmma_dirty(gfn_offset, 0x20, &log);
576e325ba22SNico Boehr 	gfn_offset += 0x20;
577e325ba22SNico Boehr 
578e325ba22SNico Boehr 	/**
579e325ba22SNico Boehr 	 * Query 1 page from the beginning of the TEST_DATA memslot. This should
580e325ba22SNico Boehr 	 * yield page 0x21.
581e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
582e325ba22SNico Boehr 	 * [0, 0x22): not dirty
583e325ba22SNico Boehr 	 * [0x22, 0x41): dirty
584e325ba22SNico Boehr 	 * [0x41, 0x61): not dirty
585e325ba22SNico Boehr 	 * [0x61, 0x200): dirty
586e325ba22SNico Boehr 	 */
587e325ba22SNico Boehr 	query_cmma_range(vm, TEST_DATA_START_GFN, 1, &log);
588e325ba22SNico Boehr 	assert_cmma_dirty(TEST_DATA_START_GFN + 0x21, 1, &log);
589e325ba22SNico Boehr 	gfn_offset++;
590e325ba22SNico Boehr 
591e325ba22SNico Boehr 	/**
592e325ba22SNico Boehr 	 * Query 15 (0xF) pages from page 0x23 in TEST_DATA memslot.
593e325ba22SNico Boehr 	 * This should yield pages [0x23, 0x33).
594e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
595e325ba22SNico Boehr 	 * [0, 0x22): not dirty
596e325ba22SNico Boehr 	 * 0x22: dirty
597e325ba22SNico Boehr 	 * [0x23, 0x33): not dirty
598e325ba22SNico Boehr 	 * [0x33, 0x41): dirty
599e325ba22SNico Boehr 	 * [0x41, 0x61): not dirty
600e325ba22SNico Boehr 	 * [0x61, 0x200): dirty
601e325ba22SNico Boehr 	 */
602e325ba22SNico Boehr 	gfn_offset = TEST_DATA_START_GFN + 0x23;
603e325ba22SNico Boehr 	query_cmma_range(vm, gfn_offset, 15, &log);
604e325ba22SNico Boehr 	assert_cmma_dirty(gfn_offset, 15, &log);
605e325ba22SNico Boehr 
606e325ba22SNico Boehr 	/**
607e325ba22SNico Boehr 	 * Query 17 (0x11) pages from page 0x22 in TEST_DATA memslot.
608e325ba22SNico Boehr 	 * This should yield page [0x22, 0x33)
609e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
610e325ba22SNico Boehr 	 * [0, 0x33): not dirty
611e325ba22SNico Boehr 	 * [0x33, 0x41): dirty
612e325ba22SNico Boehr 	 * [0x41, 0x61): not dirty
613e325ba22SNico Boehr 	 * [0x61, 0x200): dirty
614e325ba22SNico Boehr 	 */
615e325ba22SNico Boehr 	gfn_offset = TEST_DATA_START_GFN + 0x22;
616e325ba22SNico Boehr 	query_cmma_range(vm, gfn_offset, 17, &log);
617e325ba22SNico Boehr 	assert_cmma_dirty(gfn_offset, 17, &log);
618e325ba22SNico Boehr 
619e325ba22SNico Boehr 	/**
620e325ba22SNico Boehr 	 * Query 25 (0x19) pages from page 0x40 in TEST_DATA memslot.
621e325ba22SNico Boehr 	 * This should yield page 0x40 and nothing more, since there are more
622e325ba22SNico Boehr 	 * than 16 non-dirty pages after page 0x40.
623e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
624e325ba22SNico Boehr 	 * [0, 0x33): not dirty
625e325ba22SNico Boehr 	 * [0x33, 0x40): dirty
626e325ba22SNico Boehr 	 * [0x40, 0x61): not dirty
627e325ba22SNico Boehr 	 * [0x61, 0x200): dirty
628e325ba22SNico Boehr 	 */
629e325ba22SNico Boehr 	gfn_offset = TEST_DATA_START_GFN + 0x40;
630e325ba22SNico Boehr 	query_cmma_range(vm, gfn_offset, 25, &log);
631e325ba22SNico Boehr 	assert_cmma_dirty(gfn_offset, 1, &log);
632e325ba22SNico Boehr 
633e325ba22SNico Boehr 	/**
634e325ba22SNico Boehr 	 * Query pages [0x33, 0x40).
635e325ba22SNico Boehr 	 * The dirty bitmap should now look like this:
636e325ba22SNico Boehr 	 * [0, 0x61): not dirty
637e325ba22SNico Boehr 	 * [0x61, 0x200): dirty
638e325ba22SNico Boehr 	 */
639e325ba22SNico Boehr 	gfn_offset = TEST_DATA_START_GFN + 0x33;
640e325ba22SNico Boehr 	query_cmma_range(vm, gfn_offset, 0x40 - 0x33, &log);
641e325ba22SNico Boehr 	assert_cmma_dirty(gfn_offset, 0x40 - 0x33, &log);
642e325ba22SNico Boehr 
643e325ba22SNico Boehr 	/**
644e325ba22SNico Boehr 	 * Query the remaining pages [0x61, 0x200).
645e325ba22SNico Boehr 	 */
646e325ba22SNico Boehr 	gfn_offset = TEST_DATA_START_GFN;
647e325ba22SNico Boehr 	query_cmma_range(vm, gfn_offset, TEST_DATA_PAGE_COUNT - 0x61, &log);
648e325ba22SNico Boehr 	assert_cmma_dirty(TEST_DATA_START_GFN + 0x61, TEST_DATA_PAGE_COUNT - 0x61, &log);
649e325ba22SNico Boehr 
650e325ba22SNico Boehr 	assert_no_pages_cmma_dirty(vm);
651e325ba22SNico Boehr }
652e325ba22SNico Boehr 
653e325ba22SNico Boehr struct testdef {
654e325ba22SNico Boehr 	const char *name;
655e325ba22SNico Boehr 	void (*test)(void);
656e325ba22SNico Boehr } testlist[] = {
657e325ba22SNico Boehr 	{ "migration mode and dirty tracking", test_migration_mode },
658e325ba22SNico Boehr 	{ "GET_CMMA_BITS: basic calls", test_get_cmma_basic },
659e325ba22SNico Boehr 	{ "GET_CMMA_BITS: all pages are dirty initally", test_get_inital_dirty },
660e325ba22SNico Boehr 	{ "GET_CMMA_BITS: holes are skipped", test_get_skip_holes },
661e325ba22SNico Boehr };
662e325ba22SNico Boehr 
663e325ba22SNico Boehr /**
664e325ba22SNico Boehr  * The kernel may support CMMA, but the machine may not (i.e. if running as
665e325ba22SNico Boehr  * guest-3).
666e325ba22SNico Boehr  *
667e325ba22SNico Boehr  * In this case, the CMMA capabilities are all there, but the CMMA-related
668e325ba22SNico Boehr  * ioctls fail. To find out whether the machine supports CMMA, create a
669e325ba22SNico Boehr  * temporary VM and then query the CMMA feature of the VM.
670e325ba22SNico Boehr  */
machine_has_cmma(void)671e325ba22SNico Boehr static int machine_has_cmma(void)
672e325ba22SNico Boehr {
673e325ba22SNico Boehr 	struct kvm_vm *vm = create_vm();
674e325ba22SNico Boehr 	int r;
675e325ba22SNico Boehr 
676e325ba22SNico Boehr 	r = !__kvm_has_device_attr(vm->fd, KVM_S390_VM_MEM_CTRL, KVM_S390_VM_MEM_ENABLE_CMMA);
677e325ba22SNico Boehr 	kvm_vm_free(vm);
678e325ba22SNico Boehr 
679e325ba22SNico Boehr 	return r;
680e325ba22SNico Boehr }
681e325ba22SNico Boehr 
main(int argc,char * argv[])682e325ba22SNico Boehr int main(int argc, char *argv[])
683e325ba22SNico Boehr {
684e325ba22SNico Boehr 	int idx;
685e325ba22SNico Boehr 
686e325ba22SNico Boehr 	TEST_REQUIRE(kvm_has_cap(KVM_CAP_SYNC_REGS));
687e325ba22SNico Boehr 	TEST_REQUIRE(kvm_has_cap(KVM_CAP_S390_CMMA_MIGRATION));
688e325ba22SNico Boehr 	TEST_REQUIRE(machine_has_cmma());
689e325ba22SNico Boehr 
690e325ba22SNico Boehr 	ksft_print_header();
691e325ba22SNico Boehr 
692e325ba22SNico Boehr 	ksft_set_plan(ARRAY_SIZE(testlist));
693e325ba22SNico Boehr 
694e325ba22SNico Boehr 	for (idx = 0; idx < ARRAY_SIZE(testlist); idx++) {
695e325ba22SNico Boehr 		testlist[idx].test();
696e325ba22SNico Boehr 		ksft_test_result_pass("%s\n", testlist[idx].name);
697e325ba22SNico Boehr 	}
698e325ba22SNico Boehr 
699e325ba22SNico Boehr 	ksft_finished();	/* Print results and exit() accordingly */
700e325ba22SNico Boehr }
701