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