xref: /kvm-unit-tests/s390x/migration-skey.c (revision 1a7b0521a2cdfed74775b416f7866a9baff967c7)
1*1a7b0521SNico Boehr /* SPDX-License-Identifier: GPL-2.0-only */
2*1a7b0521SNico Boehr /*
3*1a7b0521SNico Boehr  * Storage Key migration tests
4*1a7b0521SNico Boehr  *
5*1a7b0521SNico Boehr  * Copyright IBM Corp. 2022
6*1a7b0521SNico Boehr  *
7*1a7b0521SNico Boehr  * Authors:
8*1a7b0521SNico Boehr  *  Nico Boehr <nrb@linux.ibm.com>
9*1a7b0521SNico Boehr  */
10*1a7b0521SNico Boehr 
11*1a7b0521SNico Boehr #include <libcflat.h>
12*1a7b0521SNico Boehr #include <asm/facility.h>
13*1a7b0521SNico Boehr #include <asm/page.h>
14*1a7b0521SNico Boehr #include <asm/mem.h>
15*1a7b0521SNico Boehr #include <asm/interrupt.h>
16*1a7b0521SNico Boehr #include <hardware.h>
17*1a7b0521SNico Boehr 
18*1a7b0521SNico Boehr #define NUM_PAGES 128
19*1a7b0521SNico Boehr static uint8_t pagebuf[NUM_PAGES][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
20*1a7b0521SNico Boehr 
21*1a7b0521SNico Boehr static void test_migration(void)
22*1a7b0521SNico Boehr {
23*1a7b0521SNico Boehr 	union skey expected_key, actual_key;
24*1a7b0521SNico Boehr 	int i, key_to_set, key_mismatches = 0;
25*1a7b0521SNico Boehr 
26*1a7b0521SNico Boehr 	for (i = 0; i < NUM_PAGES; i++) {
27*1a7b0521SNico Boehr 		/*
28*1a7b0521SNico Boehr 		 * Storage keys are 7 bit, lowest bit is always returned as zero
29*1a7b0521SNico Boehr 		 * by iske.
30*1a7b0521SNico Boehr 		 * This loop will set all 7 bits which means we set fetch
31*1a7b0521SNico Boehr 		 * protection as well as reference and change indication for
32*1a7b0521SNico Boehr 		 * some keys.
33*1a7b0521SNico Boehr 		 */
34*1a7b0521SNico Boehr 		key_to_set = i * 2;
35*1a7b0521SNico Boehr 		set_storage_key(pagebuf[i], key_to_set, 1);
36*1a7b0521SNico Boehr 	}
37*1a7b0521SNico Boehr 
38*1a7b0521SNico Boehr 	puts("Please migrate me, then press return\n");
39*1a7b0521SNico Boehr 	(void)getchar();
40*1a7b0521SNico Boehr 
41*1a7b0521SNico Boehr 	for (i = 0; i < NUM_PAGES; i++) {
42*1a7b0521SNico Boehr 		actual_key.val = get_storage_key(pagebuf[i]);
43*1a7b0521SNico Boehr 		expected_key.val = i * 2;
44*1a7b0521SNico Boehr 
45*1a7b0521SNico Boehr 		/*
46*1a7b0521SNico Boehr 		 * The PoP neither gives a guarantee that the reference bit is
47*1a7b0521SNico Boehr 		 * accurate nor that it won't be cleared by hardware. Hence we
48*1a7b0521SNico Boehr 		 * don't rely on it and just clear the bits to avoid compare
49*1a7b0521SNico Boehr 		 * errors.
50*1a7b0521SNico Boehr 		 */
51*1a7b0521SNico Boehr 		actual_key.str.rf = 0;
52*1a7b0521SNico Boehr 		expected_key.str.rf = 0;
53*1a7b0521SNico Boehr 
54*1a7b0521SNico Boehr 		/* don't log anything when key matches to avoid spamming the log */
55*1a7b0521SNico Boehr 		if (actual_key.val != expected_key.val) {
56*1a7b0521SNico Boehr 			key_mismatches++;
57*1a7b0521SNico Boehr 			report_fail("page %d expected_key=0x%x actual_key=0x%x", i, expected_key.val, actual_key.val);
58*1a7b0521SNico Boehr 		}
59*1a7b0521SNico Boehr 	}
60*1a7b0521SNico Boehr 
61*1a7b0521SNico Boehr 	report(!key_mismatches, "skeys after migration match");
62*1a7b0521SNico Boehr }
63*1a7b0521SNico Boehr 
64*1a7b0521SNico Boehr int main(void)
65*1a7b0521SNico Boehr {
66*1a7b0521SNico Boehr 	report_prefix_push("migration-skey");
67*1a7b0521SNico Boehr 	if (test_facility(169)) {
68*1a7b0521SNico Boehr 		report_skip("storage key removal facility is active");
69*1a7b0521SNico Boehr 
70*1a7b0521SNico Boehr 		/*
71*1a7b0521SNico Boehr 		 * If we just exit and don't ask migrate_cmd to migrate us, it
72*1a7b0521SNico Boehr 		 * will just hang forever. Hence, also ask for migration when we
73*1a7b0521SNico Boehr 		 * skip this test altogether.
74*1a7b0521SNico Boehr 		 */
75*1a7b0521SNico Boehr 		puts("Please migrate me, then press return\n");
76*1a7b0521SNico Boehr 		(void)getchar();
77*1a7b0521SNico Boehr 	} else {
78*1a7b0521SNico Boehr 		test_migration();
79*1a7b0521SNico Boehr 	}
80*1a7b0521SNico Boehr 
81*1a7b0521SNico Boehr 	report_prefix_pop();
82*1a7b0521SNico Boehr 	return report_summary();
83*1a7b0521SNico Boehr }
84