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 <stdint.h> 37 # include <stdio.h> 38 # include <unistd.h> 39 40 # include <asm/guarded_storage.h> 41 42 # ifndef VERBOSE 43 # define VERBOSE 0 44 # endif 45 46 static void 47 gs_no_arg(kernel_ulong_t val, const char *val_str) 48 { 49 static const kernel_ulong_t bogus_addr = 50 (kernel_ulong_t) 0xcaffeedadeadbed5ULL; 51 static const kernel_ulong_t bogus_cmd_mask = 52 (kernel_ulong_t) 0xbadc0ded00000000ULL; 53 long rc; 54 55 rc = syscall(__NR_s390_guarded_storage, val | bogus_cmd_mask, 56 bogus_addr); 57 printf("s390_guarded_storage(%s) = %s\n", val_str, sprintrc(rc)); 58 } 59 60 static void 61 gs_print_epl(uint64_t addr, bool valid, const char *str) 62 { 63 if (!valid) { 64 if (str) 65 printf("%s", str); 66 else 67 printf("%#" PRIx64, addr); 68 69 return; 70 } 71 72 struct gs_epl *gsepl = (struct gs_epl *) (uintptr_t) addr; 73 74 printf("[{"); 75 76 # if VERBOSE 77 if (gsepl->pad1) 78 printf("pad1=%#02x, ", gsepl->pad1); 79 80 printf("gs_eam=%#02x /* extended addressing mode: %u, " 81 "basic addressing mode: %u */" 82 ", gs_eci=%#02x /* CPU in TX: %u, CPU in CX: %u, " 83 "instruction: %s */" 84 ", gs_eai=%#02x /* DAT: %u, address space indication: %u, " 85 "AR number: %u */, ", 86 gsepl->gs_eam, gsepl->e, gsepl->b, 87 gsepl->gs_eci, gsepl->tx, gsepl->cx, 88 gsepl->in ? "LLGFGS": "LGG", 89 gsepl->gs_eai, gsepl->t, gsepl->as, gsepl->ar); 90 91 if (gsepl->pad2) 92 printf("pad2=%#08x, ", gsepl->pad2); 93 # endif /* VERBOSE */ 94 95 printf("gs_eha=%#llx, ", (unsigned long long) gsepl->gs_eha); 96 97 # if VERBOSE 98 printf("gs_eia=%#llx, gs_eoa=%#llx, gs_eir=%#llx, gs_era=%#llx", 99 (unsigned long long) gsepl->gs_eia, 100 (unsigned long long) gsepl->gs_eoa, 101 (unsigned long long) gsepl->gs_eir, 102 (unsigned long long) gsepl->gs_era); 103 # else /* !VERBOSE */ 104 printf("..."); 105 # endif /* VERBOSE */ 106 107 printf("}]"); 108 } 109 110 static void 111 gs_set_cb(kernel_ulong_t addr, bool valid, bool epl_valid, 112 const char *bc_str, const char *epl_str) 113 { 114 static const kernel_ulong_t bogus_cmd_mask = 115 (kernel_ulong_t) 0xda7a105700000000ULL; 116 117 long rc; 118 119 printf("s390_guarded_storage(GS_SET_BC_CB, "); 120 121 if (valid) { 122 struct gs_cb *gscb = (struct gs_cb *) (uintptr_t) addr; 123 124 printf("{"); 125 126 if (gscb->reserved) 127 printf("reserved=%#016llx, ", 128 (unsigned long long) gscb->reserved); 129 130 printf("gsd=%#16llx", 131 (unsigned long long) gscb->gsd); 132 # if VERBOSE 133 printf(" /* GS origin: "); 134 135 unsigned int gsc = gscb->gsd & 0x3F; 136 unsigned int gls = (gscb->gsd >> 8) & 7; 137 bool gsc_valid = gsc >= 25 && gsc <= 56; 138 139 if (gsc_valid) { 140 uint64_t gls = gscb->gsd >> gsc; 141 int field_size = 2 + (67 - gsc) / 4; 142 143 printf("%#0*" PRIx64, field_size, gls); 144 } else { 145 printf("[invalid]"); 146 } 147 148 printf(", guard load shift: %u, GS characteristic: %u */", 149 gls, gsc); 150 # endif /* VERBOSE */ 151 152 printf(", gssm=%#016llx, gs_epl_a=", 153 (unsigned long long) gscb->gssm); 154 155 gs_print_epl(gscb->gs_epl_a, epl_valid, epl_str); 156 157 printf("}"); 158 } else { 159 if (bc_str) 160 printf("%s", bc_str); 161 else 162 printf("%#llx", (unsigned long long) addr); 163 } 164 165 rc = syscall(__NR_s390_guarded_storage, 166 GS_SET_BC_CB | bogus_cmd_mask, addr); 167 printf(") = %s\n", sprintrc(rc)); 168 } 169 170 int 171 main(void) 172 { 173 static const kernel_ulong_t bogus_cmd = 174 (kernel_ulong_t) 0xdeafbeefdeadc0deULL; 175 static const kernel_ulong_t bogus_addr = 176 (kernel_ulong_t) 0xfacefeedac0ffeedULL; 177 178 TAIL_ALLOC_OBJECT_CONST_PTR(struct gs_cb, gscb); 179 TAIL_ALLOC_OBJECT_CONST_PTR(struct gs_epl, gsepl); 180 181 long rc; 182 183 rc = syscall(__NR_s390_guarded_storage, 5, 0); 184 printf("s390_guarded_storage(0x5 /* GS_??? */, NULL) = %s\n", 185 sprintrc(rc)); 186 187 rc = syscall(__NR_s390_guarded_storage, bogus_cmd, bogus_addr); 188 printf("s390_guarded_storage(%#x /* GS_??? */, %#lx) = %s\n", 189 (unsigned) bogus_cmd, (unsigned long) bogus_addr, sprintrc(rc)); 190 191 gs_no_arg(ARG_STR(GS_BROADCAST)); 192 gs_no_arg(ARG_STR(GS_CLEAR_BC_CB)); 193 gs_no_arg(ARG_STR(GS_DISABLE)); 194 gs_no_arg(ARG_STR(GS_ENABLE)); 195 196 fill_memory(gscb, sizeof(*gscb)); 197 fill_memory_ex(gsepl, sizeof(*gsepl), 0xA5, 0x5A); 198 199 gs_set_cb(0, false, false, "NULL", NULL); 200 gs_set_cb((uintptr_t) (gscb + 1), false, false, NULL, NULL); 201 202 gscb->gs_epl_a = 0; 203 gs_set_cb((uintptr_t) gscb, true, false, NULL, "NULL"); 204 205 fill_memory_ex(gscb, sizeof(*gscb), 0x5A, 0xA5); 206 gscb->gs_epl_a = (uintptr_t) (gsepl + 1) | 207 (sizeof(kernel_ulong_t) < sizeof(uint64_t) ? 208 0xc0debad000000000ULL : 0); 209 gs_set_cb((uintptr_t) gscb, true, false, NULL, NULL); 210 211 fill_memory_ex(gscb, sizeof(*gscb), 0xA7, 0xA5); 212 gscb->gs_epl_a = (uintptr_t) gsepl; 213 gs_set_cb((uintptr_t) gscb, true, true, NULL, NULL); 214 215 fill_memory_ex(gscb, sizeof(*gscb), 0x55, 0xAA); 216 fill_memory_ex(gsepl, sizeof(*gsepl), 0x5A, 0xA5); 217 gscb->gs_epl_a = (uintptr_t) gsepl; 218 gs_set_cb((uintptr_t) gscb, true, true, NULL, NULL); 219 220 puts("+++ exited with 0 +++"); 221 return 0; 222 } 223 224 #else 225 226 SKIP_MAIN_UNDEFINED("__NR_s390_guarded_storage && HAVE_ASM_GUARDED_STORAGE_H") 227 228 #endif 229