1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Diagnose 0x308 hypercall tests 4 * 5 * Copyright (c) 2019 Thomas Huth, Red Hat Inc. 6 */ 7 8 #include <libcflat.h> 9 #include <asm/asm-offsets.h> 10 #include <asm/interrupt.h> 11 12 /* The diagnose calls should be blocked in problem state */ 13 static void test_priv(void) 14 { 15 expect_pgm_int(); 16 enter_pstate(); 17 asm volatile ("diag %0,%1,0x308" :: "d"(0), "d"(3)); 18 check_pgm_int_code(PGM_INT_CODE_PRIVILEGED_OPERATION); 19 } 20 21 22 /* 23 * Check that diag308 with subcode 0 and 1 loads the PSW at address 0, i.e. 24 * that we can put a pointer into address 4 which then gets executed. 25 */ 26 extern int diag308_load_reset(u64); 27 static void test_subcode0(void) 28 { 29 report(diag308_load_reset(0), "load modified clear done"); 30 } 31 32 static void test_subcode1(void) 33 { 34 report(diag308_load_reset(1), "load normal reset done"); 35 } 36 37 /* Expect a specification exception when using an uneven register */ 38 static void test_uneven_reg(unsigned int subcode) 39 { 40 register unsigned long sc asm("6") = subcode; 41 register unsigned long r3 asm("9") = 0x2000; 42 43 report_prefix_push("uneven register"); 44 expect_pgm_int(); 45 asm volatile ("diag %0,%1,0x308" :: "d"(r3), "d"(sc)); 46 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 47 report_prefix_pop(); 48 } 49 50 /* Expect a specification exception when using an unaligned address */ 51 static void test_unaligned_address(unsigned int subcode) 52 { 53 register unsigned long sc asm("6") = subcode; 54 register unsigned long addr asm("8") = 54321; 55 56 report_prefix_push("unaligned address"); 57 expect_pgm_int(); 58 asm volatile ("diag %0,%1,0x308" :: "d"(addr), "d"(sc)); 59 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 60 report_prefix_pop(); 61 } 62 63 static void test_subcode5(void) 64 { 65 test_uneven_reg(5); 66 test_unaligned_address(5); 67 } 68 69 static void test_subcode6(void) 70 { 71 test_uneven_reg(6); 72 test_unaligned_address(6); 73 } 74 75 /* Unsupported subcodes should generate a specification exception */ 76 static void test_unsupported_subcode(void) 77 { 78 int subcodes[] = { 2, 0x101, 0xffff, 0x10001, -1 }; 79 int idx; 80 81 for (idx = 0; idx < ARRAY_SIZE(subcodes); idx++) { 82 report_prefix_pushf("0x%04x", subcodes[idx]); 83 expect_pgm_int(); 84 asm volatile ("diag %0,%1,0x308" :: "d"(0), "d"(subcodes[idx])); 85 check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); 86 report_prefix_pop(); 87 } 88 } 89 90 static struct { 91 const char *name; 92 void (*func)(void); 93 } tests[] = { 94 { "privileged", test_priv }, 95 { "subcode 0", test_subcode0 }, 96 { "subcode 1", test_subcode1 }, 97 { "subcode 5", test_subcode5 }, 98 { "subcode 6", test_subcode6 }, 99 { "unsupported", test_unsupported_subcode }, 100 { NULL, NULL } 101 }; 102 103 int main(int argc, char**argv) 104 { 105 int i; 106 107 report_prefix_push("diag308"); 108 for (i = 0; tests[i].name; i++) { 109 report_prefix_push(tests[i].name); 110 tests[i].func(); 111 report_prefix_pop(); 112 } 113 report_prefix_pop(); 114 115 return report_summary(); 116 } 117