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