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