1fcf5ef2aSThomas Huth /* 2fcf5ef2aSThomas Huth * ARM gdb server stub 3fcf5ef2aSThomas Huth * 4fcf5ef2aSThomas Huth * Copyright (c) 2003-2005 Fabrice Bellard 5fcf5ef2aSThomas Huth * Copyright (c) 2013 SUSE LINUX Products GmbH 6fcf5ef2aSThomas Huth * 7fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or 8fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public 9fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either 1050f57e09SChetan Pant * version 2.1 of the License, or (at your option) any later version. 11fcf5ef2aSThomas Huth * 12fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful, 13fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of 14fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15fcf5ef2aSThomas Huth * Lesser General Public License for more details. 16fcf5ef2aSThomas Huth * 17fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public 18fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>. 19fcf5ef2aSThomas Huth */ 20fcf5ef2aSThomas Huth #include "qemu/osdep.h" 21fcf5ef2aSThomas Huth #include "cpu.h" 22fcf5ef2aSThomas Huth #include "exec/gdbstub.h" 234ea5fe99SAlex Bennée #include "gdbstub/helpers.h" 2446e3b237SPhilippe Mathieu-Daudé #include "sysemu/tcg.h" 25cf7c6d10SRichard Henderson #include "internals.h" 26*5a534314SPeter Maydell #include "cpu-features.h" 27cf7c6d10SRichard Henderson #include "cpregs.h" 28fcf5ef2aSThomas Huth 29200bf5b7SAbdallah Bouassida typedef struct RegisterSysregXmlParam { 30200bf5b7SAbdallah Bouassida CPUState *cs; 31200bf5b7SAbdallah Bouassida GString *s; 3232d6e32aSAlex Bennée int n; 33200bf5b7SAbdallah Bouassida } RegisterSysregXmlParam; 34200bf5b7SAbdallah Bouassida 35fcf5ef2aSThomas Huth /* Old gdb always expect FPA registers. Newer (xml-aware) gdb only expect 36fcf5ef2aSThomas Huth whatever the target description contains. Due to a historical mishap 37fcf5ef2aSThomas Huth the FPA registers appear in between core integer regs and the CPSR. 38fcf5ef2aSThomas Huth We hack round this by giving the FPA regs zero size when talking to a 39fcf5ef2aSThomas Huth newer gdb. */ 40fcf5ef2aSThomas Huth 41a010bdbeSAlex Bennée int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) 42fcf5ef2aSThomas Huth { 43fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(cs); 44fcf5ef2aSThomas Huth CPUARMState *env = &cpu->env; 45fcf5ef2aSThomas Huth 46fcf5ef2aSThomas Huth if (n < 16) { 47fcf5ef2aSThomas Huth /* Core integer register. */ 48fcf5ef2aSThomas Huth return gdb_get_reg32(mem_buf, env->regs[n]); 49fcf5ef2aSThomas Huth } 50dd2f7e29SAkihiko Odaki if (n == 25) { 51c888f7e0SPeter Maydell /* CPSR, or XPSR for M-profile */ 52c888f7e0SPeter Maydell if (arm_feature(env, ARM_FEATURE_M)) { 53c888f7e0SPeter Maydell return gdb_get_reg32(mem_buf, xpsr_read(env)); 54c888f7e0SPeter Maydell } else { 55fcf5ef2aSThomas Huth return gdb_get_reg32(mem_buf, cpsr_read(env)); 56fcf5ef2aSThomas Huth } 57c888f7e0SPeter Maydell } 58fcf5ef2aSThomas Huth /* Unknown register. */ 59fcf5ef2aSThomas Huth return 0; 60fcf5ef2aSThomas Huth } 61fcf5ef2aSThomas Huth 62fcf5ef2aSThomas Huth int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) 63fcf5ef2aSThomas Huth { 64fcf5ef2aSThomas Huth ARMCPU *cpu = ARM_CPU(cs); 65fcf5ef2aSThomas Huth CPUARMState *env = &cpu->env; 66fcf5ef2aSThomas Huth uint32_t tmp; 67fcf5ef2aSThomas Huth 68fcf5ef2aSThomas Huth tmp = ldl_p(mem_buf); 69fcf5ef2aSThomas Huth 707055fe4bSRichard Henderson /* 717055fe4bSRichard Henderson * Mask out low bits of PC to workaround gdb bugs. 727055fe4bSRichard Henderson * This avoids an assert in thumb_tr_translate_insn, because it is 737055fe4bSRichard Henderson * architecturally impossible to misalign the pc. 747055fe4bSRichard Henderson * This will probably cause problems if we ever implement the 757055fe4bSRichard Henderson * Jazelle DBX extensions. 767055fe4bSRichard Henderson */ 77fcf5ef2aSThomas Huth if (n == 15) { 78fcf5ef2aSThomas Huth tmp &= ~1; 79fcf5ef2aSThomas Huth } 80fcf5ef2aSThomas Huth 81fcf5ef2aSThomas Huth if (n < 16) { 82fcf5ef2aSThomas Huth /* Core integer register. */ 83888f470fSPeter Maydell if (n == 13 && arm_feature(env, ARM_FEATURE_M)) { 84888f470fSPeter Maydell /* M profile SP low bits are always 0 */ 85888f470fSPeter Maydell tmp &= ~3; 86888f470fSPeter Maydell } 87fcf5ef2aSThomas Huth env->regs[n] = tmp; 88fcf5ef2aSThomas Huth return 4; 89fcf5ef2aSThomas Huth } 90dd2f7e29SAkihiko Odaki if (n == 25) { 91c888f7e0SPeter Maydell /* CPSR, or XPSR for M-profile */ 92c888f7e0SPeter Maydell if (arm_feature(env, ARM_FEATURE_M)) { 93c888f7e0SPeter Maydell /* 94c888f7e0SPeter Maydell * Don't allow writing to XPSR.Exception as it can cause 95c888f7e0SPeter Maydell * a transition into or out of handler mode (it's not 969323e79fSPeter Maydell * writable via the MSR insn so this is a reasonable 97c888f7e0SPeter Maydell * restriction). Other fields are safe to update. 98c888f7e0SPeter Maydell */ 99c888f7e0SPeter Maydell xpsr_write(env, tmp, ~XPSR_EXCP); 100c888f7e0SPeter Maydell } else { 101fcf5ef2aSThomas Huth cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub); 102c888f7e0SPeter Maydell } 103fcf5ef2aSThomas Huth return 4; 104fcf5ef2aSThomas Huth } 105fcf5ef2aSThomas Huth /* Unknown register. */ 106fcf5ef2aSThomas Huth return 0; 107fcf5ef2aSThomas Huth } 108200bf5b7SAbdallah Bouassida 10989f4f20eSPeter Maydell static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) 11089f4f20eSPeter Maydell { 11189f4f20eSPeter Maydell ARMCPU *cpu = env_archcpu(env); 11289f4f20eSPeter Maydell int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; 11389f4f20eSPeter Maydell 11489f4f20eSPeter Maydell /* VFP data registers are always little-endian. */ 11589f4f20eSPeter Maydell if (reg < nregs) { 11689f4f20eSPeter Maydell return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg)); 11789f4f20eSPeter Maydell } 11889f4f20eSPeter Maydell if (arm_feature(env, ARM_FEATURE_NEON)) { 11989f4f20eSPeter Maydell /* Aliases for Q regs. */ 12089f4f20eSPeter Maydell nregs += 16; 12189f4f20eSPeter Maydell if (reg < nregs) { 12289f4f20eSPeter Maydell uint64_t *q = aa32_vfp_qreg(env, reg - 32); 12389f4f20eSPeter Maydell return gdb_get_reg128(buf, q[0], q[1]); 12489f4f20eSPeter Maydell } 12589f4f20eSPeter Maydell } 12689f4f20eSPeter Maydell switch (reg - nregs) { 12789f4f20eSPeter Maydell case 0: 12889f4f20eSPeter Maydell return gdb_get_reg32(buf, vfp_get_fpscr(env)); 12989f4f20eSPeter Maydell } 13089f4f20eSPeter Maydell return 0; 13189f4f20eSPeter Maydell } 13289f4f20eSPeter Maydell 13389f4f20eSPeter Maydell static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) 13489f4f20eSPeter Maydell { 13589f4f20eSPeter Maydell ARMCPU *cpu = env_archcpu(env); 13689f4f20eSPeter Maydell int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; 13789f4f20eSPeter Maydell 13889f4f20eSPeter Maydell if (reg < nregs) { 13989f4f20eSPeter Maydell *aa32_vfp_dreg(env, reg) = ldq_le_p(buf); 14089f4f20eSPeter Maydell return 8; 14189f4f20eSPeter Maydell } 14289f4f20eSPeter Maydell if (arm_feature(env, ARM_FEATURE_NEON)) { 14389f4f20eSPeter Maydell nregs += 16; 14489f4f20eSPeter Maydell if (reg < nregs) { 14589f4f20eSPeter Maydell uint64_t *q = aa32_vfp_qreg(env, reg - 32); 14689f4f20eSPeter Maydell q[0] = ldq_le_p(buf); 14789f4f20eSPeter Maydell q[1] = ldq_le_p(buf + 8); 14889f4f20eSPeter Maydell return 16; 14989f4f20eSPeter Maydell } 15089f4f20eSPeter Maydell } 15189f4f20eSPeter Maydell switch (reg - nregs) { 15289f4f20eSPeter Maydell case 0: 153b355f08aSPeter Maydell vfp_set_fpscr(env, ldl_p(buf)); 154b355f08aSPeter Maydell return 4; 155b355f08aSPeter Maydell } 156b355f08aSPeter Maydell return 0; 157b355f08aSPeter Maydell } 158b355f08aSPeter Maydell 159b355f08aSPeter Maydell static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) 160b355f08aSPeter Maydell { 161b355f08aSPeter Maydell switch (reg) { 162b355f08aSPeter Maydell case 0: 163b355f08aSPeter Maydell return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); 164b355f08aSPeter Maydell case 1: 165b355f08aSPeter Maydell return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); 166b355f08aSPeter Maydell } 167b355f08aSPeter Maydell return 0; 168b355f08aSPeter Maydell } 169b355f08aSPeter Maydell 170b355f08aSPeter Maydell static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) 171b355f08aSPeter Maydell { 172b355f08aSPeter Maydell switch (reg) { 173b355f08aSPeter Maydell case 0: 17489f4f20eSPeter Maydell env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); 17589f4f20eSPeter Maydell return 4; 17689f4f20eSPeter Maydell case 1: 17789f4f20eSPeter Maydell env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); 17889f4f20eSPeter Maydell return 4; 17989f4f20eSPeter Maydell } 18089f4f20eSPeter Maydell return 0; 18189f4f20eSPeter Maydell } 18289f4f20eSPeter Maydell 183dbd9e084SPeter Maydell static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) 184dbd9e084SPeter Maydell { 185dbd9e084SPeter Maydell switch (reg) { 186dbd9e084SPeter Maydell case 0: 187dbd9e084SPeter Maydell return gdb_get_reg32(buf, env->v7m.vpr); 188dbd9e084SPeter Maydell default: 189dbd9e084SPeter Maydell return 0; 190dbd9e084SPeter Maydell } 191dbd9e084SPeter Maydell } 192dbd9e084SPeter Maydell 193dbd9e084SPeter Maydell static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) 194dbd9e084SPeter Maydell { 195dbd9e084SPeter Maydell switch (reg) { 196dbd9e084SPeter Maydell case 0: 197dbd9e084SPeter Maydell env->v7m.vpr = ldl_p(buf); 198dbd9e084SPeter Maydell return 4; 199dbd9e084SPeter Maydell default: 200dbd9e084SPeter Maydell return 0; 201dbd9e084SPeter Maydell } 202dbd9e084SPeter Maydell } 203dbd9e084SPeter Maydell 20489f4f20eSPeter Maydell /** 20589f4f20eSPeter Maydell * arm_get/set_gdb_*: get/set a gdb register 20689f4f20eSPeter Maydell * @env: the CPU state 20789f4f20eSPeter Maydell * @buf: a buffer to copy to/from 20889f4f20eSPeter Maydell * @reg: register number (offset from start of group) 20989f4f20eSPeter Maydell * 21089f4f20eSPeter Maydell * We return the number of bytes copied 21189f4f20eSPeter Maydell */ 21289f4f20eSPeter Maydell 21389f4f20eSPeter Maydell static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) 21489f4f20eSPeter Maydell { 21589f4f20eSPeter Maydell ARMCPU *cpu = env_archcpu(env); 21689f4f20eSPeter Maydell const ARMCPRegInfo *ri; 21789f4f20eSPeter Maydell uint32_t key; 21889f4f20eSPeter Maydell 21989f4f20eSPeter Maydell key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg]; 22089f4f20eSPeter Maydell ri = get_arm_cp_reginfo(cpu->cp_regs, key); 22189f4f20eSPeter Maydell if (ri) { 22289f4f20eSPeter Maydell if (cpreg_field_is_64bit(ri)) { 22389f4f20eSPeter Maydell return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri)); 22489f4f20eSPeter Maydell } else { 22589f4f20eSPeter Maydell return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri)); 22689f4f20eSPeter Maydell } 22789f4f20eSPeter Maydell } 22889f4f20eSPeter Maydell return 0; 22989f4f20eSPeter Maydell } 23089f4f20eSPeter Maydell 23189f4f20eSPeter Maydell static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) 23289f4f20eSPeter Maydell { 23389f4f20eSPeter Maydell return 0; 23489f4f20eSPeter Maydell } 23589f4f20eSPeter Maydell 236448d4d14SAlex Bennée static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml, 237200bf5b7SAbdallah Bouassida ARMCPRegInfo *ri, uint32_t ri_key, 23832d6e32aSAlex Bennée int bitsize, int regnum) 239200bf5b7SAbdallah Bouassida { 240200bf5b7SAbdallah Bouassida g_string_append_printf(s, "<reg name=\"%s\"", ri->name); 241200bf5b7SAbdallah Bouassida g_string_append_printf(s, " bitsize=\"%d\"", bitsize); 24232d6e32aSAlex Bennée g_string_append_printf(s, " regnum=\"%d\"", regnum); 243200bf5b7SAbdallah Bouassida g_string_append_printf(s, " group=\"cp_regs\"/>"); 244448d4d14SAlex Bennée dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key; 245448d4d14SAlex Bennée dyn_xml->num++; 246200bf5b7SAbdallah Bouassida } 247200bf5b7SAbdallah Bouassida 248200bf5b7SAbdallah Bouassida static void arm_register_sysreg_for_xml(gpointer key, gpointer value, 249200bf5b7SAbdallah Bouassida gpointer p) 250200bf5b7SAbdallah Bouassida { 2515860362dSRichard Henderson uint32_t ri_key = (uintptr_t)key; 252200bf5b7SAbdallah Bouassida ARMCPRegInfo *ri = value; 253200bf5b7SAbdallah Bouassida RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p; 254200bf5b7SAbdallah Bouassida GString *s = param->s; 255200bf5b7SAbdallah Bouassida ARMCPU *cpu = ARM_CPU(param->cs); 256200bf5b7SAbdallah Bouassida CPUARMState *env = &cpu->env; 257448d4d14SAlex Bennée DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml; 258200bf5b7SAbdallah Bouassida 259200bf5b7SAbdallah Bouassida if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) { 260200bf5b7SAbdallah Bouassida if (arm_feature(env, ARM_FEATURE_AARCH64)) { 261200bf5b7SAbdallah Bouassida if (ri->state == ARM_CP_STATE_AA64) { 26232d6e32aSAlex Bennée arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, 26332d6e32aSAlex Bennée param->n++); 264200bf5b7SAbdallah Bouassida } 265200bf5b7SAbdallah Bouassida } else { 266200bf5b7SAbdallah Bouassida if (ri->state == ARM_CP_STATE_AA32) { 267200bf5b7SAbdallah Bouassida if (!arm_feature(env, ARM_FEATURE_EL3) && 268200bf5b7SAbdallah Bouassida (ri->secure & ARM_CP_SECSTATE_S)) { 269200bf5b7SAbdallah Bouassida return; 270200bf5b7SAbdallah Bouassida } 271200bf5b7SAbdallah Bouassida if (ri->type & ARM_CP_64BIT) { 27232d6e32aSAlex Bennée arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64, 27332d6e32aSAlex Bennée param->n++); 274200bf5b7SAbdallah Bouassida } else { 27532d6e32aSAlex Bennée arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32, 27632d6e32aSAlex Bennée param->n++); 277200bf5b7SAbdallah Bouassida } 278200bf5b7SAbdallah Bouassida } 279200bf5b7SAbdallah Bouassida } 280200bf5b7SAbdallah Bouassida } 281200bf5b7SAbdallah Bouassida } 282200bf5b7SAbdallah Bouassida 2834bce95b4SRichard Henderson static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg) 284200bf5b7SAbdallah Bouassida { 285200bf5b7SAbdallah Bouassida ARMCPU *cpu = ARM_CPU(cs); 286200bf5b7SAbdallah Bouassida GString *s = g_string_new(NULL); 28732d6e32aSAlex Bennée RegisterSysregXmlParam param = {cs, s, base_reg}; 288200bf5b7SAbdallah Bouassida 289448d4d14SAlex Bennée cpu->dyn_sysreg_xml.num = 0; 290448d4d14SAlex Bennée cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs)); 291200bf5b7SAbdallah Bouassida g_string_printf(s, "<?xml version=\"1.0\"?>"); 292200bf5b7SAbdallah Bouassida g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 293200bf5b7SAbdallah Bouassida g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">"); 294200bf5b7SAbdallah Bouassida g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, ¶m); 295200bf5b7SAbdallah Bouassida g_string_append_printf(s, "</feature>"); 296448d4d14SAlex Bennée cpu->dyn_sysreg_xml.desc = g_string_free(s, false); 297448d4d14SAlex Bennée return cpu->dyn_sysreg_xml.num; 298200bf5b7SAbdallah Bouassida } 299200bf5b7SAbdallah Bouassida 300893ca916SFabiano Rosas #ifdef CONFIG_TCG 3017d8b28b8SRichard Henderson typedef enum { 3027d8b28b8SRichard Henderson M_SYSREG_MSP, 3037d8b28b8SRichard Henderson M_SYSREG_PSP, 3047d8b28b8SRichard Henderson M_SYSREG_PRIMASK, 3057d8b28b8SRichard Henderson M_SYSREG_CONTROL, 3067d8b28b8SRichard Henderson M_SYSREG_BASEPRI, 3077d8b28b8SRichard Henderson M_SYSREG_FAULTMASK, 3087d8b28b8SRichard Henderson M_SYSREG_MSPLIM, 3097d8b28b8SRichard Henderson M_SYSREG_PSPLIM, 3107d8b28b8SRichard Henderson } MProfileSysreg; 3117d8b28b8SRichard Henderson 3127d8b28b8SRichard Henderson static const struct { 3137d8b28b8SRichard Henderson const char *name; 3147d8b28b8SRichard Henderson int feature; 3157d8b28b8SRichard Henderson } m_sysreg_def[] = { 3167d8b28b8SRichard Henderson [M_SYSREG_MSP] = { "msp", ARM_FEATURE_M }, 3177d8b28b8SRichard Henderson [M_SYSREG_PSP] = { "psp", ARM_FEATURE_M }, 3187d8b28b8SRichard Henderson [M_SYSREG_PRIMASK] = { "primask", ARM_FEATURE_M }, 3197d8b28b8SRichard Henderson [M_SYSREG_CONTROL] = { "control", ARM_FEATURE_M }, 3207d8b28b8SRichard Henderson [M_SYSREG_BASEPRI] = { "basepri", ARM_FEATURE_M_MAIN }, 3217d8b28b8SRichard Henderson [M_SYSREG_FAULTMASK] = { "faultmask", ARM_FEATURE_M_MAIN }, 3227d8b28b8SRichard Henderson [M_SYSREG_MSPLIM] = { "msplim", ARM_FEATURE_V8 }, 3237d8b28b8SRichard Henderson [M_SYSREG_PSPLIM] = { "psplim", ARM_FEATURE_V8 }, 3247d8b28b8SRichard Henderson }; 3257d8b28b8SRichard Henderson 3267d8b28b8SRichard Henderson static uint32_t *m_sysreg_ptr(CPUARMState *env, MProfileSysreg reg, bool sec) 3277d8b28b8SRichard Henderson { 3287d8b28b8SRichard Henderson uint32_t *ptr; 3297d8b28b8SRichard Henderson 3307d8b28b8SRichard Henderson switch (reg) { 3317d8b28b8SRichard Henderson case M_SYSREG_MSP: 3327d8b28b8SRichard Henderson ptr = arm_v7m_get_sp_ptr(env, sec, false, true); 3337d8b28b8SRichard Henderson break; 3347d8b28b8SRichard Henderson case M_SYSREG_PSP: 3357d8b28b8SRichard Henderson ptr = arm_v7m_get_sp_ptr(env, sec, true, true); 3367d8b28b8SRichard Henderson break; 3377d8b28b8SRichard Henderson case M_SYSREG_MSPLIM: 3387d8b28b8SRichard Henderson ptr = &env->v7m.msplim[sec]; 3397d8b28b8SRichard Henderson break; 3407d8b28b8SRichard Henderson case M_SYSREG_PSPLIM: 3417d8b28b8SRichard Henderson ptr = &env->v7m.psplim[sec]; 3427d8b28b8SRichard Henderson break; 3437d8b28b8SRichard Henderson case M_SYSREG_PRIMASK: 3447d8b28b8SRichard Henderson ptr = &env->v7m.primask[sec]; 3457d8b28b8SRichard Henderson break; 3467d8b28b8SRichard Henderson case M_SYSREG_BASEPRI: 3477d8b28b8SRichard Henderson ptr = &env->v7m.basepri[sec]; 3487d8b28b8SRichard Henderson break; 3497d8b28b8SRichard Henderson case M_SYSREG_FAULTMASK: 3507d8b28b8SRichard Henderson ptr = &env->v7m.faultmask[sec]; 3517d8b28b8SRichard Henderson break; 3527d8b28b8SRichard Henderson case M_SYSREG_CONTROL: 3537d8b28b8SRichard Henderson ptr = &env->v7m.control[sec]; 3547d8b28b8SRichard Henderson break; 3557d8b28b8SRichard Henderson default: 3567d8b28b8SRichard Henderson return NULL; 3577d8b28b8SRichard Henderson } 3587d8b28b8SRichard Henderson return arm_feature(env, m_sysreg_def[reg].feature) ? ptr : NULL; 3597d8b28b8SRichard Henderson } 3607d8b28b8SRichard Henderson 3617d8b28b8SRichard Henderson static int m_sysreg_get(CPUARMState *env, GByteArray *buf, 3627d8b28b8SRichard Henderson MProfileSysreg reg, bool secure) 3637d8b28b8SRichard Henderson { 3647d8b28b8SRichard Henderson uint32_t *ptr = m_sysreg_ptr(env, reg, secure); 3657d8b28b8SRichard Henderson 3667d8b28b8SRichard Henderson if (ptr == NULL) { 3677d8b28b8SRichard Henderson return 0; 3687d8b28b8SRichard Henderson } 3697d8b28b8SRichard Henderson return gdb_get_reg32(buf, *ptr); 3707d8b28b8SRichard Henderson } 3717d8b28b8SRichard Henderson 3727d8b28b8SRichard Henderson static int arm_gdb_get_m_systemreg(CPUARMState *env, GByteArray *buf, int reg) 3737d8b28b8SRichard Henderson { 3747d8b28b8SRichard Henderson /* 3757d8b28b8SRichard Henderson * Here, we emulate MRS instruction, where CONTROL has a mix of 3767d8b28b8SRichard Henderson * banked and non-banked bits. 3777d8b28b8SRichard Henderson */ 3787d8b28b8SRichard Henderson if (reg == M_SYSREG_CONTROL) { 3797d8b28b8SRichard Henderson return gdb_get_reg32(buf, arm_v7m_mrs_control(env, env->v7m.secure)); 3807d8b28b8SRichard Henderson } 3817d8b28b8SRichard Henderson return m_sysreg_get(env, buf, reg, env->v7m.secure); 3827d8b28b8SRichard Henderson } 3837d8b28b8SRichard Henderson 3847d8b28b8SRichard Henderson static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg) 3857d8b28b8SRichard Henderson { 3867d8b28b8SRichard Henderson return 0; /* TODO */ 3877d8b28b8SRichard Henderson } 3887d8b28b8SRichard Henderson 3897d8b28b8SRichard Henderson static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg) 3907d8b28b8SRichard Henderson { 3917d8b28b8SRichard Henderson ARMCPU *cpu = ARM_CPU(cs); 3927d8b28b8SRichard Henderson CPUARMState *env = &cpu->env; 3937d8b28b8SRichard Henderson GString *s = g_string_new(NULL); 3947d8b28b8SRichard Henderson int base_reg = orig_base_reg; 3957d8b28b8SRichard Henderson int i; 3967d8b28b8SRichard Henderson 3977d8b28b8SRichard Henderson g_string_printf(s, "<?xml version=\"1.0\"?>"); 3987d8b28b8SRichard Henderson g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 3997d8b28b8SRichard Henderson g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.m-system\">\n"); 4007d8b28b8SRichard Henderson 4017d8b28b8SRichard Henderson for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) { 4027d8b28b8SRichard Henderson if (arm_feature(env, m_sysreg_def[i].feature)) { 4037d8b28b8SRichard Henderson g_string_append_printf(s, 4047d8b28b8SRichard Henderson "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n", 4057d8b28b8SRichard Henderson m_sysreg_def[i].name, base_reg++); 4067d8b28b8SRichard Henderson } 4077d8b28b8SRichard Henderson } 4087d8b28b8SRichard Henderson 4097d8b28b8SRichard Henderson g_string_append_printf(s, "</feature>"); 4107d8b28b8SRichard Henderson cpu->dyn_m_systemreg_xml.desc = g_string_free(s, false); 4117d8b28b8SRichard Henderson cpu->dyn_m_systemreg_xml.num = base_reg - orig_base_reg; 4127d8b28b8SRichard Henderson 4137d8b28b8SRichard Henderson return cpu->dyn_m_systemreg_xml.num; 4147d8b28b8SRichard Henderson } 4157d8b28b8SRichard Henderson 4167d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY 4177d8b28b8SRichard Henderson /* 4187d8b28b8SRichard Henderson * For user-only, we see the non-secure registers via m_systemreg above. 4197d8b28b8SRichard Henderson * For secext, encode the non-secure view as even and secure view as odd. 4207d8b28b8SRichard Henderson */ 4217d8b28b8SRichard Henderson static int arm_gdb_get_m_secextreg(CPUARMState *env, GByteArray *buf, int reg) 4227d8b28b8SRichard Henderson { 4237d8b28b8SRichard Henderson return m_sysreg_get(env, buf, reg >> 1, reg & 1); 4247d8b28b8SRichard Henderson } 4257d8b28b8SRichard Henderson 4267d8b28b8SRichard Henderson static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg) 4277d8b28b8SRichard Henderson { 4287d8b28b8SRichard Henderson return 0; /* TODO */ 4297d8b28b8SRichard Henderson } 4307d8b28b8SRichard Henderson 4317d8b28b8SRichard Henderson static int arm_gen_dynamic_m_secextreg_xml(CPUState *cs, int orig_base_reg) 4327d8b28b8SRichard Henderson { 4337d8b28b8SRichard Henderson ARMCPU *cpu = ARM_CPU(cs); 4347d8b28b8SRichard Henderson GString *s = g_string_new(NULL); 4357d8b28b8SRichard Henderson int base_reg = orig_base_reg; 4367d8b28b8SRichard Henderson int i; 4377d8b28b8SRichard Henderson 4387d8b28b8SRichard Henderson g_string_printf(s, "<?xml version=\"1.0\"?>"); 4397d8b28b8SRichard Henderson g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">"); 4407d8b28b8SRichard Henderson g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.secext\">\n"); 4417d8b28b8SRichard Henderson 4427d8b28b8SRichard Henderson for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) { 4437d8b28b8SRichard Henderson g_string_append_printf(s, 4447d8b28b8SRichard Henderson "<reg name=\"%s_ns\" bitsize=\"32\" regnum=\"%d\"/>\n", 4457d8b28b8SRichard Henderson m_sysreg_def[i].name, base_reg++); 4467d8b28b8SRichard Henderson g_string_append_printf(s, 4477d8b28b8SRichard Henderson "<reg name=\"%s_s\" bitsize=\"32\" regnum=\"%d\"/>\n", 4487d8b28b8SRichard Henderson m_sysreg_def[i].name, base_reg++); 4497d8b28b8SRichard Henderson } 4507d8b28b8SRichard Henderson 4517d8b28b8SRichard Henderson g_string_append_printf(s, "</feature>"); 4527d8b28b8SRichard Henderson cpu->dyn_m_secextreg_xml.desc = g_string_free(s, false); 4537d8b28b8SRichard Henderson cpu->dyn_m_secextreg_xml.num = base_reg - orig_base_reg; 4547d8b28b8SRichard Henderson 4557d8b28b8SRichard Henderson return cpu->dyn_m_secextreg_xml.num; 4567d8b28b8SRichard Henderson } 4577d8b28b8SRichard Henderson #endif 458893ca916SFabiano Rosas #endif /* CONFIG_TCG */ 4597d8b28b8SRichard Henderson 460200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) 461200bf5b7SAbdallah Bouassida { 462200bf5b7SAbdallah Bouassida ARMCPU *cpu = ARM_CPU(cs); 463200bf5b7SAbdallah Bouassida 464200bf5b7SAbdallah Bouassida if (strcmp(xmlname, "system-registers.xml") == 0) { 465448d4d14SAlex Bennée return cpu->dyn_sysreg_xml.desc; 466d12379c5SAlex Bennée } else if (strcmp(xmlname, "sve-registers.xml") == 0) { 467d12379c5SAlex Bennée return cpu->dyn_svereg_xml.desc; 4687d8b28b8SRichard Henderson } else if (strcmp(xmlname, "arm-m-system.xml") == 0) { 4697d8b28b8SRichard Henderson return cpu->dyn_m_systemreg_xml.desc; 4707d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY 4717d8b28b8SRichard Henderson } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) { 4727d8b28b8SRichard Henderson return cpu->dyn_m_secextreg_xml.desc; 4737d8b28b8SRichard Henderson #endif 474200bf5b7SAbdallah Bouassida } 475200bf5b7SAbdallah Bouassida return NULL; 476200bf5b7SAbdallah Bouassida } 47789f4f20eSPeter Maydell 47889f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) 47989f4f20eSPeter Maydell { 48089f4f20eSPeter Maydell CPUState *cs = CPU(cpu); 48189f4f20eSPeter Maydell CPUARMState *env = &cpu->env; 48289f4f20eSPeter Maydell 48389f4f20eSPeter Maydell if (arm_feature(env, ARM_FEATURE_AARCH64)) { 48489f4f20eSPeter Maydell /* 48589f4f20eSPeter Maydell * The lower part of each SVE register aliases to the FPU 48689f4f20eSPeter Maydell * registers so we don't need to include both. 48789f4f20eSPeter Maydell */ 48889f4f20eSPeter Maydell #ifdef TARGET_AARCH64 48989f4f20eSPeter Maydell if (isar_feature_aa64_sve(&cpu->isar)) { 490963a6b91SRichard Henderson int nreg = arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs); 491963a6b91SRichard Henderson gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg, 492963a6b91SRichard Henderson aarch64_gdb_set_sve_reg, nreg, 49389f4f20eSPeter Maydell "sve-registers.xml", 0); 49489f4f20eSPeter Maydell } else { 495963a6b91SRichard Henderson gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg, 496963a6b91SRichard Henderson aarch64_gdb_set_fpu_reg, 49789f4f20eSPeter Maydell 34, "aarch64-fpu.xml", 0); 49889f4f20eSPeter Maydell } 4995787d17aSPeter Maydell /* 5007bdd67a5SPeter Maydell * Note that we report pauth information via the feature name 5017bdd67a5SPeter Maydell * org.gnu.gdb.aarch64.pauth_v2, not org.gnu.gdb.aarch64.pauth. 5027bdd67a5SPeter Maydell * GDB versions 9 through 12 have a bug where they will crash 5037bdd67a5SPeter Maydell * if they see the latter XML from QEMU. 5045787d17aSPeter Maydell */ 505e995d5ccSRichard Henderson if (isar_feature_aa64_pauth(&cpu->isar)) { 506e995d5ccSRichard Henderson gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg, 507e995d5ccSRichard Henderson aarch64_gdb_set_pauth_reg, 508e995d5ccSRichard Henderson 4, "aarch64-pauth.xml", 0); 509e995d5ccSRichard Henderson } 51089f4f20eSPeter Maydell #endif 511b355f08aSPeter Maydell } else { 512b355f08aSPeter Maydell if (arm_feature(env, ARM_FEATURE_NEON)) { 51389f4f20eSPeter Maydell gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, 514b355f08aSPeter Maydell 49, "arm-neon.xml", 0); 51589f4f20eSPeter Maydell } else if (cpu_isar_feature(aa32_simd_r32, cpu)) { 51689f4f20eSPeter Maydell gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, 517b355f08aSPeter Maydell 33, "arm-vfp3.xml", 0); 51889f4f20eSPeter Maydell } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) { 51989f4f20eSPeter Maydell gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, 520b355f08aSPeter Maydell 17, "arm-vfp.xml", 0); 521b355f08aSPeter Maydell } 522b355f08aSPeter Maydell if (!arm_feature(env, ARM_FEATURE_M)) { 523b355f08aSPeter Maydell /* 524b355f08aSPeter Maydell * A and R profile have FP sysregs FPEXC and FPSID that we 525b355f08aSPeter Maydell * expose to gdb. 526b355f08aSPeter Maydell */ 527b355f08aSPeter Maydell gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg, 528b355f08aSPeter Maydell 2, "arm-vfp-sysregs.xml", 0); 529b355f08aSPeter Maydell } 53089f4f20eSPeter Maydell } 53146e3b237SPhilippe Mathieu-Daudé if (cpu_isar_feature(aa32_mve, cpu) && tcg_enabled()) { 532dbd9e084SPeter Maydell gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg, 533dbd9e084SPeter Maydell 1, "arm-m-profile-mve.xml", 0); 534dbd9e084SPeter Maydell } 53589f4f20eSPeter Maydell gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg, 53689f4f20eSPeter Maydell arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs), 53789f4f20eSPeter Maydell "system-registers.xml", 0); 53889f4f20eSPeter Maydell 539893ca916SFabiano Rosas #ifdef CONFIG_TCG 54046e3b237SPhilippe Mathieu-Daudé if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) { 5417d8b28b8SRichard Henderson gdb_register_coprocessor(cs, 5427d8b28b8SRichard Henderson arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg, 5437d8b28b8SRichard Henderson arm_gen_dynamic_m_systemreg_xml(cs, cs->gdb_num_regs), 5447d8b28b8SRichard Henderson "arm-m-system.xml", 0); 5457d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY 5467d8b28b8SRichard Henderson if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { 5477d8b28b8SRichard Henderson gdb_register_coprocessor(cs, 5487d8b28b8SRichard Henderson arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg, 5497d8b28b8SRichard Henderson arm_gen_dynamic_m_secextreg_xml(cs, cs->gdb_num_regs), 5507d8b28b8SRichard Henderson "arm-m-secext.xml", 0); 5517d8b28b8SRichard Henderson } 5527d8b28b8SRichard Henderson #endif 5537d8b28b8SRichard Henderson } 554893ca916SFabiano Rosas #endif /* CONFIG_TCG */ 55589f4f20eSPeter Maydell } 556