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 static void test_diag(u32 instr) 289ec666ecSJanosch Frank { 299ec666ecSJanosch Frank vm.sblk->gpsw.addr = PAGE_SIZE * 2; 3044026818SJanosch Frank vm.sblk->gpsw.mask = PSW_MASK_64; 319ec666ecSJanosch Frank 329ec666ecSJanosch Frank memset(guest_instr, 0, PAGE_SIZE); 339ec666ecSJanosch Frank memcpy(guest_instr, &instr, 4); 349ec666ecSJanosch Frank sie(&vm); 359ec666ecSJanosch Frank report(vm.sblk->icptcode == ICPT_INST && 369ec666ecSJanosch Frank vm.sblk->ipa == instr >> 16 && vm.sblk->ipb == instr << 16, 379ec666ecSJanosch Frank "Intercept data"); 389ec666ecSJanosch Frank } 399ec666ecSJanosch Frank 409ec666ecSJanosch Frank static struct { 419ec666ecSJanosch Frank const char *name; 429ec666ecSJanosch Frank u32 instr; 439ec666ecSJanosch Frank } tests[] = { 449ec666ecSJanosch Frank { "10", 0x83020010 }, 459ec666ecSJanosch Frank { "44", 0x83020044 }, 469ec666ecSJanosch Frank { "9c", 0x8302009c }, 479ec666ecSJanosch Frank { NULL, 0 } 489ec666ecSJanosch Frank }; 499ec666ecSJanosch Frank 509ec666ecSJanosch Frank static void test_diags(void) 519ec666ecSJanosch Frank { 529ec666ecSJanosch Frank int i; 539ec666ecSJanosch Frank 549ec666ecSJanosch Frank for (i = 0; tests[i].name; i++) { 559ec666ecSJanosch Frank report_prefix_push(tests[i].name); 569ec666ecSJanosch Frank test_diag(tests[i].instr); 579ec666ecSJanosch Frank report_prefix_pop(); 589ec666ecSJanosch Frank } 599ec666ecSJanosch Frank } 609ec666ecSJanosch Frank 61f72ecf78SThomas Huth static void test_epoch_ext(void) 62f72ecf78SThomas Huth { 63f72ecf78SThomas Huth u32 instr[] = { 64f72ecf78SThomas Huth 0xb2780000, /* STCKE 0 */ 65f72ecf78SThomas Huth 0x83000044 /* DIAG 0x44 to intercept */ 66f72ecf78SThomas Huth }; 67f72ecf78SThomas Huth 68f72ecf78SThomas Huth if (!test_facility(139)) { 69f72ecf78SThomas Huth report_skip("epdx: Multiple Epoch Facility is not available"); 70f72ecf78SThomas Huth return; 71f72ecf78SThomas Huth } 72f72ecf78SThomas Huth 73f72ecf78SThomas Huth guest[0] = 0x00; 74f72ecf78SThomas Huth memcpy(guest_instr, instr, sizeof(instr)); 75f72ecf78SThomas Huth 76f72ecf78SThomas Huth vm.sblk->gpsw.addr = PAGE_SIZE * 2; 77f72ecf78SThomas Huth vm.sblk->gpsw.mask = PSW_MASK_64; 78f72ecf78SThomas Huth 79f72ecf78SThomas Huth vm.sblk->ecd |= ECD_MEF; 80f72ecf78SThomas Huth vm.sblk->epdx = 0x47; /* Setting the epoch extension here ... */ 81f72ecf78SThomas Huth 82f72ecf78SThomas Huth sie(&vm); 83f72ecf78SThomas Huth 84f72ecf78SThomas Huth /* ... should result in the same epoch extension here: */ 85f72ecf78SThomas Huth report(guest[0] == 0x47, "epdx: different epoch is visible in the guest"); 86f72ecf78SThomas Huth } 87f72ecf78SThomas Huth 889ec666ecSJanosch Frank static void setup_guest(void) 899ec666ecSJanosch Frank { 909ec666ecSJanosch Frank setup_vm(); 919ec666ecSJanosch Frank 92*ae337a39SNico Boehr guest = sie_guest_alloc(SZ_1M); 93*ae337a39SNico Boehr 949ec666ecSJanosch Frank /* The first two pages are the lowcore */ 959ec666ecSJanosch Frank guest_instr = guest + PAGE_SIZE * 2; 969ec666ecSJanosch Frank 97a58e5546SJanosch Frank sie_guest_create(&vm, (uint64_t)guest, HPAGE_SIZE); 989ec666ecSJanosch Frank } 999ec666ecSJanosch Frank 1009ec666ecSJanosch Frank int main(void) 1019ec666ecSJanosch Frank { 1029ec666ecSJanosch Frank report_prefix_push("sie"); 1039ec666ecSJanosch Frank if (!sclp_facilities.has_sief2) { 1049ec666ecSJanosch Frank report_skip("SIEF2 facility unavailable"); 1059ec666ecSJanosch Frank goto done; 1069ec666ecSJanosch Frank } 1079ec666ecSJanosch Frank 1089ec666ecSJanosch Frank setup_guest(); 1099ec666ecSJanosch Frank test_diags(); 110f72ecf78SThomas Huth test_epoch_ext(); 111a58e5546SJanosch Frank sie_guest_destroy(&vm); 112a58e5546SJanosch Frank 1139ec666ecSJanosch Frank done: 1149ec666ecSJanosch Frank report_prefix_pop(); 1159ec666ecSJanosch Frank return report_summary(); 1169ec666ecSJanosch Frank } 117