1 /* 2 * ARM 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 #include "qemu/osdep.h" 21 #include "cpu.h" 22 #include "exec/gdbstub.h" 23 #include "gdbstub/helpers.h" 24 #include "sysemu/tcg.h" 25 #include "internals.h" 26 #include "cpregs.h" 27 28 typedef struct RegisterSysregXmlParam { 29 CPUState *cs; 30 GString *s; 31 int n; 32 } RegisterSysregXmlParam; 33 34 /* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect 35 whatever the target description contains. Due to a historical mishap 36 the FPA registers appear in between core integer regs and the CPSR. 37 We hack round this by giving the FPA regs zero size when talking to a 38 newer gdb. */ 39 40 int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 41 { 42 ARMCPU *cpu = ARM_CPU(cs); 43 CPUARMState *env = &cpu->env; 44 45 if (n < 16) { 46 /* Core integer register. */ 47 return gdb_get_reg32(mem_buf, env->regs[n]); 48 } 49 if (n == 25) { 50 /* CPSR, or XPSR for M-profile */ 51 if (arm_feature(env, ARM_FEATURE_M)) { 52 return gdb_get_reg32(mem_buf, xpsr_read(env)); 53 } else { 54 return gdb_get_reg32(mem_buf, cpsr_read(env)); 55 } 56 } 57 /* Unknown register. */ 58 return 0; 59 } 60 61 int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 62 { 63 ARMCPU *cpu = ARM_CPU(cs); 64 CPUARMState *env = &cpu->env; 65 uint32_t tmp; 66 67 tmp = ldl_p(mem_buf); 68 69 /* 70 * Mask out low bits of PC to workaround gdb bugs. 71 * This avoids an assert in thumb_tr_translate_insn, because it is 72 * architecturally impossible to misalign the pc. 73 * This will probably cause problems if we ever implement the 74 * Jazelle DBX extensions. 75 */ 76 if (n == 15) { 77 tmp &= ~1; 78 } 79 80 if (n < 16) { 81 /* Core integer register. */ 82 if (n == 13 && arm_feature(env, ARM_FEATURE_M)) { 83 /* M profile SP low bits are always 0 */ 84 tmp &= ~3; 85 } 86 env->regs[n] = tmp; 87 return 4; 88 } 89 if (n == 25) { 90 /* CPSR, or XPSR for M-profile */ 91 if (arm_feature(env, ARM_FEATURE_M)) { 92 /* 93 * Don't allow writing to XPSR.Exception as it can cause 94 * a transition into or out of handler mode (it's not 95 * writable via the MSR insn so this is a reasonable 96 * restriction). Other fields are safe to update. 97 */ 98 xpsr_write(env, tmp, ~XPSR_EXCP); 99 } else { 100 cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); 101 } 102 return 4; 103 } 104 /* Unknown register. */ 105 return 0; 106 } 107 108 static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) 109 { 110 ARMCPU *cpu = env_archcpu(env); 111 int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; 112 113 /* VFP data registers are always little-endian. */ 114 if (reg < nregs) { 115 return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg)); 116 } 117 if (arm_feature(env, ARM_FEATURE_NEON)) { 118 /* Aliases for Q regs. */ 119 nregs += 16; 120 if (reg < nregs) { 121 uint64_t *q = aa32_vfp_qreg(env, reg - 32); 122 return gdb_get_reg128(buf, q[0], q[1]); 123 } 124 } 125 switch (reg - nregs) { 126 case 0: 127 return gdb_get_reg32(buf, vfp_get_fpscr(env)); 128 } 129 return 0; 130 } 131 132 static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) 133 { 134 ARMCPU *cpu = env_archcpu(env); 135 int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; 136 137 if (reg < nregs) { 138 *aa32_vfp_dreg(env, reg) = ldq_le_p(buf); 139 return 8; 140 } 141 if (arm_feature(env, ARM_FEATURE_NEON)) { 142 nregs += 16; 143 if (reg < nregs) { 144 uint64_t *q = aa32_vfp_qreg(env, reg - 32); 145 q[0] = ldq_le_p(buf); 146 q[1] = ldq_le_p(buf + 8); 147 return 16; 148 } 149 } 150 switch (reg - nregs) { 151 case 0: 152 vfp_set_fpscr(env, ldl_p(buf)); 153 return 4; 154 } 155 return 0; 156 } 157 158 static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) 159 { 160 switch (reg) { 161 case 0: 162 return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); 163 case 1: 164 return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); 165 } 166 return 0; 167 } 168 169 static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) 170 { 171 switch (reg) { 172 case 0: 173 env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); 174 return 4; 175 case 1: 176 env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); 177 return 4; 178 } 179 return 0; 180 } 181 182 static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) 183 { 184 switch (reg) { 185 case 0: 186 return gdb_get_reg32(buf, env->v7m.vpr); 187 default: 188 return 0; 189 } 190 } 191 192 static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) 193 { 194 switch (reg) { 195 case 0: 196 env->v7m.vpr = ldl_p(buf); 197 return 4; 198 default: 199 return 0; 200 } 201 } 202 203 /** 204 * arm_get/set_gdb_*: get/set a gdb register 205 * @env: the CPU state 206 * @buf: a buffer to copy to/from 207 * @reg: register number (offset from start of group) 208 * 209 * We return the number of bytes copied 210 */ 211 212 static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) 213 { 214 ARMCPU *cpu = env_archcpu(env); 215 const ARMCPRegInfo *ri; 216 uint32_t key; 217 218 key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg]; 219 ri = get_arm_cp_reginfo(cpu->cp_regs, key); 220 if (ri) { 221 if (cpreg_field_is_64bit(ri)) { 222 return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri)); 223 } else { 224 return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri)); 225 } 226 } 227 return 0; 228 } 229 230 static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) 231 { 232 return 0; 233 } 234 235 static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml, 236 ARMCPRegInfo *ri, uint32_t ri_key, 237 int bitsize, int regnum) 238 { 239 g_string_append_printf(s, "<reg name=\"%s\"", ri->name); 240 g_string_append_printf(s, " bitsize=\"%d\"", bitsize); 241 g_string_append_printf(s, " regnum=\"%d\"", regnum); 242 g_string_append_printf(s, " group=\"cp_regs\"/>"); 243 dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key; 244 dyn_xml->num++; 245 } 246 247 static void arm_register_sysreg_for_xml(gpointer key, gpointer value, 248 gpointer p) 249 { 250 uint32_t ri_key = (uintptr_t)key; 251 ARMCPRegInfo *ri = value; 252 RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p; 253 GString *s = param->s; 254 ARMCPU *cpu = ARM_CPU(param->cs); 255 CPUARMState *env = &cpu->env; 256 DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml; 257 258 if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) { 259 if (arm_feature(env, ARM_FEATURE_AARCH64)) { 260 if (ri->state == ARM_CP_STATE_AA64) { 261 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, 262 param->n++); 263 } 264 } else { 265 if (ri->state == ARM_CP_STATE_AA32) { 266 if (!arm_feature(env, ARM_FEATURE_EL3) && 267 (ri->secure & ARM_CP_SECSTATE_S)) { 268 return; 269 } 270 if (ri->type & ARM_CP_64BIT) { 271 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, 272 param->n++); 273 } else { 274 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32, 275 param->n++); 276 } 277 } 278 } 279 } 280 } 281 282 static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg) 283 { 284 ARMCPU *cpu = ARM_CPU(cs); 285 GString *s = g_string_new(NULL); 286 RegisterSysregXmlParam param = {cs, s, base_reg}; 287 288 cpu->dyn_sysreg_xml.num = 0; 289 cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs)); 290 g_string_printf(s, "<?xml version=\"1.0\"?>"); 291 g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 292 g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">"); 293 g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, ¶m); 294 g_string_append_printf(s, "</feature>"); 295 cpu->dyn_sysreg_xml.desc = g_string_free(s, false); 296 return cpu->dyn_sysreg_xml.num; 297 } 298 299 #ifdef CONFIG_TCG 300 typedef enum { 301 M_SYSREG_MSP, 302 M_SYSREG_PSP, 303 M_SYSREG_PRIMASK, 304 M_SYSREG_CONTROL, 305 M_SYSREG_BASEPRI, 306 M_SYSREG_FAULTMASK, 307 M_SYSREG_MSPLIM, 308 M_SYSREG_PSPLIM, 309 } MProfileSysreg; 310 311 static const struct { 312 const char *name; 313 int feature; 314 } m_sysreg_def[] = { 315 [M_SYSREG_MSP] = { "msp", ARM_FEATURE_M }, 316 [M_SYSREG_PSP] = { "psp", ARM_FEATURE_M }, 317 [M_SYSREG_PRIMASK] = { "primask", ARM_FEATURE_M }, 318 [M_SYSREG_CONTROL] = { "control", ARM_FEATURE_M }, 319 [M_SYSREG_BASEPRI] = { "basepri", ARM_FEATURE_M_MAIN }, 320 [M_SYSREG_FAULTMASK] = { "faultmask", ARM_FEATURE_M_MAIN }, 321 [M_SYSREG_MSPLIM] = { "msplim", ARM_FEATURE_V8 }, 322 [M_SYSREG_PSPLIM] = { "psplim", ARM_FEATURE_V8 }, 323 }; 324 325 static uint32_t *m_sysreg_ptr(CPUARMState *env, MProfileSysreg reg, bool sec) 326 { 327 uint32_t *ptr; 328 329 switch (reg) { 330 case M_SYSREG_MSP: 331 ptr = arm_v7m_get_sp_ptr(env, sec, false, true); 332 break; 333 case M_SYSREG_PSP: 334 ptr = arm_v7m_get_sp_ptr(env, sec, true, true); 335 break; 336 case M_SYSREG_MSPLIM: 337 ptr = &env->v7m.msplim[sec]; 338 break; 339 case M_SYSREG_PSPLIM: 340 ptr = &env->v7m.psplim[sec]; 341 break; 342 case M_SYSREG_PRIMASK: 343 ptr = &env->v7m.primask[sec]; 344 break; 345 case M_SYSREG_BASEPRI: 346 ptr = &env->v7m.basepri[sec]; 347 break; 348 case M_SYSREG_FAULTMASK: 349 ptr = &env->v7m.faultmask[sec]; 350 break; 351 case M_SYSREG_CONTROL: 352 ptr = &env->v7m.control[sec]; 353 break; 354 default: 355 return NULL; 356 } 357 return arm_feature(env, m_sysreg_def[reg].feature) ? ptr : NULL; 358 } 359 360 static int m_sysreg_get(CPUARMState *env, GByteArray *buf, 361 MProfileSysreg reg, bool secure) 362 { 363 uint32_t *ptr = m_sysreg_ptr(env, reg, secure); 364 365 if (ptr == NULL) { 366 return 0; 367 } 368 return gdb_get_reg32(buf, *ptr); 369 } 370 371 static int arm_gdb_get_m_systemreg(CPUARMState *env, GByteArray *buf, int reg) 372 { 373 /* 374 * Here, we emulate MRS instruction, where CONTROL has a mix of 375 * banked and non-banked bits. 376 */ 377 if (reg == M_SYSREG_CONTROL) { 378 return gdb_get_reg32(buf, arm_v7m_mrs_control(env, env->v7m.secure)); 379 } 380 return m_sysreg_get(env, buf, reg, env->v7m.secure); 381 } 382 383 static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg) 384 { 385 return 0; /* TODO */ 386 } 387 388 static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg) 389 { 390 ARMCPU *cpu = ARM_CPU(cs); 391 CPUARMState *env = &cpu->env; 392 GString *s = g_string_new(NULL); 393 int base_reg = orig_base_reg; 394 int i; 395 396 g_string_printf(s, "<?xml version=\"1.0\"?>"); 397 g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 398 g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.m-system\">\n"); 399 400 for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) { 401 if (arm_feature(env, m_sysreg_def[i].feature)) { 402 g_string_append_printf(s, 403 "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n", 404 m_sysreg_def[i].name, base_reg++); 405 } 406 } 407 408 g_string_append_printf(s, "</feature>"); 409 cpu->dyn_m_systemreg_xml.desc = g_string_free(s, false); 410 cpu->dyn_m_systemreg_xml.num = base_reg - orig_base_reg; 411 412 return cpu->dyn_m_systemreg_xml.num; 413 } 414 415 #ifndef CONFIG_USER_ONLY 416 /* 417 * For user-only, we see the non-secure registers via m_systemreg above. 418 * For secext, encode the non-secure view as even and secure view as odd. 419 */ 420 static int arm_gdb_get_m_secextreg(CPUARMState *env, GByteArray *buf, int reg) 421 { 422 return m_sysreg_get(env, buf, reg >> 1, reg & 1); 423 } 424 425 static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg) 426 { 427 return 0; /* TODO */ 428 } 429 430 static int arm_gen_dynamic_m_secextreg_xml(CPUState *cs, int orig_base_reg) 431 { 432 ARMCPU *cpu = ARM_CPU(cs); 433 GString *s = g_string_new(NULL); 434 int base_reg = orig_base_reg; 435 int i; 436 437 g_string_printf(s, "<?xml version=\"1.0\"?>"); 438 g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 439 g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.secext\">\n"); 440 441 for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) { 442 g_string_append_printf(s, 443 "<reg name=\"%s_ns\" bitsize=\"32\" regnum=\"%d\"/>\n", 444 m_sysreg_def[i].name, base_reg++); 445 g_string_append_printf(s, 446 "<reg name=\"%s_s\" bitsize=\"32\" regnum=\"%d\"/>\n", 447 m_sysreg_def[i].name, base_reg++); 448 } 449 450 g_string_append_printf(s, "</feature>"); 451 cpu->dyn_m_secextreg_xml.desc = g_string_free(s, false); 452 cpu->dyn_m_secextreg_xml.num = base_reg - orig_base_reg; 453 454 return cpu->dyn_m_secextreg_xml.num; 455 } 456 #endif 457 #endif /* CONFIG_TCG */ 458 459 const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) 460 { 461 ARMCPU *cpu = ARM_CPU(cs); 462 463 if (strcmp(xmlname, "system-registers.xml") == 0) { 464 return cpu->dyn_sysreg_xml.desc; 465 } else if (strcmp(xmlname, "sve-registers.xml") == 0) { 466 return cpu->dyn_svereg_xml.desc; 467 } else if (strcmp(xmlname, "arm-m-system.xml") == 0) { 468 return cpu->dyn_m_systemreg_xml.desc; 469 #ifndef CONFIG_USER_ONLY 470 } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) { 471 return cpu->dyn_m_secextreg_xml.desc; 472 #endif 473 } 474 return NULL; 475 } 476 477 void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) 478 { 479 CPUState *cs = CPU(cpu); 480 CPUARMState *env = &cpu->env; 481 482 if (arm_feature(env, ARM_FEATURE_AARCH64)) { 483 /* 484 * The lower part of each SVE register aliases to the FPU 485 * registers so we don't need to include both. 486 */ 487 #ifdef TARGET_AARCH64 488 if (isar_feature_aa64_sve(&cpu->isar)) { 489 int nreg = arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs); 490 gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg, 491 aarch64_gdb_set_sve_reg, nreg, 492 "sve-registers.xml", 0); 493 } else { 494 gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg, 495 aarch64_gdb_set_fpu_reg, 496 34, "aarch64-fpu.xml", 0); 497 } 498 /* 499 * Note that we report pauth information via the feature name 500 * org.gnu.gdb.aarch64.pauth_v2, not org.gnu.gdb.aarch64.pauth. 501 * GDB versions 9 through 12 have a bug where they will crash 502 * if they see the latter XML from QEMU. 503 */ 504 if (isar_feature_aa64_pauth(&cpu->isar)) { 505 gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg, 506 aarch64_gdb_set_pauth_reg, 507 4, "aarch64-pauth.xml", 0); 508 } 509 #endif 510 } else { 511 if (arm_feature(env, ARM_FEATURE_NEON)) { 512 gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, 513 49, "arm-neon.xml", 0); 514 } else if (cpu_isar_feature(aa32_simd_r32, cpu)) { 515 gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, 516 33, "arm-vfp3.xml", 0); 517 } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) { 518 gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, 519 17, "arm-vfp.xml", 0); 520 } 521 if (!arm_feature(env, ARM_FEATURE_M)) { 522 /* 523 * A and R profile have FP sysregs FPEXC and FPSID that we 524 * expose to gdb. 525 */ 526 gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg, 527 2, "arm-vfp-sysregs.xml", 0); 528 } 529 } 530 if (cpu_isar_feature(aa32_mve, cpu) && tcg_enabled()) { 531 gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg, 532 1, "arm-m-profile-mve.xml", 0); 533 } 534 gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg, 535 arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs), 536 "system-registers.xml", 0); 537 538 #ifdef CONFIG_TCG 539 if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) { 540 gdb_register_coprocessor(cs, 541 arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg, 542 arm_gen_dynamic_m_systemreg_xml(cs, cs->gdb_num_regs), 543 "arm-m-system.xml", 0); 544 #ifndef CONFIG_USER_ONLY 545 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { 546 gdb_register_coprocessor(cs, 547 arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg, 548 arm_gen_dynamic_m_secextreg_xml(cs, cs->gdb_num_regs), 549 "arm-m-secext.xml", 0); 550 } 551 #endif 552 } 553 #endif /* CONFIG_TCG */ 554 } 555