xref: /kvm-unit-tests/s390x/skey.c (revision 268752cd5334b7284f220763bd75b3f6c2139adb)
1 /*
2  * Storage key tests
3  *
4  * Copyright (c) 2018 IBM Corp
5  *
6  * Authors:
7  *  Janosch Frank <frankja@linux.vnet.ibm.com>
8  *
9  * This code is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU Library 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 
20 static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2)));
21 const unsigned long page0 = (unsigned long)pagebuf;
22 const unsigned long page1 = (unsigned long)(pagebuf + PAGE_SIZE);
23 
24 static void test_set_mb(void)
25 {
26 	union skey skey, ret1, ret2;
27 	unsigned long addr = 0x10000 - 2 * PAGE_SIZE;
28 	unsigned long end = 0x10000;
29 
30 	/* Multi block support came with EDAT 1 */
31 	if (!test_facility(8))
32 		return;
33 
34 	skey.val = 0x30;
35 	while (addr < end)
36 		addr = set_storage_key_mb(addr, skey.val);
37 
38 	ret1.val = get_storage_key(end - PAGE_SIZE) & (SKEY_ACC | SKEY_FP);
39 	ret2.val = get_storage_key(end - PAGE_SIZE * 2) & (SKEY_ACC | SKEY_FP);
40 	report("multi block",
41 	       ret1.val == ret2.val && ret1.val == skey.val);
42 }
43 
44 static void test_chg(void)
45 {
46 	union skey skey1, skey2;
47 
48 	skey1.val = 0x30;
49 	set_storage_key(page0, skey1.val, 0);
50 	skey1.val = get_storage_key(page0);
51 	pagebuf[0] = 3;
52 	skey2.val = get_storage_key(page0);
53 	report("chg bit test", !skey1.str.ch && skey2.str.ch);
54 }
55 
56 static void test_set(void)
57 {
58 	union skey skey, ret;
59 
60 	skey.val = 0x30;
61 	ret.val = get_storage_key(page0);
62 	set_storage_key(page0, skey.val, 0);
63 	ret.val = get_storage_key(page0);
64 	/*
65 	 * For all set tests we only test the ACC and FP bits. RF and
66 	 * CH are set by the machine for memory references and changes
67 	 * and hence might change between a set and a get.
68 	 */
69 	report("set key test",
70 	       skey.str.acc == ret.str.acc && skey.str.fp == ret.str.fp);
71 }
72 
73 static void test_priv(void)
74 {
75 	union skey skey;
76 
77 	memset(pagebuf, 0, PAGE_SIZE * 2);
78 	report_prefix_push("privileged");
79 	report_prefix_push("sske");
80 	expect_pgm_int();
81 	enter_pstate();
82 	set_storage_key(page0, 0x30, 0);
83 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
84 	report_prefix_pop();
85 
86 	skey.val = get_storage_key(page0);
87 	report("skey did not change on exception", skey.str.acc != 3);
88 
89 	report_prefix_push("iske");
90 	expect_pgm_int();
91 	enter_pstate();
92 	get_storage_key(page0);
93 	check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION);
94 	report_prefix_pop();
95 
96 	report_prefix_pop();
97 }
98 
99 int main(void)
100 {
101 	report_prefix_push("skey");
102 	test_priv();
103 	test_set();
104 	test_set_mb();
105 	test_chg();
106 	report_prefix_pop();
107 	return report_summary();
108 }
109