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
test_diag(u32 instr)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
test_diags(void)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
test_epoch_ext(void)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
setup_guest(void)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
main(void)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