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