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