xref: /kvm-unit-tests/s390x/skrf.c (revision a299895b7abb54e7ba6bb4108f202acbb484ac65)
1 /*
2  * Storage key removal facility tests
3  *
4  * Copyright (c) 2019 IBM Corp
5  *
6  * Authors:
7  *  Janosch Frank <frankja@linux.ibm.com>
8  *
9  * This code is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License version 2.
11  */
12 #include <libcflat.h>
13 #include <asm/asm-offsets.h>
14 #include <asm/interrupt.h>
15 #include <asm/page.h>
16 #include <asm/facility.h>
17 #include <asm/mem.h>
18 
19 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
20 
21 static void test_facilities(void)
22 {
23 	report_prefix_push("facilities");
24 	report(!test_facility(10), "!10");
25 	report(!test_facility(14), "!14");
26 	report(!test_facility(66), "!66");
27 	report(!test_facility(145), "!145");
28 	report(!test_facility(140), "!149");
29 	report_prefix_pop();
30 }
31 
32 static void test_skey(void)
33 {
34 	report_prefix_push("sske");
35 	expect_pgm_int();
36 	set_storage_key(pagebuf, 0x30, 0);
37 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
38 	expect_pgm_int();
39 	report_prefix_pop();
40 	report_prefix_push("iske");
41 	get_storage_key(pagebuf);
42 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
43 	report_prefix_pop();
44 }
45 
46 static void test_pfmf(void)
47 {
48 	union pfmf_r1 r1;
49 
50 	report_prefix_push("pfmf");
51 	r1.val = 0;
52 	r1.reg.sk = 1;
53 	r1.reg.fsc = PFMF_FSC_4K;
54 	r1.reg.key = 0x30;
55 	expect_pgm_int();
56 	pfmf(r1.val, pagebuf);
57 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
58 	report_prefix_pop();
59 }
60 
61 static void test_psw_key(void)
62 {
63 	uint64_t psw_mask = extract_psw_mask() | 0xF0000000000000UL;
64 
65 	report_prefix_push("psw key");
66 	expect_pgm_int();
67 	load_psw_mask(psw_mask);
68 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
69 	report_prefix_pop();
70 }
71 
72 static void test_mvcos(void)
73 {
74 	uint64_t r3 = 64;
75 	uint8_t *src = pagebuf;
76 	uint8_t *dst = pagebuf + PAGE_SIZE;
77 	/* K bit set, as well as keys */
78 	register unsigned long oac asm("0") = 0xf002f002;
79 
80 	report_prefix_push("mvcos");
81 	expect_pgm_int();
82 	asm volatile("mvcos	%[dst],%[src],%[len]"
83 		     : [dst] "+Q" (*(dst))
84 		     : [src] "Q" (*(src)), [len] "d" (r3), "d" (oac)
85 		     : "cc", "memory");
86 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
87 	report_prefix_pop();
88 }
89 
90 static void test_spka(void)
91 {
92 	report_prefix_push("spka");
93 	expect_pgm_int();
94 	asm volatile("spka	0xf0(0)\n");
95 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
96 	report_prefix_pop();
97 }
98 
99 static void test_tprot(void)
100 {
101 	report_prefix_push("tprot");
102 	expect_pgm_int();
103 	asm volatile("tprot	%[addr],0xf0(0)\n"
104 		     : : [addr] "a" (pagebuf) : );
105 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
106 	report_prefix_pop();
107 }
108 
109 int main(void)
110 {
111 	report_prefix_push("skrf");
112 	if (!test_facility(169)) {
113 		report_skip("storage key removal facility not available\n");
114 		goto done;
115 	}
116 
117 	test_facilities();
118 	test_skey();
119 	test_pfmf();
120 	test_psw_key();
121 	test_mvcos();
122 	test_spka();
123 	test_tprot();
124 
125 done:
126 	report_prefix_pop();
127 	return report_summary();
128 }
129