1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3 * Tests SIE diagnose intercepts.
4 * Mainly used as a template for SIE tests.
5 *
6 * Copyright 2021 IBM Corp.
7 *
8 * Authors:
9 * Janosch Frank <frankja@linux.ibm.com>
10 */
11 #include <libcflat.h>
12 #include <asm/asm-offsets.h>
13 #include <asm/arch_def.h>
14 #include <asm/interrupt.h>
15 #include <asm/page.h>
16 #include <alloc_page.h>
17 #include <vmalloc.h>
18 #include <asm/facility.h>
19 #include <mmu.h>
20 #include <sclp.h>
21 #include <sie.h>
22
23 static u8 *guest;
24 static u8 *guest_instr;
25 static struct vm vm;
26
test_diag(u32 instr)27 static void test_diag(u32 instr)
28 {
29 vm.sblk->gpsw.addr = PAGE_SIZE * 2;
30 vm.sblk->gpsw.mask = PSW_MASK_64;
31
32 memset(guest_instr, 0, PAGE_SIZE);
33 memcpy(guest_instr, &instr, 4);
34 sie(&vm);
35 report(vm.sblk->icptcode == ICPT_INST &&
36 vm.sblk->ipa == instr >> 16 && vm.sblk->ipb == instr << 16,
37 "Intercept data");
38 }
39
40 static struct {
41 const char *name;
42 u32 instr;
43 } tests[] = {
44 { "10", 0x83020010 },
45 { "44", 0x83020044 },
46 { "9c", 0x8302009c },
47 { NULL, 0 }
48 };
49
test_diags(void)50 static void test_diags(void)
51 {
52 int i;
53
54 for (i = 0; tests[i].name; i++) {
55 report_prefix_push(tests[i].name);
56 test_diag(tests[i].instr);
57 report_prefix_pop();
58 }
59 }
60
test_epoch_ext(void)61 static void test_epoch_ext(void)
62 {
63 u32 instr[] = {
64 0xb2780000, /* STCKE 0 */
65 0x83000044 /* DIAG 0x44 to intercept */
66 };
67
68 if (!test_facility(139)) {
69 report_skip("epdx: Multiple Epoch Facility is not available");
70 return;
71 }
72
73 guest[0] = 0x00;
74 memcpy(guest_instr, instr, sizeof(instr));
75
76 vm.sblk->gpsw.addr = PAGE_SIZE * 2;
77 vm.sblk->gpsw.mask = PSW_MASK_64;
78
79 vm.sblk->ecd |= ECD_MEF;
80 vm.sblk->epdx = 0x47; /* Setting the epoch extension here ... */
81
82 sie(&vm);
83
84 /* ... should result in the same epoch extension here: */
85 report(guest[0] == 0x47, "epdx: different epoch is visible in the guest");
86 }
87
setup_guest(void)88 static void setup_guest(void)
89 {
90 setup_vm();
91
92 guest = sie_guest_alloc(SZ_1M);
93
94 /* The first two pages are the lowcore */
95 guest_instr = guest + PAGE_SIZE * 2;
96
97 sie_guest_create(&vm, (uint64_t)guest, HPAGE_SIZE);
98 }
99
main(void)100 int main(void)
101 {
102 report_prefix_push("sie");
103 if (!sclp_facilities.has_sief2) {
104 report_skip("SIEF2 facility unavailable");
105 goto done;
106 }
107
108 setup_guest();
109 test_diags();
110 test_epoch_ext();
111 sie_guest_destroy(&vm);
112
113 done:
114 report_prefix_pop();
115 return report_summary();
116 }
117