1 /* 2 * Check decoding of s390_guarded_storage syscall. 3 * 4 * Copyright (c) 2018 The strace developers. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "tests.h" 31 #include <asm/unistd.h> 32 33 #if defined __NR_s390_guarded_storage && defined HAVE_ASM_GUARDED_STORAGE_H 34 35 # include <inttypes.h> 36 # include <stdbool.h> 37 # include <stdint.h> 38 # include <stdio.h> 39 # include <unistd.h> 40 41 # include <asm/guarded_storage.h> 42 43 # ifndef VERBOSE 44 # define VERBOSE 0 45 # endif 46 47 static void 48 gs_no_arg(kernel_ulong_t val, const char *val_str) 49 { 50 static const kernel_ulong_t bogus_addr = 51 (kernel_ulong_t) 0xcaffeedadeadbed5ULL; 52 static const kernel_ulong_t bogus_cmd_mask = 53 (kernel_ulong_t) 0xbadc0ded00000000ULL; 54 long rc; 55 56 rc = syscall(__NR_s390_guarded_storage, val | bogus_cmd_mask, 57 bogus_addr); 58 printf("s390_guarded_storage(%s) = %s\n", val_str, sprintrc(rc)); 59 } 60 61 static void 62 gs_print_epl(uint64_t addr, bool valid, const char *str) 63 { 64 if (!valid) { 65 if (str) 66 printf("%s", str); 67 else 68 printf("%#" PRIx64, addr); 69 70 return; 71 } 72 73 struct gs_epl *gsepl = (struct gs_epl *) (uintptr_t) addr; 74 75 printf("[{"); 76 77 # if VERBOSE 78 if (gsepl->pad1) 79 printf("pad1=%#02x, ", gsepl->pad1); 80 81 printf("gs_eam=%#02x /* extended addressing mode: %u, " 82 "basic addressing mode: %u */" 83 ", gs_eci=%#02x /* CPU in TX: %u, CPU in CX: %u, " 84 "instruction: %s */" 85 ", gs_eai=%#02x /* DAT: %u, address space indication: %u, " 86 "AR number: %u */, ", 87 gsepl->gs_eam, gsepl->e, gsepl->b, 88 gsepl->gs_eci, gsepl->tx, gsepl->cx, 89 gsepl->in ? "LLGFGS": "LGG", 90 gsepl->gs_eai, gsepl->t, gsepl->as, gsepl->ar); 91 92 if (gsepl->pad2) 93 printf("pad2=%#08x, ", gsepl->pad2); 94 # endif /* VERBOSE */ 95 96 printf("gs_eha=%#llx, ", (unsigned long long) gsepl->gs_eha); 97 98 # if VERBOSE 99 printf("gs_eia=%#llx, gs_eoa=%#llx, gs_eir=%#llx, gs_era=%#llx", 100 (unsigned long long) gsepl->gs_eia, 101 (unsigned long long) gsepl->gs_eoa, 102 (unsigned long long) gsepl->gs_eir, 103 (unsigned long long) gsepl->gs_era); 104 # else /* !VERBOSE */ 105 printf("..."); 106 # endif /* VERBOSE */ 107 108 printf("}]"); 109 } 110 111 static void 112 gs_set_cb(kernel_ulong_t addr, bool valid, bool epl_valid, 113 const char *bc_str, const char *epl_str) 114 { 115 static const kernel_ulong_t bogus_cmd_mask = 116 (kernel_ulong_t) 0xda7a105700000000ULL; 117 118 long rc; 119 120 printf("s390_guarded_storage(GS_SET_BC_CB, "); 121 122 if (valid) { 123 struct gs_cb *gscb = (struct gs_cb *) (uintptr_t) addr; 124 125 printf("{"); 126 127 if (gscb->reserved) 128 printf("reserved=%#016llx, ", 129 (unsigned long long) gscb->reserved); 130 131 printf("gsd=%#16llx", 132 (unsigned long long) gscb->gsd); 133 # if VERBOSE 134 printf(" /* GS origin: "); 135 136 unsigned int gsc = gscb->gsd & 0x3F; 137 unsigned int gls = (gscb->gsd >> 8) & 7; 138 bool gsc_valid = gsc >= 25 && gsc <= 56; 139 140 if (gsc_valid) { 141 uint64_t gls = gscb->gsd >> gsc; 142 int field_size = 2 + (67 - gsc) / 4; 143 144 printf("%#0*" PRIx64, field_size, gls); 145 } else { 146 printf("[invalid]"); 147 } 148 149 printf(", guard load shift: %u, GS characteristic: %u */", 150 gls, gsc); 151 # endif /* VERBOSE */ 152 153 printf(", gssm=%#016llx, gs_epl_a=", 154 (unsigned long long) gscb->gssm); 155 156 gs_print_epl(gscb->gs_epl_a, epl_valid, epl_str); 157 158 printf("}"); 159 } else { 160 if (bc_str) 161 printf("%s", bc_str); 162 else 163 printf("%#llx", (unsigned long long) addr); 164 } 165 166 rc = syscall(__NR_s390_guarded_storage, 167 GS_SET_BC_CB | bogus_cmd_mask, addr); 168 printf(") = %s\n", sprintrc(rc)); 169 } 170 171 int 172 main(void) 173 { 174 static const kernel_ulong_t bogus_cmd = 175 (kernel_ulong_t) 0xdeafbeefdeadc0deULL; 176 static const kernel_ulong_t bogus_addr = 177 (kernel_ulong_t) 0xfacefeedac0ffeedULL; 178 179 struct gs_cb *gscb = tail_alloc(sizeof(*gscb)); 180 struct gs_epl *gsepl = tail_alloc(sizeof(*gsepl)); 181 182 long rc; 183 184 rc = syscall(__NR_s390_guarded_storage, 5, 0); 185 printf("s390_guarded_storage(0x5 /* GS_??? */, NULL) = %s\n", 186 sprintrc(rc)); 187 188 rc = syscall(__NR_s390_guarded_storage, bogus_cmd, bogus_addr); 189 printf("s390_guarded_storage(%#x /* GS_??? */, %#lx) = %s\n", 190 (unsigned) bogus_cmd, (unsigned long) bogus_addr, sprintrc(rc)); 191 192 gs_no_arg(ARG_STR(GS_BROADCAST)); 193 gs_no_arg(ARG_STR(GS_CLEAR_BC_CB)); 194 gs_no_arg(ARG_STR(GS_DISABLE)); 195 gs_no_arg(ARG_STR(GS_ENABLE)); 196 197 fill_memory(gscb, sizeof(*gscb)); 198 fill_memory_ex(gsepl, sizeof(*gsepl), 0xA5, 0x5A); 199 200 gs_set_cb(0, false, false, "NULL", NULL); 201 gs_set_cb((uintptr_t) (gscb + 1), false, false, NULL, NULL); 202 203 gscb->gs_epl_a = 0; 204 gs_set_cb((uintptr_t) gscb, true, false, NULL, "NULL"); 205 206 fill_memory_ex(gscb, sizeof(*gscb), 0x5A, 0xA5); 207 gscb->gs_epl_a = (uintptr_t) (gsepl + 1) | 208 (sizeof(kernel_ulong_t) < sizeof(uint64_t) ? 209 0xc0debad000000000ULL : 0); 210 gs_set_cb((uintptr_t) gscb, true, false, NULL, NULL); 211 212 fill_memory_ex(gscb, sizeof(*gscb), 0xA7, 0xA5); 213 gscb->gs_epl_a = (uintptr_t) gsepl; 214 gs_set_cb((uintptr_t) gscb, true, true, NULL, NULL); 215 216 fill_memory_ex(gscb, sizeof(*gscb), 0x55, 0xAA); 217 fill_memory_ex(gsepl, sizeof(*gsepl), 0x5A, 0xA5); 218 gscb->gs_epl_a = (uintptr_t) gsepl; 219 gs_set_cb((uintptr_t) gscb, true, true, NULL, NULL); 220 221 puts("+++ exited with 0 +++"); 222 return 0; 223 } 224 225 #else 226 227 SKIP_MAIN_UNDEFINED("__NR_s390_guarded_storage && HAVE_ASM_GUARDED_STORAGE_H") 228 229 #endif 230