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