1a402fad4SJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
2a402fad4SJanosch Frank /*
3a402fad4SJanosch Frank * PV virtualization interception tests for intercepts that are not
4a402fad4SJanosch Frank * caused by an instruction.
5a402fad4SJanosch Frank *
6a402fad4SJanosch Frank * Copyright (c) 2023 IBM Corp
7a402fad4SJanosch Frank *
8a402fad4SJanosch Frank * Authors:
9a402fad4SJanosch Frank * Janosch Frank <frankja@linux.ibm.com>
10a402fad4SJanosch Frank */
11a402fad4SJanosch Frank #include <libcflat.h>
12a402fad4SJanosch Frank #include <sie.h>
13a402fad4SJanosch Frank #include <smp.h>
14a402fad4SJanosch Frank #include <sclp.h>
15a402fad4SJanosch Frank #include <snippet.h>
16*dc142414SNina Schoetterl-Glausch #include <sie-icpt.h>
17a402fad4SJanosch Frank #include <asm/facility.h>
18a402fad4SJanosch Frank #include <asm/barrier.h>
19a402fad4SJanosch Frank #include <asm/sigp.h>
20a402fad4SJanosch Frank #include <asm/uv.h>
21a402fad4SJanosch Frank #include <asm/time.h>
22a402fad4SJanosch Frank
23a402fad4SJanosch Frank static struct vm vm, vm2;
24a402fad4SJanosch Frank
25a402fad4SJanosch Frank /*
26a402fad4SJanosch Frank * The hypervisor should not be able to decrease the cpu timer by an
27a402fad4SJanosch Frank * amount that is higher than the amount of time spent outside of
28a402fad4SJanosch Frank * SIE.
29a402fad4SJanosch Frank *
30a402fad4SJanosch Frank * Warning: A lot of things influence time so decreasing the timer by
31a402fad4SJanosch Frank * a more significant amount than the difference to have a safety
32a402fad4SJanosch Frank * margin is advised.
33a402fad4SJanosch Frank */
test_validity_timing(void)34a402fad4SJanosch Frank static void test_validity_timing(void)
35a402fad4SJanosch Frank {
36a402fad4SJanosch Frank extern const char SNIPPET_NAME_START(asm, pv_icpt_vir_timing)[];
37a402fad4SJanosch Frank extern const char SNIPPET_NAME_END(asm, pv_icpt_vir_timing)[];
38a402fad4SJanosch Frank extern const char SNIPPET_HDR_START(asm, pv_icpt_vir_timing)[];
39a402fad4SJanosch Frank extern const char SNIPPET_HDR_END(asm, pv_icpt_vir_timing)[];
40a402fad4SJanosch Frank int size_hdr = SNIPPET_HDR_LEN(asm, pv_icpt_vir_timing);
41a402fad4SJanosch Frank int size_gbin = SNIPPET_LEN(asm, pv_icpt_vir_timing);
42a402fad4SJanosch Frank uint64_t time_exit, time_entry, tmp;
43a402fad4SJanosch Frank
44a402fad4SJanosch Frank report_prefix_push("manipulated cpu time");
45a402fad4SJanosch Frank snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_icpt_vir_timing),
46a402fad4SJanosch Frank SNIPPET_HDR_START(asm, pv_icpt_vir_timing),
47a402fad4SJanosch Frank size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
48a402fad4SJanosch Frank
49a402fad4SJanosch Frank sie(&vm);
50*dc142414SNina Schoetterl-Glausch report(sie_is_diag_icpt(&vm, 0x44), "spt done");
51a402fad4SJanosch Frank stck(&time_exit);
52a402fad4SJanosch Frank tmp = vm.sblk->cputm;
53a402fad4SJanosch Frank mb();
54a402fad4SJanosch Frank
55a402fad4SJanosch Frank /* Cpu timer counts down so adding a ms should lead to a validity */
56a402fad4SJanosch Frank vm.sblk->cputm += S390_CLOCK_SHIFT_US * 1000;
57a402fad4SJanosch Frank sie_expect_validity(&vm);
58a402fad4SJanosch Frank sie(&vm);
59a402fad4SJanosch Frank report(uv_validity_check(&vm), "validity entry cput > exit cput");
60a402fad4SJanosch Frank vm.sblk->cputm = tmp;
61a402fad4SJanosch Frank
62a402fad4SJanosch Frank /*
63a402fad4SJanosch Frank * We are not allowed to decrement the timer more than the
64a402fad4SJanosch Frank * time spent outside of SIE
65a402fad4SJanosch Frank */
66a402fad4SJanosch Frank stck(&time_entry);
67a402fad4SJanosch Frank vm.sblk->cputm -= (time_entry - time_exit) + S390_CLOCK_SHIFT_US * 1000;
68a402fad4SJanosch Frank sie_expect_validity(&vm);
69a402fad4SJanosch Frank sie(&vm);
70a402fad4SJanosch Frank report(uv_validity_check(&vm), "validity entry cput < time spent outside SIE");
71a402fad4SJanosch Frank vm.sblk->cputm = tmp;
72a402fad4SJanosch Frank
73a402fad4SJanosch Frank uv_destroy_guest(&vm);
74a402fad4SJanosch Frank report_prefix_pop();
75a402fad4SJanosch Frank }
76a402fad4SJanosch Frank
run_loop(void)77a402fad4SJanosch Frank static void run_loop(void)
78a402fad4SJanosch Frank {
79a402fad4SJanosch Frank sie(&vm);
80a402fad4SJanosch Frank sigp_retry(stap(), SIGP_STOP, 0, NULL);
81a402fad4SJanosch Frank }
82a402fad4SJanosch Frank
test_validity_already_running(void)83a402fad4SJanosch Frank static void test_validity_already_running(void)
84a402fad4SJanosch Frank {
85a402fad4SJanosch Frank extern const char SNIPPET_NAME_START(asm, loop)[];
86a402fad4SJanosch Frank extern const char SNIPPET_NAME_END(asm, loop)[];
87a402fad4SJanosch Frank extern const char SNIPPET_HDR_START(asm, loop)[];
88a402fad4SJanosch Frank extern const char SNIPPET_HDR_END(asm, loop)[];
89a402fad4SJanosch Frank int size_hdr = SNIPPET_HDR_LEN(asm, loop);
90a402fad4SJanosch Frank int size_gbin = SNIPPET_LEN(asm, loop);
91a402fad4SJanosch Frank struct psw psw = {
92a402fad4SJanosch Frank .mask = PSW_MASK_64,
93a402fad4SJanosch Frank .addr = (uint64_t)run_loop,
94a402fad4SJanosch Frank };
95a402fad4SJanosch Frank
96a402fad4SJanosch Frank report_prefix_push("already running");
97a402fad4SJanosch Frank if (smp_query_num_cpus() < 3) {
98a402fad4SJanosch Frank report_skip("need at least 3 cpus for this test");
99a402fad4SJanosch Frank goto out;
100a402fad4SJanosch Frank }
101a402fad4SJanosch Frank
102a402fad4SJanosch Frank snippet_pv_init(&vm, SNIPPET_NAME_START(asm, loop),
103a402fad4SJanosch Frank SNIPPET_HDR_START(asm, loop),
104a402fad4SJanosch Frank size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
105a402fad4SJanosch Frank
106a402fad4SJanosch Frank smp_cpu_setup(1, psw);
107a402fad4SJanosch Frank sie_expect_validity(&vm);
108a402fad4SJanosch Frank smp_cpu_setup(2, psw);
109a402fad4SJanosch Frank while (vm.sblk->icptcode != ICPT_VALIDITY) {
110a402fad4SJanosch Frank mb();
111a402fad4SJanosch Frank }
112a402fad4SJanosch Frank
113a402fad4SJanosch Frank /*
114a402fad4SJanosch Frank * One cpu will enter SIE and one will receive the validity.
115a402fad4SJanosch Frank * We rely on the expectation that the cpu in SIE won't exit
116a402fad4SJanosch Frank * until we had a chance to observe the validity as the exit
117a402fad4SJanosch Frank * would overwrite the validity.
118a402fad4SJanosch Frank *
119a402fad4SJanosch Frank * In general that expectation is valid but HW/FW can in
120a402fad4SJanosch Frank * theory still exit to handle their interrupts.
121a402fad4SJanosch Frank */
122a402fad4SJanosch Frank report(uv_validity_check(&vm), "validity");
123a402fad4SJanosch Frank smp_cpu_stop(1);
124a402fad4SJanosch Frank smp_cpu_stop(2);
125a402fad4SJanosch Frank uv_destroy_guest(&vm);
126a402fad4SJanosch Frank
127a402fad4SJanosch Frank out:
128a402fad4SJanosch Frank report_prefix_pop();
129a402fad4SJanosch Frank }
130a402fad4SJanosch Frank
131a402fad4SJanosch Frank /* Tests if a vcpu handle from another configuration results in a validity intercept. */
test_validity_handle_not_in_config(void)132a402fad4SJanosch Frank static void test_validity_handle_not_in_config(void)
133a402fad4SJanosch Frank {
134a402fad4SJanosch Frank extern const char SNIPPET_NAME_START(asm, icpt_loop)[];
135a402fad4SJanosch Frank extern const char SNIPPET_NAME_END(asm, icpt_loop)[];
136a402fad4SJanosch Frank extern const char SNIPPET_HDR_START(asm, icpt_loop)[];
137a402fad4SJanosch Frank extern const char SNIPPET_HDR_END(asm, icpt_loop)[];
138a402fad4SJanosch Frank int size_hdr = SNIPPET_HDR_LEN(asm, icpt_loop);
139a402fad4SJanosch Frank int size_gbin = SNIPPET_LEN(asm, icpt_loop);
140a402fad4SJanosch Frank
141a402fad4SJanosch Frank report_prefix_push("handle not in config");
142a402fad4SJanosch Frank /* Setup our primary vm */
143a402fad4SJanosch Frank snippet_pv_init(&vm, SNIPPET_NAME_START(asm, icpt_loop),
144a402fad4SJanosch Frank SNIPPET_HDR_START(asm, icpt_loop),
145a402fad4SJanosch Frank size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
146a402fad4SJanosch Frank
147a402fad4SJanosch Frank /* Setup secondary vm */
148a402fad4SJanosch Frank snippet_setup_guest(&vm2, true);
149a402fad4SJanosch Frank snippet_pv_init(&vm2, SNIPPET_NAME_START(asm, icpt_loop),
150a402fad4SJanosch Frank SNIPPET_HDR_START(asm, icpt_loop),
151a402fad4SJanosch Frank size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
152a402fad4SJanosch Frank
153a402fad4SJanosch Frank vm.sblk->pv_handle_cpu = vm2.sblk->pv_handle_cpu;
154a402fad4SJanosch Frank sie_expect_validity(&vm);
155a402fad4SJanosch Frank sie(&vm);
156a402fad4SJanosch Frank report(uv_validity_check(&vm), "switched cpu handle");
157a402fad4SJanosch Frank vm.sblk->pv_handle_cpu = vm.uv.vcpu_handle;
158a402fad4SJanosch Frank
159a402fad4SJanosch Frank vm.sblk->pv_handle_config = vm2.uv.vm_handle;
160a402fad4SJanosch Frank sie_expect_validity(&vm);
161a402fad4SJanosch Frank sie(&vm);
162a402fad4SJanosch Frank report(uv_validity_check(&vm), "switched configuration handle");
163a402fad4SJanosch Frank vm.sblk->pv_handle_config = vm.uv.vm_handle;
164a402fad4SJanosch Frank
165a402fad4SJanosch Frank /* Destroy the second vm, since we don't need it for further tests */
166a402fad4SJanosch Frank uv_destroy_guest(&vm2);
167a402fad4SJanosch Frank sie_guest_destroy(&vm2);
168a402fad4SJanosch Frank
169a402fad4SJanosch Frank uv_destroy_guest(&vm);
170a402fad4SJanosch Frank report_prefix_pop();
171a402fad4SJanosch Frank }
172a402fad4SJanosch Frank
173a402fad4SJanosch Frank /* Tests if a wrong vm or vcpu handle results in a validity intercept. */
test_validity_seid(void)174a402fad4SJanosch Frank static void test_validity_seid(void)
175a402fad4SJanosch Frank {
176a402fad4SJanosch Frank extern const char SNIPPET_NAME_START(asm, icpt_loop)[];
177a402fad4SJanosch Frank extern const char SNIPPET_NAME_END(asm, icpt_loop)[];
178a402fad4SJanosch Frank extern const char SNIPPET_HDR_START(asm, icpt_loop)[];
179a402fad4SJanosch Frank extern const char SNIPPET_HDR_END(asm, icpt_loop)[];
180a402fad4SJanosch Frank int size_hdr = SNIPPET_HDR_LEN(asm, icpt_loop);
181a402fad4SJanosch Frank int size_gbin = SNIPPET_LEN(asm, icpt_loop);
182a402fad4SJanosch Frank int fails = 0;
183a402fad4SJanosch Frank int i;
184a402fad4SJanosch Frank
185a402fad4SJanosch Frank report_prefix_push("handles");
186a402fad4SJanosch Frank snippet_pv_init(&vm, SNIPPET_NAME_START(asm, icpt_loop),
187a402fad4SJanosch Frank SNIPPET_HDR_START(asm, icpt_loop),
188a402fad4SJanosch Frank size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
189a402fad4SJanosch Frank
190a402fad4SJanosch Frank for (i = 0; i < 64; i++) {
191a402fad4SJanosch Frank vm.sblk->pv_handle_config ^= 1UL << i;
192a402fad4SJanosch Frank sie_expect_validity(&vm);
193a402fad4SJanosch Frank sie(&vm);
194a402fad4SJanosch Frank if (!uv_validity_check(&vm)) {
195a402fad4SJanosch Frank report_fail("SIE accepted wrong VM SEID, changed bit %d",
196a402fad4SJanosch Frank 63 - i);
197a402fad4SJanosch Frank fails++;
198a402fad4SJanosch Frank }
199a402fad4SJanosch Frank vm.sblk->pv_handle_config ^= 1UL << i;
200a402fad4SJanosch Frank }
201a402fad4SJanosch Frank report(!fails, "No wrong vm handle accepted");
202a402fad4SJanosch Frank
203a402fad4SJanosch Frank fails = 0;
204a402fad4SJanosch Frank for (i = 0; i < 64; i++) {
205a402fad4SJanosch Frank vm.sblk->pv_handle_cpu ^= 1UL << i;
206a402fad4SJanosch Frank sie_expect_validity(&vm);
207a402fad4SJanosch Frank sie(&vm);
208a402fad4SJanosch Frank if (!uv_validity_check(&vm)) {
209a402fad4SJanosch Frank report_fail("SIE accepted wrong CPU SEID, changed bit %d",
210a402fad4SJanosch Frank 63 - i);
211a402fad4SJanosch Frank fails++;
212a402fad4SJanosch Frank }
213a402fad4SJanosch Frank vm.sblk->pv_handle_cpu ^= 1UL << i;
214a402fad4SJanosch Frank }
215a402fad4SJanosch Frank report(!fails, "No wrong cpu handle accepted");
216a402fad4SJanosch Frank
217a402fad4SJanosch Frank uv_destroy_guest(&vm);
218a402fad4SJanosch Frank report_prefix_pop();
219a402fad4SJanosch Frank }
220a402fad4SJanosch Frank
221a402fad4SJanosch Frank /*
222a402fad4SJanosch Frank * Tests if we get a validity intercept if the CR1 asce at SIE entry
223a402fad4SJanosch Frank * is not the same as the one given at the UV creation of the VM.
224a402fad4SJanosch Frank */
test_validity_asce(void)225a402fad4SJanosch Frank static void test_validity_asce(void)
226a402fad4SJanosch Frank {
227a402fad4SJanosch Frank extern const char SNIPPET_NAME_START(asm, pv_icpt_112)[];
228a402fad4SJanosch Frank extern const char SNIPPET_NAME_END(asm, pv_icpt_112)[];
229a402fad4SJanosch Frank extern const char SNIPPET_HDR_START(asm, pv_icpt_112)[];
230a402fad4SJanosch Frank extern const char SNIPPET_HDR_END(asm, pv_icpt_112)[];
231a402fad4SJanosch Frank int size_hdr = SNIPPET_HDR_LEN(asm, pv_icpt_112);
232a402fad4SJanosch Frank int size_gbin = SNIPPET_LEN(asm, pv_icpt_112);
233a402fad4SJanosch Frank uint64_t asce_old, asce_new;
234a402fad4SJanosch Frank void *pgd_new, *pgd_old;
235a402fad4SJanosch Frank
236a402fad4SJanosch Frank report_prefix_push("asce");
237a402fad4SJanosch Frank snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_icpt_112),
238a402fad4SJanosch Frank SNIPPET_HDR_START(asm, pv_icpt_112),
239a402fad4SJanosch Frank size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
240a402fad4SJanosch Frank
241a402fad4SJanosch Frank asce_old = vm.save_area.guest.asce;
242a402fad4SJanosch Frank pgd_new = memalign_pages_flags(PAGE_SIZE, PAGE_SIZE * 4, 0);
243a402fad4SJanosch Frank pgd_old = (void *)(asce_old & PAGE_MASK);
244a402fad4SJanosch Frank
245a402fad4SJanosch Frank /* Copy the contents of the top most table */
246a402fad4SJanosch Frank memcpy(pgd_new, pgd_old, PAGE_SIZE * 4);
247a402fad4SJanosch Frank
248a402fad4SJanosch Frank /* Create the replacement ASCE */
249a402fad4SJanosch Frank asce_new = __pa(pgd_new) | ASCE_DT_REGION1 | REGION_TABLE_LENGTH | ASCE_P;
250a402fad4SJanosch Frank vm.save_area.guest.asce = asce_new;
251a402fad4SJanosch Frank
252a402fad4SJanosch Frank sie_expect_validity(&vm);
253a402fad4SJanosch Frank sie(&vm);
254a402fad4SJanosch Frank report(uv_validity_check(&vm), "wrong CR1 validity");
255a402fad4SJanosch Frank
256a402fad4SJanosch Frank /* Restore the old ASCE */
257a402fad4SJanosch Frank vm.save_area.guest.asce = asce_old;
258a402fad4SJanosch Frank
259a402fad4SJanosch Frank /* Try if we can still do an entry with the correct asce */
260a402fad4SJanosch Frank sie(&vm);
261*dc142414SNina Schoetterl-Glausch report(sie_is_diag_icpt(&vm, 0x44), "re-entry with valid CR1");
262a402fad4SJanosch Frank uv_destroy_guest(&vm);
263a402fad4SJanosch Frank free_pages(pgd_new);
264a402fad4SJanosch Frank report_prefix_pop();
265a402fad4SJanosch Frank }
266a402fad4SJanosch Frank
run_icpt_122_tests(unsigned long lc_off)267a402fad4SJanosch Frank static void run_icpt_122_tests(unsigned long lc_off)
268a402fad4SJanosch Frank {
269a402fad4SJanosch Frank uv_export(vm.sblk->mso + lc_off);
270a402fad4SJanosch Frank sie(&vm);
271a402fad4SJanosch Frank report(vm.sblk->icptcode == ICPT_PV_PREF, "Intercept 112 for page 0");
272a402fad4SJanosch Frank uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off);
273a402fad4SJanosch Frank
274a402fad4SJanosch Frank uv_export(vm.sblk->mso + lc_off + PAGE_SIZE);
275a402fad4SJanosch Frank sie(&vm);
276a402fad4SJanosch Frank report(vm.sblk->icptcode == ICPT_PV_PREF, "Intercept 112 for page 1");
277a402fad4SJanosch Frank uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off + PAGE_SIZE);
278a402fad4SJanosch Frank }
279a402fad4SJanosch Frank
run_icpt_122_tests_prefix(unsigned long prefix)280a402fad4SJanosch Frank static void run_icpt_122_tests_prefix(unsigned long prefix)
281a402fad4SJanosch Frank {
282a402fad4SJanosch Frank uint32_t *ptr = 0;
283a402fad4SJanosch Frank
284a402fad4SJanosch Frank report_prefix_pushf("0x%lx", prefix);
285a402fad4SJanosch Frank report_prefix_push("unshared");
286a402fad4SJanosch Frank run_icpt_122_tests(prefix);
287a402fad4SJanosch Frank report_prefix_pop();
288a402fad4SJanosch Frank
289a402fad4SJanosch Frank /*
290a402fad4SJanosch Frank * Guest will share the lowcore and we need to check if that
291a402fad4SJanosch Frank * makes a difference (which it should not).
292a402fad4SJanosch Frank */
293a402fad4SJanosch Frank report_prefix_push("shared");
294a402fad4SJanosch Frank
295a402fad4SJanosch Frank sie(&vm);
296a402fad4SJanosch Frank /* Guest indicates that it has been setup via the diag 0x44 */
297*dc142414SNina Schoetterl-Glausch assert(sie_is_diag_icpt(&vm, 0x44));
298a402fad4SJanosch Frank /* If the pages have not been shared these writes will cause exceptions */
299a402fad4SJanosch Frank ptr = (uint32_t *)prefix;
300a402fad4SJanosch Frank WRITE_ONCE(ptr, 0);
301a402fad4SJanosch Frank ptr = (uint32_t *)(prefix + offsetof(struct lowcore, ars_sa[0]));
302a402fad4SJanosch Frank WRITE_ONCE(ptr, 0);
303a402fad4SJanosch Frank
304a402fad4SJanosch Frank run_icpt_122_tests(prefix);
305a402fad4SJanosch Frank
306a402fad4SJanosch Frank /* shared*/
307a402fad4SJanosch Frank report_prefix_pop();
308a402fad4SJanosch Frank /* prefix hex value */
309a402fad4SJanosch Frank report_prefix_pop();
310a402fad4SJanosch Frank }
311a402fad4SJanosch Frank
test_icpt_112(void)312a402fad4SJanosch Frank static void test_icpt_112(void)
313a402fad4SJanosch Frank {
314a402fad4SJanosch Frank extern const char SNIPPET_NAME_START(asm, pv_icpt_112)[];
315a402fad4SJanosch Frank extern const char SNIPPET_NAME_END(asm, pv_icpt_112)[];
316a402fad4SJanosch Frank extern const char SNIPPET_HDR_START(asm, pv_icpt_112)[];
317a402fad4SJanosch Frank extern const char SNIPPET_HDR_END(asm, pv_icpt_112)[];
318a402fad4SJanosch Frank int size_hdr = SNIPPET_HDR_LEN(asm, pv_icpt_112);
319a402fad4SJanosch Frank int size_gbin = SNIPPET_LEN(asm, pv_icpt_112);
320a402fad4SJanosch Frank
321a402fad4SJanosch Frank unsigned long lc_off = 0;
322a402fad4SJanosch Frank
323a402fad4SJanosch Frank report_prefix_push("prefix");
324a402fad4SJanosch Frank
325a402fad4SJanosch Frank snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_icpt_112),
326a402fad4SJanosch Frank SNIPPET_HDR_START(asm, pv_icpt_112),
327a402fad4SJanosch Frank size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
328a402fad4SJanosch Frank
329a402fad4SJanosch Frank /* Setup of the guest's state for 0x0 prefix */
330a402fad4SJanosch Frank sie(&vm);
331*dc142414SNina Schoetterl-Glausch assert(sie_is_diag_icpt(&vm, 0x44));
332a402fad4SJanosch Frank
333a402fad4SJanosch Frank /* Test on standard 0x0 prefix */
334a402fad4SJanosch Frank run_icpt_122_tests_prefix(0);
335a402fad4SJanosch Frank
336a402fad4SJanosch Frank /* Setup of the guest's state for 0x8000 prefix */
337a402fad4SJanosch Frank lc_off = 0x8000;
338a402fad4SJanosch Frank uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off);
339a402fad4SJanosch Frank uv_import(vm.uv.vm_handle, vm.sblk->mso + lc_off + PAGE_SIZE);
340a402fad4SJanosch Frank /* Guest will set prefix to 0x8000 */
341a402fad4SJanosch Frank sie(&vm);
342a402fad4SJanosch Frank /* SPX generates a PV instruction notification */
343a402fad4SJanosch Frank assert(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0xb210);
344a402fad4SJanosch Frank assert(*(u32 *)vm.sblk->sidad == 0x8000);
345a402fad4SJanosch Frank
346a402fad4SJanosch Frank /* Test on 0x8000 prefix */
347a402fad4SJanosch Frank run_icpt_122_tests_prefix(0x8000);
348a402fad4SJanosch Frank
349a402fad4SJanosch Frank /* Try a re-entry after everything has been imported again */
350a402fad4SJanosch Frank sie(&vm);
351*dc142414SNina Schoetterl-Glausch report(sie_is_diag_icpt(&vm, 0x9c) &&
352a402fad4SJanosch Frank vm.save_area.guest.grs[0] == 42,
353a402fad4SJanosch Frank "re-entry successful");
354a402fad4SJanosch Frank report_prefix_pop();
355a402fad4SJanosch Frank uv_destroy_guest(&vm);
356a402fad4SJanosch Frank }
357a402fad4SJanosch Frank
main(void)358a402fad4SJanosch Frank int main(void)
359a402fad4SJanosch Frank {
360a402fad4SJanosch Frank report_prefix_push("pv-icpts");
361a402fad4SJanosch Frank if (!uv_host_requirement_checks())
362a402fad4SJanosch Frank goto done;
363a402fad4SJanosch Frank
364a402fad4SJanosch Frank snippet_setup_guest(&vm, true);
365a402fad4SJanosch Frank test_icpt_112();
366a402fad4SJanosch Frank test_validity_asce();
367a402fad4SJanosch Frank test_validity_seid();
368a402fad4SJanosch Frank test_validity_handle_not_in_config();
369a402fad4SJanosch Frank test_validity_already_running();
370a402fad4SJanosch Frank test_validity_timing();
371a402fad4SJanosch Frank sie_guest_destroy(&vm);
372a402fad4SJanosch Frank
373a402fad4SJanosch Frank done:
374a402fad4SJanosch Frank report_prefix_pop();
375a402fad4SJanosch Frank return report_summary();
376a402fad4SJanosch Frank }
377