xref: /kvm-unit-tests/s390x/migration-skey.c (revision eef2cdb55d647c4509b398825fcaf6feea6788c2)
11a7b0521SNico Boehr /* SPDX-License-Identifier: GPL-2.0-only */
21a7b0521SNico Boehr /*
31a7b0521SNico Boehr  * Storage Key migration tests
41a7b0521SNico Boehr  *
51a7b0521SNico Boehr  * Copyright IBM Corp. 2022
61a7b0521SNico Boehr  *
71a7b0521SNico Boehr  * Authors:
81a7b0521SNico Boehr  *  Nico Boehr <nrb@linux.ibm.com>
91a7b0521SNico Boehr  */
101a7b0521SNico Boehr 
111a7b0521SNico Boehr #include <libcflat.h>
12*eef2cdb5SNico Boehr #include <migrate.h>
131a7b0521SNico Boehr #include <asm/facility.h>
141a7b0521SNico Boehr #include <asm/page.h>
151a7b0521SNico Boehr #include <asm/mem.h>
161a7b0521SNico Boehr #include <asm/interrupt.h>
171a7b0521SNico Boehr #include <hardware.h>
181a7b0521SNico Boehr 
191a7b0521SNico Boehr #define NUM_PAGES 128
201a7b0521SNico Boehr static uint8_t pagebuf[NUM_PAGES][PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
211a7b0521SNico Boehr 
221a7b0521SNico Boehr static void test_migration(void)
231a7b0521SNico Boehr {
241a7b0521SNico Boehr 	union skey expected_key, actual_key;
251a7b0521SNico Boehr 	int i, key_to_set, key_mismatches = 0;
261a7b0521SNico Boehr 
271a7b0521SNico Boehr 	for (i = 0; i < NUM_PAGES; i++) {
281a7b0521SNico Boehr 		/*
291a7b0521SNico Boehr 		 * Storage keys are 7 bit, lowest bit is always returned as zero
301a7b0521SNico Boehr 		 * by iske.
311a7b0521SNico Boehr 		 * This loop will set all 7 bits which means we set fetch
321a7b0521SNico Boehr 		 * protection as well as reference and change indication for
331a7b0521SNico Boehr 		 * some keys.
341a7b0521SNico Boehr 		 */
351a7b0521SNico Boehr 		key_to_set = i * 2;
361a7b0521SNico Boehr 		set_storage_key(pagebuf[i], key_to_set, 1);
371a7b0521SNico Boehr 	}
381a7b0521SNico Boehr 
39*eef2cdb5SNico Boehr 	migrate_once();
401a7b0521SNico Boehr 
411a7b0521SNico Boehr 	for (i = 0; i < NUM_PAGES; i++) {
421a7b0521SNico Boehr 		actual_key.val = get_storage_key(pagebuf[i]);
431a7b0521SNico Boehr 		expected_key.val = i * 2;
441a7b0521SNico Boehr 
451a7b0521SNico Boehr 		/*
461a7b0521SNico Boehr 		 * The PoP neither gives a guarantee that the reference bit is
471a7b0521SNico Boehr 		 * accurate nor that it won't be cleared by hardware. Hence we
481a7b0521SNico Boehr 		 * don't rely on it and just clear the bits to avoid compare
491a7b0521SNico Boehr 		 * errors.
501a7b0521SNico Boehr 		 */
511a7b0521SNico Boehr 		actual_key.str.rf = 0;
521a7b0521SNico Boehr 		expected_key.str.rf = 0;
531a7b0521SNico Boehr 
541a7b0521SNico Boehr 		/* don't log anything when key matches to avoid spamming the log */
551a7b0521SNico Boehr 		if (actual_key.val != expected_key.val) {
561a7b0521SNico Boehr 			key_mismatches++;
571a7b0521SNico Boehr 			report_fail("page %d expected_key=0x%x actual_key=0x%x", i, expected_key.val, actual_key.val);
581a7b0521SNico Boehr 		}
591a7b0521SNico Boehr 	}
601a7b0521SNico Boehr 
611a7b0521SNico Boehr 	report(!key_mismatches, "skeys after migration match");
621a7b0521SNico Boehr }
631a7b0521SNico Boehr 
641a7b0521SNico Boehr int main(void)
651a7b0521SNico Boehr {
661a7b0521SNico Boehr 	report_prefix_push("migration-skey");
671a7b0521SNico Boehr 
68*eef2cdb5SNico Boehr 	if (test_facility(169))
69*eef2cdb5SNico Boehr 		report_skip("storage key removal facility is active");
70*eef2cdb5SNico Boehr 	else
711a7b0521SNico Boehr 		test_migration();
72*eef2cdb5SNico Boehr 
73*eef2cdb5SNico Boehr 	migrate_once();
741a7b0521SNico Boehr 
751a7b0521SNico Boehr 	report_prefix_pop();
761a7b0521SNico Boehr 	return report_summary();
771a7b0521SNico Boehr }
78