1 /* 2 * s390x gdb server stub 3 * 4 * Copyright (c) 2003-2005 Fabrice Bellard 5 * Copyright (c) 2013 SUSE LINUX Products GmbH 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include "qemu/osdep.h" 22 #include "cpu.h" 23 #include "s390x-internal.h" 24 #include "exec/exec-all.h" 25 #include "exec/gdbstub.h" 26 #include "gdbstub/helpers.h" 27 #include "qemu/bitops.h" 28 #include "sysemu/hw_accel.h" 29 #include "sysemu/tcg.h" 30 31 int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 32 { 33 CPUS390XState *env = cpu_env(cs); 34 35 switch (n) { 36 case S390_PSWM_REGNUM: 37 return gdb_get_regl(mem_buf, s390_cpu_get_psw_mask(env)); 38 case S390_PSWA_REGNUM: 39 return gdb_get_regl(mem_buf, env->psw.addr); 40 case S390_R0_REGNUM ... S390_R15_REGNUM: 41 return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]); 42 } 43 return 0; 44 } 45 46 int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 47 { 48 CPUS390XState *env = cpu_env(cs); 49 target_ulong tmpl = ldtul_p(mem_buf); 50 51 switch (n) { 52 case S390_PSWM_REGNUM: 53 s390_cpu_set_psw(env, tmpl, env->psw.addr); 54 break; 55 case S390_PSWA_REGNUM: 56 env->psw.addr = tmpl; 57 break; 58 case S390_R0_REGNUM ... S390_R15_REGNUM: 59 env->regs[n - S390_R0_REGNUM] = tmpl; 60 break; 61 default: 62 return 0; 63 } 64 return 8; 65 } 66 67 /* the values represent the positions in s390-acr.xml */ 68 #define S390_A0_REGNUM 0 69 #define S390_A15_REGNUM 15 70 /* total number of registers in s390-acr.xml */ 71 #define S390_NUM_AC_REGS 16 72 73 static int cpu_read_ac_reg(CPUS390XState *env, GByteArray *buf, int n) 74 { 75 switch (n) { 76 case S390_A0_REGNUM ... S390_A15_REGNUM: 77 return gdb_get_reg32(buf, env->aregs[n]); 78 default: 79 return 0; 80 } 81 } 82 83 static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 84 { 85 switch (n) { 86 case S390_A0_REGNUM ... S390_A15_REGNUM: 87 env->aregs[n] = ldl_p(mem_buf); 88 cpu_synchronize_post_init(env_cpu(env)); 89 return 4; 90 default: 91 return 0; 92 } 93 } 94 95 /* the values represent the positions in s390-fpr.xml */ 96 #define S390_FPC_REGNUM 0 97 #define S390_F0_REGNUM 1 98 #define S390_F15_REGNUM 16 99 /* total number of registers in s390-fpr.xml */ 100 #define S390_NUM_FP_REGS 17 101 102 static int cpu_read_fp_reg(CPUS390XState *env, GByteArray *buf, int n) 103 { 104 switch (n) { 105 case S390_FPC_REGNUM: 106 return gdb_get_reg32(buf, env->fpc); 107 case S390_F0_REGNUM ... S390_F15_REGNUM: 108 return gdb_get_reg64(buf, *get_freg(env, n - S390_F0_REGNUM)); 109 default: 110 return 0; 111 } 112 } 113 114 static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 115 { 116 switch (n) { 117 case S390_FPC_REGNUM: 118 env->fpc = ldl_p(mem_buf); 119 return 4; 120 case S390_F0_REGNUM ... S390_F15_REGNUM: 121 *get_freg(env, n - S390_F0_REGNUM) = ldtul_p(mem_buf); 122 return 8; 123 default: 124 return 0; 125 } 126 } 127 128 /* the values represent the positions in s390-vx.xml */ 129 #define S390_V0L_REGNUM 0 130 #define S390_V15L_REGNUM 15 131 #define S390_V16_REGNUM 16 132 #define S390_V31_REGNUM 31 133 /* total number of registers in s390-vx.xml */ 134 #define S390_NUM_VREGS 32 135 136 static int cpu_read_vreg(CPUS390XState *env, GByteArray *buf, int n) 137 { 138 int ret; 139 140 switch (n) { 141 case S390_V0L_REGNUM ... S390_V15L_REGNUM: 142 ret = gdb_get_reg64(buf, env->vregs[n][1]); 143 break; 144 case S390_V16_REGNUM ... S390_V31_REGNUM: 145 ret = gdb_get_reg64(buf, env->vregs[n][0]); 146 ret += gdb_get_reg64(buf, env->vregs[n][1]); 147 break; 148 default: 149 ret = 0; 150 } 151 152 return ret; 153 } 154 155 static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) 156 { 157 switch (n) { 158 case S390_V0L_REGNUM ... S390_V15L_REGNUM: 159 env->vregs[n][1] = ldtul_p(mem_buf + 8); 160 return 8; 161 case S390_V16_REGNUM ... S390_V31_REGNUM: 162 env->vregs[n][0] = ldtul_p(mem_buf); 163 env->vregs[n][1] = ldtul_p(mem_buf + 8); 164 return 16; 165 default: 166 return 0; 167 } 168 } 169 170 /* the values represent the positions in s390-cr.xml */ 171 #define S390_C0_REGNUM 0 172 #define S390_C15_REGNUM 15 173 /* total number of registers in s390-cr.xml */ 174 #define S390_NUM_C_REGS 16 175 176 #ifndef CONFIG_USER_ONLY 177 static int cpu_read_c_reg(CPUS390XState *env, GByteArray *buf, int n) 178 { 179 switch (n) { 180 case S390_C0_REGNUM ... S390_C15_REGNUM: 181 return gdb_get_regl(buf, env->cregs[n]); 182 default: 183 return 0; 184 } 185 } 186 187 static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 188 { 189 switch (n) { 190 case S390_C0_REGNUM ... S390_C15_REGNUM: 191 env->cregs[n] = ldtul_p(mem_buf); 192 if (tcg_enabled()) { 193 tlb_flush(env_cpu(env)); 194 } 195 cpu_synchronize_post_init(env_cpu(env)); 196 return 8; 197 default: 198 return 0; 199 } 200 } 201 202 /* the values represent the positions in s390-virt.xml */ 203 #define S390_VIRT_CKC_REGNUM 0 204 #define S390_VIRT_CPUTM_REGNUM 1 205 #define S390_VIRT_BEA_REGNUM 2 206 #define S390_VIRT_PREFIX_REGNUM 3 207 /* total number of registers in s390-virt.xml */ 208 #define S390_NUM_VIRT_REGS 4 209 210 static int cpu_read_virt_reg(CPUS390XState *env, GByteArray *mem_buf, int n) 211 { 212 switch (n) { 213 case S390_VIRT_CKC_REGNUM: 214 return gdb_get_regl(mem_buf, env->ckc); 215 case S390_VIRT_CPUTM_REGNUM: 216 return gdb_get_regl(mem_buf, env->cputm); 217 case S390_VIRT_BEA_REGNUM: 218 return gdb_get_regl(mem_buf, env->gbea); 219 case S390_VIRT_PREFIX_REGNUM: 220 return gdb_get_regl(mem_buf, env->psa); 221 default: 222 return 0; 223 } 224 } 225 226 static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 227 { 228 switch (n) { 229 case S390_VIRT_CKC_REGNUM: 230 env->ckc = ldtul_p(mem_buf); 231 cpu_synchronize_post_init(env_cpu(env)); 232 return 8; 233 case S390_VIRT_CPUTM_REGNUM: 234 env->cputm = ldtul_p(mem_buf); 235 cpu_synchronize_post_init(env_cpu(env)); 236 return 8; 237 case S390_VIRT_BEA_REGNUM: 238 env->gbea = ldtul_p(mem_buf); 239 cpu_synchronize_post_init(env_cpu(env)); 240 return 8; 241 case S390_VIRT_PREFIX_REGNUM: 242 env->psa = ldtul_p(mem_buf); 243 cpu_synchronize_post_init(env_cpu(env)); 244 return 8; 245 default: 246 return 0; 247 } 248 } 249 250 /* the values represent the positions in s390-virt-kvm.xml */ 251 #define S390_VIRT_KVM_PP_REGNUM 0 252 #define S390_VIRT_KVM_PFT_REGNUM 1 253 #define S390_VIRT_KVM_PFS_REGNUM 2 254 #define S390_VIRT_KVM_PFC_REGNUM 3 255 /* total number of registers in s390-virt-kvm.xml */ 256 #define S390_NUM_VIRT_KVM_REGS 4 257 258 static int cpu_read_virt_kvm_reg(CPUS390XState *env, GByteArray *mem_buf, int n) 259 { 260 switch (n) { 261 case S390_VIRT_KVM_PP_REGNUM: 262 return gdb_get_regl(mem_buf, env->pp); 263 case S390_VIRT_KVM_PFT_REGNUM: 264 return gdb_get_regl(mem_buf, env->pfault_token); 265 case S390_VIRT_KVM_PFS_REGNUM: 266 return gdb_get_regl(mem_buf, env->pfault_select); 267 case S390_VIRT_KVM_PFC_REGNUM: 268 return gdb_get_regl(mem_buf, env->pfault_compare); 269 default: 270 return 0; 271 } 272 } 273 274 static int cpu_write_virt_kvm_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 275 { 276 switch (n) { 277 case S390_VIRT_KVM_PP_REGNUM: 278 env->pp = ldtul_p(mem_buf); 279 cpu_synchronize_post_init(env_cpu(env)); 280 return 8; 281 case S390_VIRT_KVM_PFT_REGNUM: 282 env->pfault_token = ldtul_p(mem_buf); 283 cpu_synchronize_post_init(env_cpu(env)); 284 return 8; 285 case S390_VIRT_KVM_PFS_REGNUM: 286 env->pfault_select = ldtul_p(mem_buf); 287 cpu_synchronize_post_init(env_cpu(env)); 288 return 8; 289 case S390_VIRT_KVM_PFC_REGNUM: 290 env->pfault_compare = ldtul_p(mem_buf); 291 cpu_synchronize_post_init(env_cpu(env)); 292 return 8; 293 default: 294 return 0; 295 } 296 } 297 #endif 298 299 /* the values represent the positions in s390-gs.xml */ 300 #define S390_GS_RESERVED_REGNUM 0 301 #define S390_GS_GSD_REGNUM 1 302 #define S390_GS_GSSM_REGNUM 2 303 #define S390_GS_GSEPLA_REGNUM 3 304 /* total number of registers in s390-gs.xml */ 305 #define S390_NUM_GS_REGS 4 306 307 static int cpu_read_gs_reg(CPUS390XState *env, GByteArray *buf, int n) 308 { 309 return gdb_get_regl(buf, env->gscb[n]); 310 } 311 312 static int cpu_write_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 313 { 314 env->gscb[n] = ldtul_p(mem_buf); 315 cpu_synchronize_post_init(env_cpu(env)); 316 return 8; 317 } 318 319 void s390_cpu_gdb_init(CPUState *cs) 320 { 321 gdb_register_coprocessor(cs, cpu_read_ac_reg, 322 cpu_write_ac_reg, 323 S390_NUM_AC_REGS, "s390-acr.xml", 0); 324 325 gdb_register_coprocessor(cs, cpu_read_fp_reg, 326 cpu_write_fp_reg, 327 S390_NUM_FP_REGS, "s390-fpr.xml", 0); 328 329 gdb_register_coprocessor(cs, cpu_read_vreg, 330 cpu_write_vreg, 331 S390_NUM_VREGS, "s390-vx.xml", 0); 332 333 gdb_register_coprocessor(cs, cpu_read_gs_reg, 334 cpu_write_gs_reg, 335 S390_NUM_GS_REGS, "s390-gs.xml", 0); 336 337 #ifndef CONFIG_USER_ONLY 338 gdb_register_coprocessor(cs, cpu_read_c_reg, 339 cpu_write_c_reg, 340 S390_NUM_C_REGS, "s390-cr.xml", 0); 341 342 gdb_register_coprocessor(cs, cpu_read_virt_reg, 343 cpu_write_virt_reg, 344 S390_NUM_VIRT_REGS, "s390-virt.xml", 0); 345 346 if (kvm_enabled()) { 347 gdb_register_coprocessor(cs, cpu_read_virt_kvm_reg, 348 cpu_write_virt_kvm_reg, 349 S390_NUM_VIRT_KVM_REGS, "s390-virt-kvm.xml", 350 0); 351 } 352 #endif 353 } 354