xref: /kvm-unit-tests/s390x/sie.c (revision d75fac5f2596e49e22344d1a33c594988364d2a1)
1aa8794b1SJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
2aa8794b1SJanosch Frank /*
3aa8794b1SJanosch Frank  * Tests SIE diagnose intercepts.
4aa8794b1SJanosch Frank  * Mainly used as a template for SIE tests.
5aa8794b1SJanosch Frank  *
6aa8794b1SJanosch Frank  * Copyright 2021 IBM Corp.
7aa8794b1SJanosch Frank  *
8aa8794b1SJanosch Frank  * Authors:
9aa8794b1SJanosch Frank  *    Janosch Frank <frankja@linux.ibm.com>
10aa8794b1SJanosch Frank  */
119ec666ecSJanosch Frank #include <libcflat.h>
129ec666ecSJanosch Frank #include <asm/asm-offsets.h>
139ec666ecSJanosch Frank #include <asm/arch_def.h>
149ec666ecSJanosch Frank #include <asm/interrupt.h>
159ec666ecSJanosch Frank #include <asm/page.h>
169ec666ecSJanosch Frank #include <alloc_page.h>
179ec666ecSJanosch Frank #include <vmalloc.h>
189ec666ecSJanosch Frank #include <asm/facility.h>
199ec666ecSJanosch Frank #include <mmu.h>
209ec666ecSJanosch Frank #include <sclp.h>
219ec666ecSJanosch Frank #include <sie.h>
229ec666ecSJanosch Frank 
239ec666ecSJanosch Frank static u8 *guest;
249ec666ecSJanosch Frank static u8 *guest_instr;
259ec666ecSJanosch Frank static struct vm vm;
269ec666ecSJanosch Frank 
279ec666ecSJanosch Frank 
289ec666ecSJanosch Frank static void sie(struct vm *vm)
299ec666ecSJanosch Frank {
309ec666ecSJanosch Frank 	while (vm->sblk->icptcode == 0) {
319ec666ecSJanosch Frank 		sie64a(vm->sblk, &vm->save_area);
32*d75fac5fSJanosch Frank 		sie_handle_validity(vm);
339ec666ecSJanosch Frank 	}
349ec666ecSJanosch Frank 	vm->save_area.guest.grs[14] = vm->sblk->gg14;
359ec666ecSJanosch Frank 	vm->save_area.guest.grs[15] = vm->sblk->gg15;
369ec666ecSJanosch Frank }
379ec666ecSJanosch Frank 
389ec666ecSJanosch Frank static void sblk_cleanup(struct vm *vm)
399ec666ecSJanosch Frank {
409ec666ecSJanosch Frank 	vm->sblk->icptcode = 0;
419ec666ecSJanosch Frank }
429ec666ecSJanosch Frank 
439ec666ecSJanosch Frank static void test_diag(u32 instr)
449ec666ecSJanosch Frank {
459ec666ecSJanosch Frank 	vm.sblk->gpsw.addr = PAGE_SIZE * 2;
469ec666ecSJanosch Frank 	vm.sblk->gpsw.mask = 0x0000000180000000ULL;
479ec666ecSJanosch Frank 
489ec666ecSJanosch Frank 	memset(guest_instr, 0, PAGE_SIZE);
499ec666ecSJanosch Frank 	memcpy(guest_instr, &instr, 4);
509ec666ecSJanosch Frank 	sie(&vm);
519ec666ecSJanosch Frank 	report(vm.sblk->icptcode == ICPT_INST &&
529ec666ecSJanosch Frank 	       vm.sblk->ipa == instr >> 16 && vm.sblk->ipb == instr << 16,
539ec666ecSJanosch Frank 	       "Intercept data");
549ec666ecSJanosch Frank 	sblk_cleanup(&vm);
559ec666ecSJanosch Frank }
569ec666ecSJanosch Frank 
579ec666ecSJanosch Frank static struct {
589ec666ecSJanosch Frank 	const char *name;
599ec666ecSJanosch Frank 	u32 instr;
609ec666ecSJanosch Frank } tests[] = {
619ec666ecSJanosch Frank 	{ "10", 0x83020010 },
629ec666ecSJanosch Frank 	{ "44", 0x83020044 },
639ec666ecSJanosch Frank 	{ "9c", 0x8302009c },
649ec666ecSJanosch Frank 	{ NULL, 0 }
659ec666ecSJanosch Frank };
669ec666ecSJanosch Frank 
679ec666ecSJanosch Frank static void test_diags(void)
689ec666ecSJanosch Frank {
699ec666ecSJanosch Frank 	int i;
709ec666ecSJanosch Frank 
719ec666ecSJanosch Frank 	for (i = 0; tests[i].name; i++) {
729ec666ecSJanosch Frank 		report_prefix_push(tests[i].name);
739ec666ecSJanosch Frank 		test_diag(tests[i].instr);
749ec666ecSJanosch Frank 		report_prefix_pop();
759ec666ecSJanosch Frank 	}
769ec666ecSJanosch Frank }
779ec666ecSJanosch Frank 
789ec666ecSJanosch Frank static void setup_guest(void)
799ec666ecSJanosch Frank {
809ec666ecSJanosch Frank 	setup_vm();
819ec666ecSJanosch Frank 
829ec666ecSJanosch Frank 	/* Allocate 1MB as guest memory */
839ec666ecSJanosch Frank 	guest = alloc_pages(8);
849ec666ecSJanosch Frank 	/* The first two pages are the lowcore */
859ec666ecSJanosch Frank 	guest_instr = guest + PAGE_SIZE * 2;
869ec666ecSJanosch Frank 
879ec666ecSJanosch Frank 	vm.sblk = alloc_page();
889ec666ecSJanosch Frank 
899ec666ecSJanosch Frank 	vm.sblk->cpuflags = CPUSTAT_ZARCH | CPUSTAT_RUNNING;
909ec666ecSJanosch Frank 	vm.sblk->prefix = 0;
919ec666ecSJanosch Frank 	/*
929ec666ecSJanosch Frank 	 * Pageable guest with the same ASCE as the test programm, but
939ec666ecSJanosch Frank 	 * the guest memory 0x0 is offset to start at the allocated
949ec666ecSJanosch Frank 	 * guest pages and end after 1MB.
959ec666ecSJanosch Frank 	 *
969ec666ecSJanosch Frank 	 * It's not pretty but faster and easier than managing guest ASCEs.
979ec666ecSJanosch Frank 	 */
989ec666ecSJanosch Frank 	vm.sblk->mso = (u64)guest;
999ec666ecSJanosch Frank 	vm.sblk->msl = (u64)guest;
1009ec666ecSJanosch Frank 	vm.sblk->ihcpu = 0xffff;
1019ec666ecSJanosch Frank 
1029ec666ecSJanosch Frank 	vm.sblk->crycbd = (uint64_t)alloc_page();
1039ec666ecSJanosch Frank }
1049ec666ecSJanosch Frank 
1059ec666ecSJanosch Frank int main(void)
1069ec666ecSJanosch Frank {
1079ec666ecSJanosch Frank 	report_prefix_push("sie");
1089ec666ecSJanosch Frank 	if (!sclp_facilities.has_sief2) {
1099ec666ecSJanosch Frank 		report_skip("SIEF2 facility unavailable");
1109ec666ecSJanosch Frank 		goto done;
1119ec666ecSJanosch Frank 	}
1129ec666ecSJanosch Frank 
1139ec666ecSJanosch Frank 	setup_guest();
1149ec666ecSJanosch Frank 	test_diags();
1159ec666ecSJanosch Frank done:
1169ec666ecSJanosch Frank 	report_prefix_pop();
1179ec666ecSJanosch Frank 	return report_summary();
1189ec666ecSJanosch Frank }
119