xref: /kvm-unit-tests/s390x/pv-diags.c (revision 1f08a91a41402b0e032ecce8ed1b5952cbfca0ea)
12c96b77eSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
22c96b77eSJanosch Frank /*
32c96b77eSJanosch Frank  * PV virtualization interception tests for diagnose instructions.
42c96b77eSJanosch Frank  *
52c96b77eSJanosch Frank  * Copyright (c) 2021 IBM Corp
62c96b77eSJanosch Frank  *
72c96b77eSJanosch Frank  * Authors:
82c96b77eSJanosch Frank  *  Janosch Frank <frankja@linux.ibm.com>
92c96b77eSJanosch Frank  */
102c96b77eSJanosch Frank #include <libcflat.h>
112c96b77eSJanosch Frank #include <snippet.h>
12*dc142414SNina Schoetterl-Glausch #include <sie-icpt.h>
132c96b77eSJanosch Frank #include <sie.h>
14c4082444SJanosch Frank #include <sclp.h>
15c4082444SJanosch Frank #include <asm/facility.h>
162c96b77eSJanosch Frank 
172c96b77eSJanosch Frank static struct vm vm;
182c96b77eSJanosch Frank 
test_diag_500(void)192c96b77eSJanosch Frank static void test_diag_500(void)
202c96b77eSJanosch Frank {
211d0f08f4SJanosch Frank 	extern const char SNIPPET_NAME_START(asm, pv_diag_500)[];
221d0f08f4SJanosch Frank 	extern const char SNIPPET_NAME_END(asm, pv_diag_500)[];
231d0f08f4SJanosch Frank 	extern const char SNIPPET_HDR_START(asm, pv_diag_500)[];
241d0f08f4SJanosch Frank 	extern const char SNIPPET_HDR_END(asm, pv_diag_500)[];
251d0f08f4SJanosch Frank 	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_500);
261d0f08f4SJanosch Frank 	int size_gbin = SNIPPET_LEN(asm, pv_diag_500);
272c96b77eSJanosch Frank 
282c96b77eSJanosch Frank 	report_prefix_push("diag 0x500");
292c96b77eSJanosch Frank 
301d0f08f4SJanosch Frank 	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_500),
311d0f08f4SJanosch Frank 			SNIPPET_HDR_START(asm, pv_diag_500),
32b36f35a8SJanosch Frank 			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
332c96b77eSJanosch Frank 
342c96b77eSJanosch Frank 	sie(&vm);
35*dc142414SNina Schoetterl-Glausch 	report(sie_is_diag_icpt(&vm, 0x500), "intercept values");
362c96b77eSJanosch Frank 	report(vm.save_area.guest.grs[1] == 1 &&
372c96b77eSJanosch Frank 	       vm.save_area.guest.grs[2] == 2 &&
382c96b77eSJanosch Frank 	       vm.save_area.guest.grs[3] == 3 &&
392c96b77eSJanosch Frank 	       vm.save_area.guest.grs[4] == 4,
402c96b77eSJanosch Frank 	       "register values");
412c96b77eSJanosch Frank 	/*
422c96b77eSJanosch Frank 	 * Check if we can inject a PGM operand which we are always
432c96b77eSJanosch Frank 	 * allowed to do after a diag500 exit.
442c96b77eSJanosch Frank 	 */
452c96b77eSJanosch Frank 	vm.sblk->iictl = IICTL_CODE_OPERAND;
462c96b77eSJanosch Frank 	sie(&vm);
47*dc142414SNina Schoetterl-Glausch 	report(sie_is_diag_icpt(&vm, 0x9c) &&
48617f251fSJanosch Frank 	       vm.save_area.guest.grs[0] == PGM_INT_CODE_OPERAND,
492c96b77eSJanosch Frank 	       "operand exception");
502c96b77eSJanosch Frank 
512c96b77eSJanosch Frank 	/*
522c96b77eSJanosch Frank 	 * Check if we can inject a PGM specification which we are always
532c96b77eSJanosch Frank 	 * allowed to do after a diag500 exit.
542c96b77eSJanosch Frank 	 */
552c96b77eSJanosch Frank 	sie(&vm);
562c96b77eSJanosch Frank 	vm.sblk->iictl = IICTL_CODE_SPECIFICATION;
572c96b77eSJanosch Frank 	/* Inject PGM, next exit should be 9c */
582c96b77eSJanosch Frank 	sie(&vm);
59*dc142414SNina Schoetterl-Glausch 	report(sie_is_diag_icpt(&vm, 0x9c) &&
60617f251fSJanosch Frank 	       vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
612c96b77eSJanosch Frank 	       "specification exception");
622c96b77eSJanosch Frank 
632c96b77eSJanosch Frank 	/* No need for cleanup, just tear down the VM */
642c96b77eSJanosch Frank 	uv_destroy_guest(&vm);
652c96b77eSJanosch Frank 
662c96b77eSJanosch Frank 	report_prefix_pop();
672c96b77eSJanosch Frank }
682c96b77eSJanosch Frank 
692c96b77eSJanosch Frank 
test_diag_288(void)702c96b77eSJanosch Frank static void test_diag_288(void)
712c96b77eSJanosch Frank {
721d0f08f4SJanosch Frank 	extern const char SNIPPET_NAME_START(asm, pv_diag_288)[];
731d0f08f4SJanosch Frank 	extern const char SNIPPET_NAME_END(asm, pv_diag_288)[];
741d0f08f4SJanosch Frank 	extern const char SNIPPET_HDR_START(asm, pv_diag_288)[];
751d0f08f4SJanosch Frank 	extern const char SNIPPET_HDR_END(asm, pv_diag_288)[];
761d0f08f4SJanosch Frank 	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_288);
771d0f08f4SJanosch Frank 	int size_gbin = SNIPPET_LEN(asm, pv_diag_288);
782c96b77eSJanosch Frank 
792c96b77eSJanosch Frank 	report_prefix_push("diag 0x288");
802c96b77eSJanosch Frank 
811d0f08f4SJanosch Frank 	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_288),
821d0f08f4SJanosch Frank 			SNIPPET_HDR_START(asm, pv_diag_288),
83b36f35a8SJanosch Frank 			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
842c96b77eSJanosch Frank 
852c96b77eSJanosch Frank 	sie(&vm);
862c96b77eSJanosch Frank 	report(vm.sblk->icptcode == ICPT_PV_INSTR && vm.sblk->ipa == 0x8302 &&
872c96b77eSJanosch Frank 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x288,
882c96b77eSJanosch Frank 	       "intercept values");
892c96b77eSJanosch Frank 	report(vm.save_area.guest.grs[0] == 1 &&
902c96b77eSJanosch Frank 	       vm.save_area.guest.grs[1] == 2 &&
912c96b77eSJanosch Frank 	       vm.save_area.guest.grs[2] == 3,
922c96b77eSJanosch Frank 	       "register values");
932c96b77eSJanosch Frank 
942c96b77eSJanosch Frank 	/*
952c96b77eSJanosch Frank 	 * Check if we can inject a PGM spec which we are always
962c96b77eSJanosch Frank 	 * allowed to do after a diag288 exit.
972c96b77eSJanosch Frank 	 */
982c96b77eSJanosch Frank 	vm.sblk->iictl = IICTL_CODE_SPECIFICATION;
992c96b77eSJanosch Frank 	sie(&vm);
1002c96b77eSJanosch Frank 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
1012c96b77eSJanosch Frank 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c
1022c96b77eSJanosch Frank 	       && vm.save_area.guest.grs[0] == PGM_INT_CODE_SPECIFICATION,
1032c96b77eSJanosch Frank 	       "specification exception");
1042c96b77eSJanosch Frank 
1052c96b77eSJanosch Frank 	/* No need for cleanup, just tear down the VM */
1062c96b77eSJanosch Frank 	uv_destroy_guest(&vm);
1072c96b77eSJanosch Frank 
1082c96b77eSJanosch Frank 	report_prefix_pop();
1092c96b77eSJanosch Frank }
1102c96b77eSJanosch Frank 
test_diag_yield(void)1112c96b77eSJanosch Frank static void test_diag_yield(void)
1122c96b77eSJanosch Frank {
1131d0f08f4SJanosch Frank 	extern const char SNIPPET_NAME_START(asm, pv_diag_yield)[];
1141d0f08f4SJanosch Frank 	extern const char SNIPPET_NAME_END(asm, pv_diag_yield)[];
1151d0f08f4SJanosch Frank 	extern const char SNIPPET_HDR_START(asm, pv_diag_yield)[];
1161d0f08f4SJanosch Frank 	extern const char SNIPPET_HDR_END(asm, pv_diag_yield)[];
1171d0f08f4SJanosch Frank 	int size_hdr = SNIPPET_HDR_LEN(asm, pv_diag_yield);
1181d0f08f4SJanosch Frank 	int size_gbin = SNIPPET_LEN(asm, pv_diag_yield);
1192c96b77eSJanosch Frank 
1202c96b77eSJanosch Frank 	report_prefix_push("diag yield");
1212c96b77eSJanosch Frank 
1221d0f08f4SJanosch Frank 	snippet_pv_init(&vm, SNIPPET_NAME_START(asm, pv_diag_yield),
1231d0f08f4SJanosch Frank 			SNIPPET_HDR_START(asm, pv_diag_yield),
124b36f35a8SJanosch Frank 			size_gbin, size_hdr, SNIPPET_UNPACK_OFF);
1252c96b77eSJanosch Frank 
1262c96b77eSJanosch Frank 	/* 0x44 */
1272c96b77eSJanosch Frank 	report_prefix_push("0x44");
1282c96b77eSJanosch Frank 	sie(&vm);
1292c96b77eSJanosch Frank 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
1302c96b77eSJanosch Frank 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x44,
1312c96b77eSJanosch Frank 	       "intercept values");
1322c96b77eSJanosch Frank 	report_prefix_pop();
1332c96b77eSJanosch Frank 
1342c96b77eSJanosch Frank 	/* 0x9c */
1352c96b77eSJanosch Frank 	report_prefix_push("0x9c");
1362c96b77eSJanosch Frank 	sie(&vm);
1372c96b77eSJanosch Frank 	report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 &&
1382c96b77eSJanosch Frank 	       vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c,
1392c96b77eSJanosch Frank 	       "intercept values");
1402c96b77eSJanosch Frank 	report(vm.save_area.guest.grs[0] == 42, "r1 correct");
1412c96b77eSJanosch Frank 	report_prefix_pop();
1422c96b77eSJanosch Frank 
1432c96b77eSJanosch Frank 	uv_destroy_guest(&vm);
1442c96b77eSJanosch Frank 	report_prefix_pop();
1452c96b77eSJanosch Frank }
1462c96b77eSJanosch Frank 
1472c96b77eSJanosch Frank 
main(void)1482c96b77eSJanosch Frank int main(void)
1492c96b77eSJanosch Frank {
1502c96b77eSJanosch Frank 	report_prefix_push("pv-diags");
151ec6683adSJanosch Frank 	if (!uv_host_requirement_checks())
1522c96b77eSJanosch Frank 		goto done;
1532c96b77eSJanosch Frank 
1542c96b77eSJanosch Frank 	uv_setup_asces();
1552c96b77eSJanosch Frank 	snippet_setup_guest(&vm, true);
1562c96b77eSJanosch Frank 	test_diag_yield();
1572c96b77eSJanosch Frank 	test_diag_288();
1582c96b77eSJanosch Frank 	test_diag_500();
1592c96b77eSJanosch Frank 	sie_guest_destroy(&vm);
1602c96b77eSJanosch Frank 
1612c96b77eSJanosch Frank done:
1622c96b77eSJanosch Frank 	report_prefix_pop();
1632c96b77eSJanosch Frank 	return report_summary();
1642c96b77eSJanosch Frank }
165