1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Tests guarded storage support. 4 * 5 * Copyright 2018 IBM Corp. 6 * 7 * Authors: 8 * Martin Schwidefsky <schwidefsky@de.ibm.com> 9 * Janosch Frank <frankja@linux.ibm.com> 10 */ 11 #include <libcflat.h> 12 #include <asm/page.h> 13 #include <asm/facility.h> 14 #include <asm/interrupt.h> 15 #include <asm-generic/barrier.h> 16 17 struct gs_cb { 18 uint64_t reserved; 19 uint64_t gsd; 20 uint64_t gssm; 21 uint64_t gs_epl_a; 22 }; 23 24 struct gs_epl { 25 uint8_t pad1; 26 union { 27 uint8_t gs_eam; 28 struct { 29 uint8_t : 6; 30 uint8_t e : 1; 31 uint8_t b : 1; 32 }; 33 }; 34 union { 35 uint8_t gs_eci; 36 struct { 37 uint8_t tx : 1; 38 uint8_t cx : 1; 39 uint8_t : 5; 40 uint8_t in : 1; 41 }; 42 }; 43 union { 44 uint8_t gs_eai; 45 struct { 46 uint8_t : 1; 47 uint8_t t : 1; 48 uint8_t as : 2; 49 uint8_t ar : 4; 50 }; 51 }; 52 uint32_t pad2; 53 uint64_t gs_eha; 54 uint64_t gs_eia; 55 uint64_t gs_eoa; 56 uint64_t gs_eir; 57 uint64_t gs_era; 58 }; 59 60 static volatile int guarded = 0; 61 static struct gs_cb gs_cb; 62 static struct gs_epl gs_epl; 63 static unsigned long gs_area = 0x2000000; 64 65 void gs_handler(struct gs_cb *this_cb); 66 67 static inline void load_gs_cb(struct gs_cb *gs_cb) 68 { 69 asm volatile(".insn rxy,0xe3000000004d,0,%0" : : "Q" (*gs_cb)); 70 } 71 72 static inline void store_gs_cb(struct gs_cb *gs_cb) 73 { 74 asm volatile(".insn rxy,0xe30000000049,0,%0" : : "Q" (*gs_cb)); 75 } 76 77 static inline unsigned long load_guarded(unsigned long *p) 78 { 79 unsigned long v; 80 81 asm(".insn rxy,0xe3000000004c, %0,%1" 82 : "=d" (v) 83 : "m" (*p) 84 : "r14", "memory"); 85 return v; 86 } 87 88 /* guarded-storage event handler and finally it calls gs_handler */ 89 extern void gs_handler_asm(void); 90 asm(".globl gs_handler_asm\n" 91 "gs_handler_asm:\n" 92 " lgr %r14,%r15\n" /* Save current stack address in r14 */ 93 " aghi %r15,-320\n" /* Allocate stack frame */ 94 " stmg %r0,%r13,192(%r15)\n" /* Store regs to save area */ 95 " stg %r14,312(%r15)\n" 96 " la %r2,160(%r15)\n" /* Store gscb address in this_cb */ 97 " .insn rxy,0xe30000000049,0,160(%r15)\n" /* stgsc */ 98 " lg %r14,24(%r2)\n" /* Get GSEPLA from GSCB*/ 99 " lg %r14,40(%r14)\n" /* Get GSERA from GSEPL*/ 100 " stg %r14,304(%r15)\n" /* Store GSERA in r14 of reg save area */ 101 " brasl %r14,gs_handler\n" /* Jump to gs_handler */ 102 " lmg %r0,%r15,192(%r15)\n" /* Restore regs */ 103 " aghi %r14, 6\n" /* Add lgg instr len to GSERA */ 104 " br %r14\n" /* Jump to next instruction after lgg */ 105 " .size gs_handler_asm,.-gs_handler_asm\n"); 106 107 void gs_handler(struct gs_cb *this_cb) 108 { 109 guarded = 1; 110 struct gs_epl *gs_epl = (struct gs_epl *) this_cb->gs_epl_a; 111 printf("gs_handler called for %016lx at %016lx\n", 112 gs_epl->gs_eir, gs_epl->gs_eia); 113 } 114 115 /* Test if load guarded gets intercepted. */ 116 static void test_load(void) 117 { 118 unsigned long v; 119 120 guarded = 0; 121 v = load_guarded(&gs_area); 122 report(guarded, "load guarded %ld", v); 123 guarded = 0; 124 } 125 126 /* Test gs instructions without enablement resulting in an exception */ 127 static void test_special(void) 128 { 129 report_prefix_push("disabled gs"); 130 report_prefix_push("load gs"); 131 expect_pgm_int(); 132 load_gs_cb(&gs_cb); 133 check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION); 134 report_prefix_pop(); 135 136 report_prefix_push("store gs"); 137 expect_pgm_int(); 138 store_gs_cb(&gs_cb); 139 check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION); 140 report_prefix_pop(); 141 142 report_prefix_pop(); 143 } 144 145 static void init(void) 146 { 147 /* Enable control bit for gs */ 148 ctl_set_bit(2, CTL2_GUARDED_STORAGE); 149 150 /* Setup gs registers to guard the gs_area */ 151 gs_cb.gsd = gs_area | 25; 152 153 /* Check all 512kb slots for events */ 154 gs_cb.gssm = 0xffffffffffffffffULL; 155 gs_cb.gs_epl_a = (unsigned long) &gs_epl; 156 157 /* Register handler */ 158 gs_epl.gs_eha = (unsigned long) gs_handler_asm; 159 load_gs_cb(&gs_cb); 160 } 161 162 int main(void) 163 { 164 bool has_gs = test_facility(133); 165 166 report_prefix_push("gs"); 167 if (!has_gs) { 168 report_skip("Guarded storage is not available"); 169 goto done; 170 } 171 172 test_special(); 173 init(); 174 test_load(); 175 176 done: 177 report_prefix_pop(); 178 return report_summary(); 179 } 180