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 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 #include "qemu/osdep.h" 21 #include "qemu-common.h" 22 #include "cpu.h" 23 #include "exec/exec-all.h" 24 #include "exec/gdbstub.h" 25 #include "qemu/bitops.h" 26 27 int s390_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) 28 { 29 S390CPU *cpu = S390_CPU(cs); 30 CPUS390XState *env = &cpu->env; 31 uint64_t val; 32 int cc_op; 33 34 switch (n) { 35 case S390_PSWM_REGNUM: 36 if (tcg_enabled()) { 37 cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, 38 env->cc_vr); 39 val = deposit64(env->psw.mask, 44, 2, cc_op); 40 return gdb_get_regl(mem_buf, val); 41 } 42 return gdb_get_regl(mem_buf, env->psw.mask); 43 case S390_PSWA_REGNUM: 44 return gdb_get_regl(mem_buf, env->psw.addr); 45 case S390_R0_REGNUM ... S390_R15_REGNUM: 46 return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]); 47 } 48 return 0; 49 } 50 51 int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 52 { 53 S390CPU *cpu = S390_CPU(cs); 54 CPUS390XState *env = &cpu->env; 55 target_ulong tmpl = ldtul_p(mem_buf); 56 57 switch (n) { 58 case S390_PSWM_REGNUM: 59 env->psw.mask = tmpl; 60 if (tcg_enabled()) { 61 env->cc_op = extract64(tmpl, 44, 2); 62 } 63 break; 64 case S390_PSWA_REGNUM: 65 env->psw.addr = tmpl; 66 break; 67 case S390_R0_REGNUM ... S390_R15_REGNUM: 68 env->regs[n - S390_R0_REGNUM] = tmpl; 69 break; 70 default: 71 return 0; 72 } 73 return 8; 74 } 75 76 /* the values represent the positions in s390-acr.xml */ 77 #define S390_A0_REGNUM 0 78 #define S390_A15_REGNUM 15 79 /* total number of registers in s390-acr.xml */ 80 #define S390_NUM_AC_REGS 16 81 82 static int cpu_read_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 83 { 84 switch (n) { 85 case S390_A0_REGNUM ... S390_A15_REGNUM: 86 return gdb_get_reg32(mem_buf, env->aregs[n]); 87 default: 88 return 0; 89 } 90 } 91 92 static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 93 { 94 switch (n) { 95 case S390_A0_REGNUM ... S390_A15_REGNUM: 96 env->aregs[n] = ldl_p(mem_buf); 97 cpu_synchronize_post_init(ENV_GET_CPU(env)); 98 return 4; 99 default: 100 return 0; 101 } 102 } 103 104 /* the values represent the positions in s390-fpr.xml */ 105 #define S390_FPC_REGNUM 0 106 #define S390_F0_REGNUM 1 107 #define S390_F15_REGNUM 16 108 /* total number of registers in s390-fpr.xml */ 109 #define S390_NUM_FP_REGS 17 110 111 static int cpu_read_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 112 { 113 switch (n) { 114 case S390_FPC_REGNUM: 115 return gdb_get_reg32(mem_buf, env->fpc); 116 case S390_F0_REGNUM ... S390_F15_REGNUM: 117 return gdb_get_reg64(mem_buf, get_freg(env, n - S390_F0_REGNUM)->ll); 118 default: 119 return 0; 120 } 121 } 122 123 static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 124 { 125 switch (n) { 126 case S390_FPC_REGNUM: 127 env->fpc = ldl_p(mem_buf); 128 return 4; 129 case S390_F0_REGNUM ... S390_F15_REGNUM: 130 get_freg(env, n - S390_F0_REGNUM)->ll = ldtul_p(mem_buf); 131 return 8; 132 default: 133 return 0; 134 } 135 } 136 137 /* the values represent the positions in s390-vx.xml */ 138 #define S390_V0L_REGNUM 0 139 #define S390_V15L_REGNUM 15 140 #define S390_V16_REGNUM 16 141 #define S390_V31_REGNUM 31 142 /* total number of registers in s390-vx.xml */ 143 #define S390_NUM_VREGS 32 144 145 static int cpu_read_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) 146 { 147 int ret; 148 149 switch (n) { 150 case S390_V0L_REGNUM ... S390_V15L_REGNUM: 151 ret = gdb_get_reg64(mem_buf, env->vregs[n][1].ll); 152 break; 153 case S390_V16_REGNUM ... S390_V31_REGNUM: 154 ret = gdb_get_reg64(mem_buf, env->vregs[n][0].ll); 155 ret += gdb_get_reg64(mem_buf + 8, env->vregs[n][1].ll); 156 break; 157 default: 158 ret = 0; 159 } 160 161 return ret; 162 } 163 164 static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n) 165 { 166 switch (n) { 167 case S390_V0L_REGNUM ... S390_V15L_REGNUM: 168 env->vregs[n][1].ll = ldtul_p(mem_buf + 8); 169 return 8; 170 case S390_V16_REGNUM ... S390_V31_REGNUM: 171 env->vregs[n][0].ll = ldtul_p(mem_buf); 172 env->vregs[n][1].ll = ldtul_p(mem_buf + 8); 173 return 16; 174 default: 175 return 0; 176 } 177 } 178 179 /* the values represent the positions in s390-cr.xml */ 180 #define S390_C0_REGNUM 0 181 #define S390_C15_REGNUM 15 182 /* total number of registers in s390-cr.xml */ 183 #define S390_NUM_C_REGS 16 184 185 #ifndef CONFIG_USER_ONLY 186 static int cpu_read_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 187 { 188 switch (n) { 189 case S390_C0_REGNUM ... S390_C15_REGNUM: 190 return gdb_get_regl(mem_buf, env->cregs[n]); 191 default: 192 return 0; 193 } 194 } 195 196 static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 197 { 198 switch (n) { 199 case S390_C0_REGNUM ... S390_C15_REGNUM: 200 env->cregs[n] = ldtul_p(mem_buf); 201 if (tcg_enabled()) { 202 tlb_flush(ENV_GET_CPU(env), 1); 203 } 204 cpu_synchronize_post_init(ENV_GET_CPU(env)); 205 return 8; 206 default: 207 return 0; 208 } 209 } 210 211 /* the values represent the positions in s390-virt.xml */ 212 #define S390_VIRT_CKC_REGNUM 0 213 #define S390_VIRT_CPUTM_REGNUM 1 214 #define S390_VIRT_BEA_REGNUM 2 215 #define S390_VIRT_PREFIX_REGNUM 3 216 #define S390_VIRT_PP_REGNUM 4 217 #define S390_VIRT_PFT_REGNUM 5 218 #define S390_VIRT_PFS_REGNUM 6 219 #define S390_VIRT_PFC_REGNUM 7 220 /* total number of registers in s390-virt.xml */ 221 #define S390_NUM_VIRT_REGS 8 222 223 static int cpu_read_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 224 { 225 switch (n) { 226 case S390_VIRT_CKC_REGNUM: 227 return gdb_get_regl(mem_buf, env->ckc); 228 case S390_VIRT_CPUTM_REGNUM: 229 return gdb_get_regl(mem_buf, env->cputm); 230 case S390_VIRT_BEA_REGNUM: 231 return gdb_get_regl(mem_buf, env->gbea); 232 case S390_VIRT_PREFIX_REGNUM: 233 return gdb_get_regl(mem_buf, env->psa); 234 case S390_VIRT_PP_REGNUM: 235 return gdb_get_regl(mem_buf, env->pp); 236 case S390_VIRT_PFT_REGNUM: 237 return gdb_get_regl(mem_buf, env->pfault_token); 238 case S390_VIRT_PFS_REGNUM: 239 return gdb_get_regl(mem_buf, env->pfault_select); 240 case S390_VIRT_PFC_REGNUM: 241 return gdb_get_regl(mem_buf, env->pfault_compare); 242 default: 243 return 0; 244 } 245 } 246 247 static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n) 248 { 249 switch (n) { 250 case S390_VIRT_CKC_REGNUM: 251 env->ckc = ldtul_p(mem_buf); 252 cpu_synchronize_post_init(ENV_GET_CPU(env)); 253 return 8; 254 case S390_VIRT_CPUTM_REGNUM: 255 env->cputm = ldtul_p(mem_buf); 256 cpu_synchronize_post_init(ENV_GET_CPU(env)); 257 return 8; 258 case S390_VIRT_BEA_REGNUM: 259 env->gbea = ldtul_p(mem_buf); 260 cpu_synchronize_post_init(ENV_GET_CPU(env)); 261 return 8; 262 case S390_VIRT_PREFIX_REGNUM: 263 env->psa = ldtul_p(mem_buf); 264 cpu_synchronize_post_init(ENV_GET_CPU(env)); 265 return 8; 266 case S390_VIRT_PP_REGNUM: 267 env->pp = ldtul_p(mem_buf); 268 cpu_synchronize_post_init(ENV_GET_CPU(env)); 269 return 8; 270 case S390_VIRT_PFT_REGNUM: 271 env->pfault_token = ldtul_p(mem_buf); 272 cpu_synchronize_post_init(ENV_GET_CPU(env)); 273 return 8; 274 case S390_VIRT_PFS_REGNUM: 275 env->pfault_select = ldtul_p(mem_buf); 276 cpu_synchronize_post_init(ENV_GET_CPU(env)); 277 return 8; 278 case S390_VIRT_PFC_REGNUM: 279 env->pfault_compare = ldtul_p(mem_buf); 280 cpu_synchronize_post_init(ENV_GET_CPU(env)); 281 return 8; 282 default: 283 return 0; 284 } 285 } 286 #endif 287 288 void s390_cpu_gdb_init(CPUState *cs) 289 { 290 gdb_register_coprocessor(cs, cpu_read_ac_reg, 291 cpu_write_ac_reg, 292 S390_NUM_AC_REGS, "s390-acr.xml", 0); 293 294 gdb_register_coprocessor(cs, cpu_read_fp_reg, 295 cpu_write_fp_reg, 296 S390_NUM_FP_REGS, "s390-fpr.xml", 0); 297 298 gdb_register_coprocessor(cs, cpu_read_vreg, 299 cpu_write_vreg, 300 S390_NUM_VREGS, "s390-vx.xml", 0); 301 302 #ifndef CONFIG_USER_ONLY 303 gdb_register_coprocessor(cs, cpu_read_c_reg, 304 cpu_write_c_reg, 305 S390_NUM_C_REGS, "s390-cr.xml", 0); 306 307 if (kvm_enabled()) { 308 gdb_register_coprocessor(cs, cpu_read_virt_reg, 309 cpu_write_virt_reg, 310 S390_NUM_VIRT_REGS, "s390-virt.xml", 0); 311 } 312 #endif 313 } 314