xref: /kvm-unit-tests/s390x/gs.c (revision c9cda994b48d8e9bc0d001e0d3c5ed2c029a8687)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Tests guarded storage support.
4  *
5  * Copyright 2018 IBM Corp.
6  *
7  * Authors:
8  *    Martin Schwidefsky <schwidefsky@de.ibm.com>
9  *    Janosch Frank <frankja@linux.ibm.com>
10  */
11 #include <libcflat.h>
12 #include <asm/asm-offsets.h>
13 #include <asm/page.h>
14 #include <asm/facility.h>
15 #include <asm/interrupt.h>
16 #include <asm-generic/barrier.h>
17 #include <gs.h>
18 
19 static volatile int guarded = 0;
20 static struct gs_cb gs_cb;
21 static struct gs_epl gs_epl;
22 static unsigned long gs_area = 0x2000000;
23 
24 void gs_handler(struct gs_cb *this_cb);
25 
load_guarded(unsigned long * p)26 static inline unsigned long load_guarded(unsigned long *p)
27 {
28 	unsigned long v;
29 
30 	asm(".insn rxy,0xe3000000004c, %0,%1"
31 	    : "=d" (v)
32 	    : "m" (*p)
33 	    : "r14", "memory");
34 	return v;
35 }
36 
37 /* guarded-storage event handler and finally it calls gs_handler */
38 extern void gs_handler_asm(void);
39 	asm (          ".macro	STGSC	args:vararg\n"
40 		"	.insn	rxy,0xe30000000049,\\args\n"
41 		"	.endm\n"
42 		"	.globl	gs_handler_asm\n"
43 		"gs_handler_asm:\n"
44 		"	lgr	%r14,%r15\n"				/* Save current stack address in r14 */
45 		".Lgs_handler_frame = 16*8+32+" xstr(STACK_FRAME_SIZE) "\n"
46 		"	aghi	%r15,-(.Lgs_handler_frame)\n"		/* Allocate stack frame */
47 		"	stmg	%r0,%r13,192(%r15)\n"			/* Store regs to save area */
48 		"	stg	%r14,312(%r15)\n"
49 		"	la	%r2," xstr(STACK_FRAME_SIZE) "(%r15)\n"	/* Store gscb address in this_cb */
50 		"	STGSC	%r0," xstr(STACK_FRAME_SIZE) "(%r15)\n"
51 		"	lg	%r14,24(%r2)\n"				/* Get GSEPLA from GSCB*/
52 		"	lg	%r14,40(%r14)\n"			/* Get GSERA from GSEPL*/
53 		"	stg	%r14,304(%r15)\n"			/* Store GSERA in r14 of reg save area */
54 		"	brasl	%r14,gs_handler\n"			/* Jump to gs_handler */
55 		"	lmg	%r0,%r15,192(%r15)\n"			/* Restore regs */
56 		"	aghi	%r14, 6\n"				/* Add lgg instr len to GSERA */
57 		"	br	%r14\n"					/* Jump to next instruction after lgg */
58 		".size gs_handler_asm,.-gs_handler_asm\n"
59 	);
60 
gs_handler(struct gs_cb * this_cb)61 void gs_handler(struct gs_cb *this_cb)
62 {
63 	guarded = 1;
64 	struct gs_epl *gs_epl = (struct gs_epl *) this_cb->gs_epl_a;
65 	printf("gs_handler called for %016lx at %016lx\n",
66 	       gs_epl->gs_eir, gs_epl->gs_eia);
67 }
68 
69 /* Test if load guarded gets intercepted. */
test_load(void)70 static void test_load(void)
71 {
72 	unsigned long v;
73 
74 	guarded = 0;
75 	v = load_guarded(&gs_area);
76 	report(guarded, "load guarded %ld", v);
77 	guarded = 0;
78 }
79 
80 /* Test gs instructions without enablement resulting in an exception */
test_special(void)81 static void test_special(void)
82 {
83 	report_prefix_push("disabled gs");
84 	report_prefix_push("load gs");
85 	expect_pgm_int();
86 	load_gs_cb(&gs_cb);
87 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
88 	report_prefix_pop();
89 
90 	report_prefix_push("store gs");
91 	expect_pgm_int();
92 	store_gs_cb(&gs_cb);
93 	check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION);
94 	report_prefix_pop();
95 
96 	report_prefix_pop();
97 }
98 
init(void)99 static void init(void)
100 {
101 	/* Enable control bit for gs */
102 	ctl_set_bit(2, CTL2_GUARDED_STORAGE);
103 
104 	/* Setup gs registers to guard the gs_area */
105 	gs_cb.gsd = gs_area | 25;
106 
107 	/* Check all 512kb slots for events */
108 	gs_cb.gssm = 0xffffffffffffffffULL;
109 	gs_cb.gs_epl_a =  (unsigned long) &gs_epl;
110 
111 	/* Register handler */
112 	gs_epl.gs_eha = (unsigned long) gs_handler_asm;
113 	load_gs_cb(&gs_cb);
114 }
115 
main(void)116 int main(void)
117 {
118 	bool has_gs = test_facility(133);
119 
120 	report_prefix_push("gs");
121 	if (!has_gs) {
122 		report_skip("Guarded storage is not available");
123 		goto done;
124 	}
125 
126 	test_special();
127 	init();
128 	test_load();
129 
130 done:
131 	report_prefix_pop();
132 	return report_summary();
133 }
134