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 71 static int cpu_read_ac_reg(CPUState *cs, GByteArray *buf, int n) 72 { 73 S390CPU *cpu = S390_CPU(cs); 74 CPUS390XState *env = &cpu->env; 75 76 switch (n) { 77 case S390_A0_REGNUM ... S390_A15_REGNUM: 78 return gdb_get_reg32(buf, env->aregs[n]); 79 default: 80 return 0; 81 } 82 } 83 84 static int cpu_write_ac_reg(CPUState *cs, uint8_t *mem_buf, int n) 85 { 86 S390CPU *cpu = S390_CPU(cs); 87 CPUS390XState *env = &cpu->env; 88 89 switch (n) { 90 case S390_A0_REGNUM ... S390_A15_REGNUM: 91 env->aregs[n] = ldl_p(mem_buf); 92 cpu_synchronize_post_init(env_cpu(env)); 93 return 4; 94 default: 95 return 0; 96 } 97 } 98 99 /* the values represent the positions in s390-fpr.xml */ 100 #define S390_FPC_REGNUM 0 101 #define S390_F0_REGNUM 1 102 #define S390_F15_REGNUM 16 103 104 static int cpu_read_fp_reg(CPUState *cs, GByteArray *buf, int n) 105 { 106 S390CPU *cpu = S390_CPU(cs); 107 CPUS390XState *env = &cpu->env; 108 109 switch (n) { 110 case S390_FPC_REGNUM: 111 return gdb_get_reg32(buf, env->fpc); 112 case S390_F0_REGNUM ... S390_F15_REGNUM: 113 return gdb_get_reg64(buf, *get_freg(env, n - S390_F0_REGNUM)); 114 default: 115 return 0; 116 } 117 } 118 119 static int cpu_write_fp_reg(CPUState *cs, uint8_t *mem_buf, int n) 120 { 121 S390CPU *cpu = S390_CPU(cs); 122 CPUS390XState *env = &cpu->env; 123 124 switch (n) { 125 case S390_FPC_REGNUM: 126 env->fpc = ldl_p(mem_buf); 127 return 4; 128 case S390_F0_REGNUM ... S390_F15_REGNUM: 129 *get_freg(env, n - S390_F0_REGNUM) = ldtul_p(mem_buf); 130 return 8; 131 default: 132 return 0; 133 } 134 } 135 136 /* the values represent the positions in s390-vx.xml */ 137 #define S390_V0L_REGNUM 0 138 #define S390_V15L_REGNUM 15 139 #define S390_V16_REGNUM 16 140 #define S390_V31_REGNUM 31 141 142 static int cpu_read_vreg(CPUState *cs, GByteArray *buf, int n) 143 { 144 S390CPU *cpu = S390_CPU(cs); 145 CPUS390XState *env = &cpu->env; 146 int ret; 147 148 switch (n) { 149 case S390_V0L_REGNUM ... S390_V15L_REGNUM: 150 ret = gdb_get_reg64(buf, env->vregs[n][1]); 151 break; 152 case S390_V16_REGNUM ... S390_V31_REGNUM: 153 ret = gdb_get_reg64(buf, env->vregs[n][0]); 154 ret += gdb_get_reg64(buf, env->vregs[n][1]); 155 break; 156 default: 157 ret = 0; 158 } 159 160 return ret; 161 } 162 163 static int cpu_write_vreg(CPUState *cs, uint8_t *mem_buf, int n) 164 { 165 S390CPU *cpu = S390_CPU(cs); 166 CPUS390XState *env = &cpu->env; 167 168 switch (n) { 169 case S390_V0L_REGNUM ... S390_V15L_REGNUM: 170 env->vregs[n][1] = ldtul_p(mem_buf + 8); 171 return 8; 172 case S390_V16_REGNUM ... S390_V31_REGNUM: 173 env->vregs[n][0] = ldtul_p(mem_buf); 174 env->vregs[n][1] = ldtul_p(mem_buf + 8); 175 return 16; 176 default: 177 return 0; 178 } 179 } 180 181 /* the values represent the positions in s390-cr.xml */ 182 #define S390_C0_REGNUM 0 183 #define S390_C15_REGNUM 15 184 185 #ifndef CONFIG_USER_ONLY 186 static int cpu_read_c_reg(CPUState *cs, GByteArray *buf, int n) 187 { 188 S390CPU *cpu = S390_CPU(cs); 189 CPUS390XState *env = &cpu->env; 190 191 switch (n) { 192 case S390_C0_REGNUM ... S390_C15_REGNUM: 193 return gdb_get_regl(buf, env->cregs[n]); 194 default: 195 return 0; 196 } 197 } 198 199 static int cpu_write_c_reg(CPUState *cs, uint8_t *mem_buf, int n) 200 { 201 S390CPU *cpu = S390_CPU(cs); 202 CPUS390XState *env = &cpu->env; 203 204 switch (n) { 205 case S390_C0_REGNUM ... S390_C15_REGNUM: 206 env->cregs[n] = ldtul_p(mem_buf); 207 if (tcg_enabled()) { 208 tlb_flush(env_cpu(env)); 209 } 210 cpu_synchronize_post_init(env_cpu(env)); 211 return 8; 212 default: 213 return 0; 214 } 215 } 216 217 /* the values represent the positions in s390-virt.xml */ 218 #define S390_VIRT_CKC_REGNUM 0 219 #define S390_VIRT_CPUTM_REGNUM 1 220 #define S390_VIRT_BEA_REGNUM 2 221 #define S390_VIRT_PREFIX_REGNUM 3 222 223 static int cpu_read_virt_reg(CPUState *cs, GByteArray *mem_buf, int n) 224 { 225 S390CPU *cpu = S390_CPU(cs); 226 CPUS390XState *env = &cpu->env; 227 228 switch (n) { 229 case S390_VIRT_CKC_REGNUM: 230 return gdb_get_regl(mem_buf, env->ckc); 231 case S390_VIRT_CPUTM_REGNUM: 232 return gdb_get_regl(mem_buf, env->cputm); 233 case S390_VIRT_BEA_REGNUM: 234 return gdb_get_regl(mem_buf, env->gbea); 235 case S390_VIRT_PREFIX_REGNUM: 236 return gdb_get_regl(mem_buf, env->psa); 237 default: 238 return 0; 239 } 240 } 241 242 static int cpu_write_virt_reg(CPUState *cs, uint8_t *mem_buf, int n) 243 { 244 S390CPU *cpu = S390_CPU(cs); 245 CPUS390XState *env = &cpu->env; 246 247 switch (n) { 248 case S390_VIRT_CKC_REGNUM: 249 env->ckc = ldtul_p(mem_buf); 250 cpu_synchronize_post_init(cs); 251 return 8; 252 case S390_VIRT_CPUTM_REGNUM: 253 env->cputm = ldtul_p(mem_buf); 254 cpu_synchronize_post_init(cs); 255 return 8; 256 case S390_VIRT_BEA_REGNUM: 257 env->gbea = ldtul_p(mem_buf); 258 cpu_synchronize_post_init(cs); 259 return 8; 260 case S390_VIRT_PREFIX_REGNUM: 261 env->psa = ldtul_p(mem_buf); 262 cpu_synchronize_post_init(cs); 263 return 8; 264 default: 265 return 0; 266 } 267 } 268 269 /* the values represent the positions in s390-virt-kvm.xml */ 270 #define S390_VIRT_KVM_PP_REGNUM 0 271 #define S390_VIRT_KVM_PFT_REGNUM 1 272 #define S390_VIRT_KVM_PFS_REGNUM 2 273 #define S390_VIRT_KVM_PFC_REGNUM 3 274 275 static int cpu_read_virt_kvm_reg(CPUState *cs, GByteArray *mem_buf, int n) 276 { 277 S390CPU *cpu = S390_CPU(cs); 278 CPUS390XState *env = &cpu->env; 279 280 switch (n) { 281 case S390_VIRT_KVM_PP_REGNUM: 282 return gdb_get_regl(mem_buf, env->pp); 283 case S390_VIRT_KVM_PFT_REGNUM: 284 return gdb_get_regl(mem_buf, env->pfault_token); 285 case S390_VIRT_KVM_PFS_REGNUM: 286 return gdb_get_regl(mem_buf, env->pfault_select); 287 case S390_VIRT_KVM_PFC_REGNUM: 288 return gdb_get_regl(mem_buf, env->pfault_compare); 289 default: 290 return 0; 291 } 292 } 293 294 static int cpu_write_virt_kvm_reg(CPUState *cs, uint8_t *mem_buf, int n) 295 { 296 S390CPU *cpu = S390_CPU(cs); 297 CPUS390XState *env = &cpu->env; 298 299 switch (n) { 300 case S390_VIRT_KVM_PP_REGNUM: 301 env->pp = ldtul_p(mem_buf); 302 cpu_synchronize_post_init(env_cpu(env)); 303 return 8; 304 case S390_VIRT_KVM_PFT_REGNUM: 305 env->pfault_token = ldtul_p(mem_buf); 306 cpu_synchronize_post_init(env_cpu(env)); 307 return 8; 308 case S390_VIRT_KVM_PFS_REGNUM: 309 env->pfault_select = ldtul_p(mem_buf); 310 cpu_synchronize_post_init(env_cpu(env)); 311 return 8; 312 case S390_VIRT_KVM_PFC_REGNUM: 313 env->pfault_compare = ldtul_p(mem_buf); 314 cpu_synchronize_post_init(env_cpu(env)); 315 return 8; 316 default: 317 return 0; 318 } 319 } 320 #endif 321 322 /* the values represent the positions in s390-gs.xml */ 323 #define S390_GS_RESERVED_REGNUM 0 324 #define S390_GS_GSD_REGNUM 1 325 #define S390_GS_GSSM_REGNUM 2 326 #define S390_GS_GSEPLA_REGNUM 3 327 328 static int cpu_read_gs_reg(CPUState *cs, GByteArray *buf, int n) 329 { 330 S390CPU *cpu = S390_CPU(cs); 331 CPUS390XState *env = &cpu->env; 332 333 return gdb_get_regl(buf, env->gscb[n]); 334 } 335 336 static int cpu_write_gs_reg(CPUState *cs, uint8_t *mem_buf, int n) 337 { 338 S390CPU *cpu = S390_CPU(cs); 339 CPUS390XState *env = &cpu->env; 340 341 env->gscb[n] = ldtul_p(mem_buf); 342 cpu_synchronize_post_init(env_cpu(env)); 343 return 8; 344 } 345 346 void s390_cpu_gdb_init(CPUState *cs) 347 { 348 gdb_register_coprocessor(cs, cpu_read_ac_reg, 349 cpu_write_ac_reg, 350 gdb_find_static_feature("s390-acr.xml"), 0); 351 352 gdb_register_coprocessor(cs, cpu_read_fp_reg, 353 cpu_write_fp_reg, 354 gdb_find_static_feature("s390-fpr.xml"), 0); 355 356 gdb_register_coprocessor(cs, cpu_read_vreg, 357 cpu_write_vreg, 358 gdb_find_static_feature("s390-vx.xml"), 0); 359 360 gdb_register_coprocessor(cs, cpu_read_gs_reg, 361 cpu_write_gs_reg, 362 gdb_find_static_feature("s390-gs.xml"), 0); 363 364 #ifndef CONFIG_USER_ONLY 365 gdb_register_coprocessor(cs, cpu_read_c_reg, 366 cpu_write_c_reg, 367 gdb_find_static_feature("s390-cr.xml"), 0); 368 369 gdb_register_coprocessor(cs, cpu_read_virt_reg, 370 cpu_write_virt_reg, 371 gdb_find_static_feature("s390-virt.xml"), 0); 372 373 if (kvm_enabled()) { 374 gdb_register_coprocessor(cs, cpu_read_virt_kvm_reg, 375 cpu_write_virt_kvm_reg, 376 gdb_find_static_feature("s390-virt-kvm.xml"), 377 0); 378 } 379 #endif 380 } 381