xref: /kvm-unit-tests/s390x/sie.c (revision fdab948bc134fb9989a8265380a55e809879418e)
1 #include <libcflat.h>
2 #include <asm/asm-offsets.h>
3 #include <asm/arch_def.h>
4 #include <asm/interrupt.h>
5 #include <asm/page.h>
6 #include <alloc_page.h>
7 #include <vmalloc.h>
8 #include <asm/facility.h>
9 #include <mmu.h>
10 #include <sclp.h>
11 #include <sie.h>
12 
13 static u8 *guest;
14 static u8 *guest_instr;
15 static struct vm vm;
16 
17 static void handle_validity(struct vm *vm)
18 {
19 	report(0, "VALIDITY: %x", vm->sblk->ipb >> 16);
20 }
21 
22 static void sie(struct vm *vm)
23 {
24 	while (vm->sblk->icptcode == 0) {
25 		sie64a(vm->sblk, &vm->save_area);
26 		if (vm->sblk->icptcode == ICPT_VALIDITY)
27 			handle_validity(vm);
28 	}
29 	vm->save_area.guest.grs[14] = vm->sblk->gg14;
30 	vm->save_area.guest.grs[15] = vm->sblk->gg15;
31 }
32 
33 static void sblk_cleanup(struct vm *vm)
34 {
35 	vm->sblk->icptcode = 0;
36 }
37 
38 static void test_diag(u32 instr)
39 {
40 	vm.sblk->gpsw.addr = PAGE_SIZE * 2;
41 	vm.sblk->gpsw.mask = 0x0000000180000000ULL;
42 
43 	memset(guest_instr, 0, PAGE_SIZE);
44 	memcpy(guest_instr, &instr, 4);
45 	sie(&vm);
46 	report(vm.sblk->icptcode == ICPT_INST &&
47 	       vm.sblk->ipa == instr >> 16 && vm.sblk->ipb == instr << 16,
48 	       "Intercept data");
49 	sblk_cleanup(&vm);
50 }
51 
52 static struct {
53 	const char *name;
54 	u32 instr;
55 } tests[] = {
56 	{ "10", 0x83020010 },
57 	{ "44", 0x83020044 },
58 	{ "9c", 0x8302009c },
59 	{ NULL, 0 }
60 };
61 
62 static void test_diags(void)
63 {
64 	int i;
65 
66 	for (i = 0; tests[i].name; i++) {
67 		report_prefix_push(tests[i].name);
68 		test_diag(tests[i].instr);
69 		report_prefix_pop();
70 	}
71 }
72 
73 static void setup_guest(void)
74 {
75 	setup_vm();
76 
77 	/* Allocate 1MB as guest memory */
78 	guest = alloc_pages(8);
79 	/* The first two pages are the lowcore */
80 	guest_instr = guest + PAGE_SIZE * 2;
81 
82 	vm.sblk = alloc_page();
83 
84 	vm.sblk->cpuflags = CPUSTAT_ZARCH | CPUSTAT_RUNNING;
85 	vm.sblk->prefix = 0;
86 	/*
87 	 * Pageable guest with the same ASCE as the test programm, but
88 	 * the guest memory 0x0 is offset to start at the allocated
89 	 * guest pages and end after 1MB.
90 	 *
91 	 * It's not pretty but faster and easier than managing guest ASCEs.
92 	 */
93 	vm.sblk->mso = (u64)guest;
94 	vm.sblk->msl = (u64)guest;
95 	vm.sblk->ihcpu = 0xffff;
96 
97 	vm.sblk->crycbd = (uint64_t)alloc_page();
98 }
99 
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 done:
111 	report_prefix_pop();
112 	return report_summary();
113 }
114