xref: /kvm-unit-tests/s390x/skey.c (revision cd719531ee2b3aae62a52cfe97aa6aa5286e4051)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Storage key tests
4  *
5  * Copyright (c) 2018 IBM Corp
6  *
7  * Authors:
8  *  Janosch Frank <frankja@linux.vnet.ibm.com>
9  */
10 #include <libcflat.h>
11 #include <asm/asm-offsets.h>
12 #include <asm/interrupt.h>
13 #include <vmalloc.h>
14 #include <asm/page.h>
15 #include <asm/facility.h>
16 #include <asm/mem.h>
17 
18 
19 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
20 
21 static void test_set_mb(void)
22 {
23 	union skey skey, ret1, ret2;
24 	void *addr = (void *)0x10000 - 2 * PAGE_SIZE;
25 	void *end = (void *)0x10000;
26 
27 	/* Multi block support came with EDAT 1 */
28 	if (!test_facility(8))
29 		return;
30 
31 	skey.val = 0x30;
32 	while (addr < end)
33 		addr = set_storage_key_mb(addr, skey.val);
34 
35 	ret1.val = get_storage_key(end - PAGE_SIZE) & (SKEY_ACC | SKEY_FP);
36 	ret2.val = get_storage_key(end - PAGE_SIZE * 2) & (SKEY_ACC | SKEY_FP);
37 	report(ret1.val == ret2.val && ret1.val == skey.val, "multi block");
38 }
39 
40 static void test_chg(void)
41 {
42 	union skey skey1, skey2;
43 
44 	skey1.val = 0x30;
45 	set_storage_key(pagebuf, skey1.val, 0);
46 	skey1.val = get_storage_key(pagebuf);
47 	pagebuf[0] = 3;
48 	skey2.val = get_storage_key(pagebuf);
49 	report(!skey1.str.ch && skey2.str.ch, "chg bit test");
50 }
51 
52 static void test_set(void)
53 {
54 	union skey skey, ret;
55 
56 	skey.val = 0x30;
57 	ret.val = get_storage_key(pagebuf);
58 	set_storage_key(pagebuf, skey.val, 0);
59 	ret.val = get_storage_key(pagebuf);
60 	/*
61 	 * For all set tests we only test the ACC and FP bits. RF and
62 	 * CH are set by the machine for memory references and changes
63 	 * and hence might change between a set and a get.
64 	 */
65 	report(skey.str.acc == ret.str.acc && skey.str.fp == ret.str.fp,
66 	       "set key test");
67 }
68 
69 static void test_priv(void)
70 {
71 	union skey skey;
72 
73 	memset(pagebuf, 0, PAGE_SIZE * 2);
74 	report_prefix_push("privileged");
75 	report_prefix_push("sske");
76 	expect_pgm_int();
77 	enter_pstate();
78 	set_storage_key(pagebuf, 0x30, 0);
79 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
80 	report_prefix_pop();
81 
82 	skey.val = get_storage_key(pagebuf);
83 	report(skey.str.acc != 3, "skey did not change on exception");
84 
85 	report_prefix_push("iske");
86 	expect_pgm_int();
87 	enter_pstate();
88 	get_storage_key(pagebuf);
89 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
90 	report_prefix_pop();
91 
92 	report_prefix_pop();
93 }
94 
95 static void test_invalid_address(void)
96 {
97 	void *inv_addr = (void *)-1ull;
98 
99 	report_prefix_push("invalid address");
100 
101 	report_prefix_push("sske");
102 	expect_pgm_int();
103 	set_storage_key(inv_addr, 0, 0);
104 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
105 	report_prefix_pop();
106 
107 	report_prefix_push("iske");
108 	expect_pgm_int();
109 	get_storage_key(inv_addr);
110 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
111 	report_prefix_pop();
112 
113 	report_prefix_push("rrbe");
114 	expect_pgm_int();
115 	reset_reference_bit(inv_addr);
116 	check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
117 	report_prefix_pop();
118 
119 	report_prefix_pop();
120 }
121 
122 static void test_test_protection(void)
123 {
124 	unsigned long addr = (unsigned long)pagebuf;
125 
126 	report_prefix_push("TPROT");
127 
128 	set_storage_key(pagebuf, 0x10, 0);
129 	report(tprot(addr, 0) == TPROT_READ_WRITE, "zero key: no protection");
130 	report(tprot(addr, 1) == TPROT_READ_WRITE, "matching key: no protection");
131 
132 	report_prefix_push("mismatching key");
133 
134 	report(tprot(addr, 2) == TPROT_READ, "no fetch protection: store protection");
135 
136 	set_storage_key(pagebuf, 0x18, 0);
137 	report(tprot(addr, 2) == TPROT_RW_PROTECTED,
138 	       "fetch protection: fetch & store protection");
139 
140 	report_prefix_push("fetch-protection override");
141 	set_storage_key(0, 0x18, 0);
142 	report(tprot(0, 2) == TPROT_RW_PROTECTED, "disabled: fetch & store protection");
143 	ctl_set_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE);
144 	report(tprot(0, 2) == TPROT_READ, "enabled: store protection");
145 	report(tprot(2048, 2) == TPROT_RW_PROTECTED, "invalid: fetch & store protection");
146 	ctl_clear_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE);
147 	set_storage_key(0, 0x00, 0);
148 	report_prefix_pop();
149 
150 	ctl_set_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE);
151 	set_storage_key(pagebuf, 0x90, 0);
152 	report(tprot(addr, 2) == TPROT_READ_WRITE,
153 	       "storage-protection override: no protection");
154 	ctl_clear_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE);
155 
156 	report_prefix_pop();
157 	set_storage_key(pagebuf, 0x00, 0);
158 	report_prefix_pop();
159 }
160 
161 /*
162  * Perform STORE CPU ADDRESS (STAP) instruction while temporarily executing
163  * with access key 1.
164  */
165 static void store_cpu_address_key_1(uint16_t *out)
166 {
167 	asm volatile (
168 		"spka	0x10\n\t"
169 		"stap	%0\n\t"
170 		"spka	0\n"
171 	     : "+Q" (*out) /* exception: old value remains in out -> + constraint */
172 	);
173 }
174 
175 static void test_store_cpu_address(void)
176 {
177 	uint16_t *out = (uint16_t *)pagebuf;
178 	uint16_t cpu_addr;
179 
180 	report_prefix_push("STORE CPU ADDRESS");
181 	asm ("stap %0" : "=Q" (cpu_addr));
182 
183 	report_prefix_push("zero key");
184 	set_storage_key(pagebuf, 0x20, 0);
185 	WRITE_ONCE(*out, 0xbeef);
186 	asm ("stap %0" : "=Q" (*out));
187 	report(*out == cpu_addr, "store occurred");
188 	report_prefix_pop();
189 
190 	report_prefix_push("matching key");
191 	set_storage_key(pagebuf, 0x10, 0);
192 	*out = 0xbeef;
193 	store_cpu_address_key_1(out);
194 	report(*out == cpu_addr, "store occurred");
195 	report_prefix_pop();
196 
197 	report_prefix_push("mismatching key");
198 	set_storage_key(pagebuf, 0x20, 0);
199 	expect_pgm_int();
200 	*out = 0xbeef;
201 	store_cpu_address_key_1(out);
202 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
203 	report(*out == 0xbeef, "no store occurred");
204 	report_prefix_pop();
205 
206 	ctl_set_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE);
207 
208 	report_prefix_push("storage-protection override, invalid key");
209 	set_storage_key(pagebuf, 0x20, 0);
210 	expect_pgm_int();
211 	*out = 0xbeef;
212 	store_cpu_address_key_1(out);
213 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
214 	report(*out == 0xbeef, "no store occurred");
215 	report_prefix_pop();
216 
217 	report_prefix_push("storage-protection override, override key");
218 	set_storage_key(pagebuf, 0x90, 0);
219 	*out = 0xbeef;
220 	store_cpu_address_key_1(out);
221 	report(*out == cpu_addr, "override occurred");
222 	report_prefix_pop();
223 
224 	ctl_clear_bit(0, CTL0_STORAGE_PROTECTION_OVERRIDE);
225 
226 	report_prefix_push("storage-protection override disabled, override key");
227 	set_storage_key(pagebuf, 0x90, 0);
228 	expect_pgm_int();
229 	*out = 0xbeef;
230 	store_cpu_address_key_1(out);
231 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
232 	report(*out == 0xbeef, "no store occurred");
233 	report_prefix_pop();
234 
235 	set_storage_key(pagebuf, 0x00, 0);
236 	report_prefix_pop();
237 }
238 
239 /*
240  * Perform SET PREFIX (SPX) instruction while temporarily executing
241  * with access key 1.
242  */
243 static void set_prefix_key_1(uint32_t *prefix_ptr)
244 {
245 	asm volatile (
246 		"spka	0x10\n\t"
247 		"spx	%0\n\t"
248 		"spka	0\n"
249 	     :: "Q" (*prefix_ptr)
250 	);
251 }
252 
253 /*
254  * We remapped page 0, making the lowcore inaccessible, which breaks the normal
255  * handler and breaks skipping the faulting instruction.
256  * Just disable dynamic address translation to make things work.
257  */
258 static void dat_fixup_pgm_int(void)
259 {
260 	uint64_t psw_mask = extract_psw_mask();
261 
262 	psw_mask &= ~PSW_MASK_DAT;
263 	load_psw_mask(psw_mask);
264 }
265 
266 #define PREFIX_AREA_SIZE (PAGE_SIZE * 2)
267 static char lowcore_tmp[PREFIX_AREA_SIZE] __attribute__((aligned(PREFIX_AREA_SIZE)));
268 
269 /*
270  * Test accessibility of the operand to SET PREFIX given different configurations
271  * with regards to storage keys. That is, check the accessibility of the location
272  * holding the new prefix, not that of the new prefix area. The new prefix area
273  * is a valid lowcore, so that the test does not crash on failure.
274  */
275 static void test_set_prefix(void)
276 {
277 	uint32_t *prefix_ptr = (uint32_t *)pagebuf;
278 	uint32_t *no_override_prefix_ptr;
279 	uint32_t old_prefix;
280 	pgd_t *root;
281 
282 	report_prefix_push("SET PREFIX");
283 	root = (pgd_t *)(stctg(1) & PAGE_MASK);
284 	old_prefix = get_prefix();
285 	memcpy(lowcore_tmp, 0, sizeof(lowcore_tmp));
286 	assert(((uint64_t)&lowcore_tmp >> 31) == 0);
287 	*prefix_ptr = (uint32_t)(uint64_t)&lowcore_tmp;
288 
289 	report_prefix_push("zero key");
290 	set_prefix(old_prefix);
291 	set_storage_key(prefix_ptr, 0x20, 0);
292 	set_prefix(*prefix_ptr);
293 	report(get_prefix() == *prefix_ptr, "set prefix");
294 	report_prefix_pop();
295 
296 	report_prefix_push("matching key");
297 	set_prefix(old_prefix);
298 	set_storage_key(pagebuf, 0x10, 0);
299 	set_prefix_key_1(prefix_ptr);
300 	report(get_prefix() == *prefix_ptr, "set prefix");
301 	report_prefix_pop();
302 
303 	report_prefix_push("mismatching key");
304 
305 	report_prefix_push("no fetch protection");
306 	set_prefix(old_prefix);
307 	set_storage_key(pagebuf, 0x20, 0);
308 	set_prefix_key_1(prefix_ptr);
309 	report(get_prefix() == *prefix_ptr, "set prefix");
310 	report_prefix_pop();
311 
312 	report_prefix_push("fetch protection");
313 	set_prefix(old_prefix);
314 	set_storage_key(pagebuf, 0x28, 0);
315 	expect_pgm_int();
316 	set_prefix_key_1(prefix_ptr);
317 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
318 	report(get_prefix() == old_prefix, "did not set prefix");
319 	report_prefix_pop();
320 
321 	register_pgm_cleanup_func(dat_fixup_pgm_int);
322 
323 	report_prefix_push("remapped page, fetch protection");
324 	set_prefix(old_prefix);
325 	set_storage_key(pagebuf, 0x28, 0);
326 	expect_pgm_int();
327 	install_page(root, virt_to_pte_phys(root, pagebuf), 0);
328 	set_prefix_key_1((uint32_t *)0);
329 	install_page(root, 0, 0);
330 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
331 	report(get_prefix() == old_prefix, "did not set prefix");
332 	report_prefix_pop();
333 
334 	ctl_set_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE);
335 
336 	report_prefix_push("fetch protection override applies");
337 	set_prefix(old_prefix);
338 	set_storage_key(pagebuf, 0x28, 0);
339 	install_page(root, virt_to_pte_phys(root, pagebuf), 0);
340 	set_prefix_key_1((uint32_t *)0);
341 	install_page(root, 0, 0);
342 	report(get_prefix() == *prefix_ptr, "set prefix");
343 	report_prefix_pop();
344 
345 	no_override_prefix_ptr = (uint32_t *)(pagebuf + 2048);
346 	WRITE_ONCE(*no_override_prefix_ptr, (uint32_t)(uint64_t)&lowcore_tmp);
347 	report_prefix_push("fetch protection override does not apply");
348 	set_prefix(old_prefix);
349 	set_storage_key(pagebuf, 0x28, 0);
350 	expect_pgm_int();
351 	install_page(root, virt_to_pte_phys(root, pagebuf), 0);
352 	set_prefix_key_1((uint32_t *)2048);
353 	install_page(root, 0, 0);
354 	check_pgm_int_code(PGM_INT_CODE_PROTECTION);
355 	report(get_prefix() == old_prefix, "did not set prefix");
356 	report_prefix_pop();
357 
358 	ctl_clear_bit(0, CTL0_FETCH_PROTECTION_OVERRIDE);
359 	register_pgm_cleanup_func(NULL);
360 	report_prefix_pop();
361 	set_storage_key(pagebuf, 0x00, 0);
362 	report_prefix_pop();
363 }
364 
365 int main(void)
366 {
367 	report_prefix_push("skey");
368 	if (test_facility(169)) {
369 		report_skip("storage key removal facility is active");
370 		goto done;
371 	}
372 	test_priv();
373 	test_invalid_address();
374 	test_set();
375 	test_set_mb();
376 	test_chg();
377 	test_test_protection();
378 	test_store_cpu_address();
379 
380 	setup_vm();
381 	test_set_prefix();
382 done:
383 	report_prefix_pop();
384 	return report_summary();
385 }
386