xref: /kvm-unit-tests/s390x/pv-diags.c (revision c604fa931a1cb70c3649ac1b7223178fc79eab6a)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * PV virtualization interception tests for diagnose instructions.
4  *
5  * Copyright (c) 2021 IBM Corp
6  *
7  * Authors:
8  *  Janosch Frank <frankja@linux.ibm.com>
9  */
10 #include <libcflat.h>
11 #include <asm/asm-offsets.h>
12 #include <asm-generic/barrier.h>
13 #include <asm/interrupt.h>
14 #include <asm/pgtable.h>
15 #include <mmu.h>
16 #include <asm/page.h>
17 #include <asm/facility.h>
18 #include <asm/mem.h>
19 #include <asm/sigp.h>
20 #include <smp.h>
21 #include <alloc_page.h>
22 #include <vmalloc.h>
23 #include <sclp.h>
24 #include <snippet.h>
25 #include <sie.h>
26 #include <uv.h>
27 #include <asm/uv.h>
28 
29 static struct vm vm;
30 
31 static void test_diag_500(void)
32 {
33 	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_500)[];
34 	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_500)[];
35 	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_500)[];
36 	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_500)[];
37 	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_500);
38 	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_500);
39 
40 	report_prefix_push("diag 0x500");
41 
42 	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_500),
43 			SNIPPET_HDR_START(asm, snippet_pv_diag_500),
44 			size_gbin, size_hdr, SNIPPET_OFF_ASM);
45 
46 	sie(&vm);
47 	report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 &&
48 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x500,
49 	       "intercept values");
50 	report(vm.save_area.guest.grs[1] == 1 &&
51 	       vm.save_area.guest.grs[2] == 2 &&
52 	       vm.save_area.guest.grs[3] == 3 &&
53 	       vm.save_area.guest.grs[4] == 4,
54 	       "register values");
55 	/*
56 	 * Check if we can inject a PGM operand which we are always
57 	 * allowed to do after a diag500 exit.
58 	 */
59 	vm.sblk->iictl = IICTL_CODE_OPERAND;
60 	sie(&vm);
61 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
62 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
63 	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND,
64 	       "operand exception");
65 
66 	/*
67 	 * Check if we can inject a PGM specification which we are always
68 	 * allowed to do after a diag500 exit.
69 	 */
70 	sie(&vm);
71 	vm.sblk->iictl = IICTL_CODE_SPECIFICATION;
72 	/* Inject PGM, next exit should be 9c */
73 	sie(&vm);
74 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
75 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
76 	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
77 	       "specification exception");
78 
79 	/* No need for cleanup, just tear down the VM */
80 	uv_destroy_guest(&vm);
81 
82 	report_prefix_pop();
83 }
84 
85 
86 static void test_diag_288(void)
87 {
88 	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_288)[];
89 	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_288)[];
90 	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_288)[];
91 	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_288)[];
92 	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_288);
93 	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_288);
94 
95 	report_prefix_push("diag 0x288");
96 
97 	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_288),
98 			SNIPPET_HDR_START(asm, snippet_pv_diag_288),
99 			size_gbin, size_hdr, SNIPPET_OFF_ASM);
100 
101 	sie(&vm);
102 	report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 &&
103 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x288,
104 	       "intercept values");
105 	report(vm.save_area.guest.grs[0] == 1 &&
106 	       vm.save_area.guest.grs[1] == 2 &&
107 	       vm.save_area.guest.grs[2] == 3,
108 	       "register values");
109 
110 	/*
111 	 * Check if we can inject a PGM spec which we are always
112 	 * allowed to do after a diag288 exit.
113 	 */
114 	vm.sblk->iictl = IICTL_CODE_SPECIFICATION;
115 	sie(&vm);
116 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
117 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
118 	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
119 	       "specification exception");
120 
121 	/* No need for cleanup, just tear down the VM */
122 	uv_destroy_guest(&vm);
123 
124 	report_prefix_pop();
125 }
126 
127 static void test_diag_yield(void)
128 {
129 	extern const char SNIPPET_NAME_START(asm, snippet_pv_diag_yield)[];
130 	extern const char SNIPPET_NAME_END(asm, snippet_pv_diag_yield)[];
131 	extern const char SNIPPET_HDR_START(asm, snippet_pv_diag_yield)[];
132 	extern const char SNIPPET_HDR_END(asm, snippet_pv_diag_yield)[];
133 	int size_hdr = SNIPPET_HDR_LEN(asm, snippet_pv_diag_yield);
134 	int size_gbin = SNIPPET_LEN(asm, snippet_pv_diag_yield);
135 
136 	report_prefix_push("diag yield");
137 
138 	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, snippet_pv_diag_yield),
139 			SNIPPET_HDR_START(asm, snippet_pv_diag_yield),
140 			size_gbin, size_hdr, SNIPPET_OFF_ASM);
141 
142 	/* 0x44 */
143 	report_prefix_push("0x44");
144 	sie(&vm);
145 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
146 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x44,
147 	       "intercept values");
148 	report_prefix_pop();
149 
150 	/* 0x9c */
151 	report_prefix_push("0x9c");
152 	sie(&vm);
153 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
154 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c,
155 	       "intercept values");
156 	report(vm.save_area.guest.grs[0] == 42, "r1 correct");
157 	report_prefix_pop();
158 
159 	uv_destroy_guest(&vm);
160 	report_prefix_pop();
161 }
162 
163 
164 int main(void)
165 {
166 	report_prefix_push("pv-diags");
167 	if (!test_facility(158)) {
168 		report_skip("UV Call facility unavailable");
169 		goto done;
170 	}
171 	if (!sclp_facilities.has_sief2) {
172 		report_skip("SIEF2 facility unavailable");
173 		goto done;
174 	}
175 
176 	uv_setup_asces();
177 	snippet_setup_guest(&vm, true);
178 	test_diag_yield();
179 	test_diag_288();
180 	test_diag_500();
181 	sie_guest_destroy(&vm);
182 
183 done:
184 	report_prefix_pop();
185 	return report_summary();
186 }
187