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