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/asm-offsets.h> 13 #include <asm/page.h> 14 #include <asm/facility.h> 15 #include <asm/interrupt.h> 16 #include <asm-generic/barrier.h> 17 #include <gs.h> 18 19 static volatile int guarded = 0; 20 static struct gs_cb gs_cb; 21 static struct gs_epl gs_epl; 22 static unsigned long gs_area = 0x2000000; 23 24 void gs_handler(struct gs_cb *this_cb); 25 26 static inline unsigned long load_guarded(unsigned long *p) 27 { 28 unsigned long v; 29 30 asm(".insn rxy,0xe3000000004c, %0,%1" 31 : "=d" (v) 32 : "m" (*p) 33 : "r14", "memory"); 34 return v; 35 } 36 37 /* guarded-storage event handler and finally it calls gs_handler */ 38 extern void gs_handler_asm(void); 39 asm ( ".macro STGSC args:vararg\n" 40 " .insn rxy,0xe30000000049,\\args\n" 41 " .endm\n" 42 " .globl gs_handler_asm\n" 43 "gs_handler_asm:\n" 44 " lgr %r14,%r15\n" /* Save current stack address in r14 */ 45 ".Lgs_handler_frame = 16*8+32+" xstr(STACK_FRAME_SIZE) "\n" 46 " aghi %r15,-(.Lgs_handler_frame)\n" /* Allocate stack frame */ 47 " stmg %r0,%r13,192(%r15)\n" /* Store regs to save area */ 48 " stg %r14,312(%r15)\n" 49 " la %r2," xstr(STACK_FRAME_SIZE) "(%r15)\n" /* Store gscb address in this_cb */ 50 " STGSC %r0," xstr(STACK_FRAME_SIZE) "(%r15)\n" 51 " lg %r14,24(%r2)\n" /* Get GSEPLA from GSCB*/ 52 " lg %r14,40(%r14)\n" /* Get GSERA from GSEPL*/ 53 " stg %r14,304(%r15)\n" /* Store GSERA in r14 of reg save area */ 54 " brasl %r14,gs_handler\n" /* Jump to gs_handler */ 55 " lmg %r0,%r15,192(%r15)\n" /* Restore regs */ 56 " aghi %r14, 6\n" /* Add lgg instr len to GSERA */ 57 " br %r14\n" /* Jump to next instruction after lgg */ 58 ".size gs_handler_asm,.-gs_handler_asm\n" 59 ); 60 61 void gs_handler(struct gs_cb *this_cb) 62 { 63 guarded = 1; 64 struct gs_epl *gs_epl = (struct gs_epl *) this_cb->gs_epl_a; 65 printf("gs_handler called for %016lx at %016lx\n", 66 gs_epl->gs_eir, gs_epl->gs_eia); 67 } 68 69 /* Test if load guarded gets intercepted. */ 70 static void test_load(void) 71 { 72 unsigned long v; 73 74 guarded = 0; 75 v = load_guarded(&gs_area); 76 report(guarded, "load guarded %ld", v); 77 guarded = 0; 78 } 79 80 /* Test gs instructions without enablement resulting in an exception */ 81 static void test_special(void) 82 { 83 report_prefix_push("disabled gs"); 84 report_prefix_push("load gs"); 85 expect_pgm_int(); 86 load_gs_cb(&gs_cb); 87 check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION); 88 report_prefix_pop(); 89 90 report_prefix_push("store gs"); 91 expect_pgm_int(); 92 store_gs_cb(&gs_cb); 93 check_pgm_int_code(PGM_INT_CODE_SPECIAL_OPERATION); 94 report_prefix_pop(); 95 96 report_prefix_pop(); 97 } 98 99 static void init(void) 100 { 101 /* Enable control bit for gs */ 102 ctl_set_bit(2, CTL2_GUARDED_STORAGE); 103 104 /* Setup gs registers to guard the gs_area */ 105 gs_cb.gsd = gs_area | 25; 106 107 /* Check all 512kb slots for events */ 108 gs_cb.gssm = 0xffffffffffffffffULL; 109 gs_cb.gs_epl_a = (unsigned long) &gs_epl; 110 111 /* Register handler */ 112 gs_epl.gs_eha = (unsigned long) gs_handler_asm; 113 load_gs_cb(&gs_cb); 114 } 115 116 int main(void) 117 { 118 bool has_gs = test_facility(133); 119 120 report_prefix_push("gs"); 121 if (!has_gs) { 122 report_skip("Guarded storage is not available"); 123 goto done; 124 } 125 126 test_special(); 127 init(); 128 test_load(); 129 130 done: 131 report_prefix_pop(); 132 return report_summary(); 133 } 134