xref: /openbmc/qemu/target/arm/gdbstub.c (revision dd2f7e2974b1cefe00cb5077ae58134ef973070d)
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"
26cf7c6d10SRichard Henderson #include "cpregs.h"
27fcf5ef2aSThomas Huth 
28200bf5b7SAbdallah Bouassida typedef struct RegisterSysregXmlParam {
29200bf5b7SAbdallah Bouassida     CPUState *cs;
30200bf5b7SAbdallah Bouassida     GString *s;
3132d6e32aSAlex Bennée     int n;
32200bf5b7SAbdallah Bouassida } RegisterSysregXmlParam;
33200bf5b7SAbdallah Bouassida 
34fcf5ef2aSThomas Huth /* Old gdb always expect FPA registers.  Newer (xml-aware) gdb only expect
35fcf5ef2aSThomas Huth    whatever the target description contains.  Due to a historical mishap
36fcf5ef2aSThomas Huth    the FPA registers appear in between core integer regs and the CPSR.
37fcf5ef2aSThomas Huth    We hack round this by giving the FPA regs zero size when talking to a
38fcf5ef2aSThomas Huth    newer gdb.  */
39fcf5ef2aSThomas Huth 
40a010bdbeSAlex Bennée int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
41fcf5ef2aSThomas Huth {
42fcf5ef2aSThomas Huth     ARMCPU *cpu = ARM_CPU(cs);
43fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
44fcf5ef2aSThomas Huth 
45fcf5ef2aSThomas Huth     if (n < 16) {
46fcf5ef2aSThomas Huth         /* Core integer register.  */
47fcf5ef2aSThomas Huth         return gdb_get_reg32(mem_buf, env->regs[n]);
48fcf5ef2aSThomas Huth     }
49*dd2f7e29SAkihiko Odaki     if (n == 25) {
50c888f7e0SPeter Maydell         /* CPSR, or XPSR for M-profile */
51c888f7e0SPeter Maydell         if (arm_feature(env, ARM_FEATURE_M)) {
52c888f7e0SPeter Maydell             return gdb_get_reg32(mem_buf, xpsr_read(env));
53c888f7e0SPeter Maydell         } else {
54fcf5ef2aSThomas Huth             return gdb_get_reg32(mem_buf, cpsr_read(env));
55fcf5ef2aSThomas Huth         }
56c888f7e0SPeter Maydell     }
57fcf5ef2aSThomas Huth     /* Unknown register.  */
58fcf5ef2aSThomas Huth     return 0;
59fcf5ef2aSThomas Huth }
60fcf5ef2aSThomas Huth 
61fcf5ef2aSThomas Huth int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
62fcf5ef2aSThomas Huth {
63fcf5ef2aSThomas Huth     ARMCPU *cpu = ARM_CPU(cs);
64fcf5ef2aSThomas Huth     CPUARMState *env = &cpu->env;
65fcf5ef2aSThomas Huth     uint32_t tmp;
66fcf5ef2aSThomas Huth 
67fcf5ef2aSThomas Huth     tmp = ldl_p(mem_buf);
68fcf5ef2aSThomas Huth 
697055fe4bSRichard Henderson     /*
707055fe4bSRichard Henderson      * Mask out low bits of PC to workaround gdb bugs.
717055fe4bSRichard Henderson      * This avoids an assert in thumb_tr_translate_insn, because it is
727055fe4bSRichard Henderson      * architecturally impossible to misalign the pc.
737055fe4bSRichard Henderson      * This will probably cause problems if we ever implement the
747055fe4bSRichard Henderson      * Jazelle DBX extensions.
757055fe4bSRichard Henderson      */
76fcf5ef2aSThomas Huth     if (n == 15) {
77fcf5ef2aSThomas Huth         tmp &= ~1;
78fcf5ef2aSThomas Huth     }
79fcf5ef2aSThomas Huth 
80fcf5ef2aSThomas Huth     if (n < 16) {
81fcf5ef2aSThomas Huth         /* Core integer register.  */
82888f470fSPeter Maydell         if (n == 13 && arm_feature(env, ARM_FEATURE_M)) {
83888f470fSPeter Maydell             /* M profile SP low bits are always 0 */
84888f470fSPeter Maydell             tmp &= ~3;
85888f470fSPeter Maydell         }
86fcf5ef2aSThomas Huth         env->regs[n] = tmp;
87fcf5ef2aSThomas Huth         return 4;
88fcf5ef2aSThomas Huth     }
89*dd2f7e29SAkihiko Odaki     if (n == 25) {
90c888f7e0SPeter Maydell         /* CPSR, or XPSR for M-profile */
91c888f7e0SPeter Maydell         if (arm_feature(env, ARM_FEATURE_M)) {
92c888f7e0SPeter Maydell             /*
93c888f7e0SPeter Maydell              * Don't allow writing to XPSR.Exception as it can cause
94c888f7e0SPeter Maydell              * a transition into or out of handler mode (it's not
959323e79fSPeter Maydell              * writable via the MSR insn so this is a reasonable
96c888f7e0SPeter Maydell              * restriction). Other fields are safe to update.
97c888f7e0SPeter Maydell              */
98c888f7e0SPeter Maydell             xpsr_write(env, tmp, ~XPSR_EXCP);
99c888f7e0SPeter Maydell         } else {
100fcf5ef2aSThomas Huth             cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
101c888f7e0SPeter Maydell         }
102fcf5ef2aSThomas Huth         return 4;
103fcf5ef2aSThomas Huth     }
104fcf5ef2aSThomas Huth     /* Unknown register.  */
105fcf5ef2aSThomas Huth     return 0;
106fcf5ef2aSThomas Huth }
107200bf5b7SAbdallah Bouassida 
10889f4f20eSPeter Maydell static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
10989f4f20eSPeter Maydell {
11089f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
11189f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
11289f4f20eSPeter Maydell 
11389f4f20eSPeter Maydell     /* VFP data registers are always little-endian.  */
11489f4f20eSPeter Maydell     if (reg < nregs) {
11589f4f20eSPeter Maydell         return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
11689f4f20eSPeter Maydell     }
11789f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
11889f4f20eSPeter Maydell         /* Aliases for Q regs.  */
11989f4f20eSPeter Maydell         nregs += 16;
12089f4f20eSPeter Maydell         if (reg < nregs) {
12189f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
12289f4f20eSPeter Maydell             return gdb_get_reg128(buf, q[0], q[1]);
12389f4f20eSPeter Maydell         }
12489f4f20eSPeter Maydell     }
12589f4f20eSPeter Maydell     switch (reg - nregs) {
12689f4f20eSPeter Maydell     case 0:
12789f4f20eSPeter Maydell         return gdb_get_reg32(buf, vfp_get_fpscr(env));
12889f4f20eSPeter Maydell     }
12989f4f20eSPeter Maydell     return 0;
13089f4f20eSPeter Maydell }
13189f4f20eSPeter Maydell 
13289f4f20eSPeter Maydell static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
13389f4f20eSPeter Maydell {
13489f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
13589f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
13689f4f20eSPeter Maydell 
13789f4f20eSPeter Maydell     if (reg < nregs) {
13889f4f20eSPeter Maydell         *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
13989f4f20eSPeter Maydell         return 8;
14089f4f20eSPeter Maydell     }
14189f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
14289f4f20eSPeter Maydell         nregs += 16;
14389f4f20eSPeter Maydell         if (reg < nregs) {
14489f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
14589f4f20eSPeter Maydell             q[0] = ldq_le_p(buf);
14689f4f20eSPeter Maydell             q[1] = ldq_le_p(buf + 8);
14789f4f20eSPeter Maydell             return 16;
14889f4f20eSPeter Maydell         }
14989f4f20eSPeter Maydell     }
15089f4f20eSPeter Maydell     switch (reg - nregs) {
15189f4f20eSPeter Maydell     case 0:
152b355f08aSPeter Maydell         vfp_set_fpscr(env, ldl_p(buf));
153b355f08aSPeter Maydell         return 4;
154b355f08aSPeter Maydell     }
155b355f08aSPeter Maydell     return 0;
156b355f08aSPeter Maydell }
157b355f08aSPeter Maydell 
158b355f08aSPeter Maydell static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
159b355f08aSPeter Maydell {
160b355f08aSPeter Maydell     switch (reg) {
161b355f08aSPeter Maydell     case 0:
162b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
163b355f08aSPeter Maydell     case 1:
164b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
165b355f08aSPeter Maydell     }
166b355f08aSPeter Maydell     return 0;
167b355f08aSPeter Maydell }
168b355f08aSPeter Maydell 
169b355f08aSPeter Maydell static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
170b355f08aSPeter Maydell {
171b355f08aSPeter Maydell     switch (reg) {
172b355f08aSPeter Maydell     case 0:
17389f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
17489f4f20eSPeter Maydell         return 4;
17589f4f20eSPeter Maydell     case 1:
17689f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
17789f4f20eSPeter Maydell         return 4;
17889f4f20eSPeter Maydell     }
17989f4f20eSPeter Maydell     return 0;
18089f4f20eSPeter Maydell }
18189f4f20eSPeter Maydell 
182dbd9e084SPeter Maydell static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
183dbd9e084SPeter Maydell {
184dbd9e084SPeter Maydell     switch (reg) {
185dbd9e084SPeter Maydell     case 0:
186dbd9e084SPeter Maydell         return gdb_get_reg32(buf, env->v7m.vpr);
187dbd9e084SPeter Maydell     default:
188dbd9e084SPeter Maydell         return 0;
189dbd9e084SPeter Maydell     }
190dbd9e084SPeter Maydell }
191dbd9e084SPeter Maydell 
192dbd9e084SPeter Maydell static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
193dbd9e084SPeter Maydell {
194dbd9e084SPeter Maydell     switch (reg) {
195dbd9e084SPeter Maydell     case 0:
196dbd9e084SPeter Maydell         env->v7m.vpr = ldl_p(buf);
197dbd9e084SPeter Maydell         return 4;
198dbd9e084SPeter Maydell     default:
199dbd9e084SPeter Maydell         return 0;
200dbd9e084SPeter Maydell     }
201dbd9e084SPeter Maydell }
202dbd9e084SPeter Maydell 
20389f4f20eSPeter Maydell /**
20489f4f20eSPeter Maydell  * arm_get/set_gdb_*: get/set a gdb register
20589f4f20eSPeter Maydell  * @env: the CPU state
20689f4f20eSPeter Maydell  * @buf: a buffer to copy to/from
20789f4f20eSPeter Maydell  * @reg: register number (offset from start of group)
20889f4f20eSPeter Maydell  *
20989f4f20eSPeter Maydell  * We return the number of bytes copied
21089f4f20eSPeter Maydell  */
21189f4f20eSPeter Maydell 
21289f4f20eSPeter Maydell static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg)
21389f4f20eSPeter Maydell {
21489f4f20eSPeter Maydell     ARMCPU *cpu = env_archcpu(env);
21589f4f20eSPeter Maydell     const ARMCPRegInfo *ri;
21689f4f20eSPeter Maydell     uint32_t key;
21789f4f20eSPeter Maydell 
21889f4f20eSPeter Maydell     key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg];
21989f4f20eSPeter Maydell     ri = get_arm_cp_reginfo(cpu->cp_regs, key);
22089f4f20eSPeter Maydell     if (ri) {
22189f4f20eSPeter Maydell         if (cpreg_field_is_64bit(ri)) {
22289f4f20eSPeter Maydell             return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
22389f4f20eSPeter Maydell         } else {
22489f4f20eSPeter Maydell             return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
22589f4f20eSPeter Maydell         }
22689f4f20eSPeter Maydell     }
22789f4f20eSPeter Maydell     return 0;
22889f4f20eSPeter Maydell }
22989f4f20eSPeter Maydell 
23089f4f20eSPeter Maydell static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
23189f4f20eSPeter Maydell {
23289f4f20eSPeter Maydell     return 0;
23389f4f20eSPeter Maydell }
23489f4f20eSPeter Maydell 
235448d4d14SAlex Bennée static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml,
236200bf5b7SAbdallah Bouassida                                        ARMCPRegInfo *ri, uint32_t ri_key,
23732d6e32aSAlex Bennée                                        int bitsize, int regnum)
238200bf5b7SAbdallah Bouassida {
239200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<reg name=\"%s\"", ri->name);
240200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " bitsize=\"%d\"", bitsize);
24132d6e32aSAlex Bennée     g_string_append_printf(s, " regnum=\"%d\"", regnum);
242200bf5b7SAbdallah Bouassida     g_string_append_printf(s, " group=\"cp_regs\"/>");
243448d4d14SAlex Bennée     dyn_xml->data.cpregs.keys[dyn_xml->num] = ri_key;
244448d4d14SAlex Bennée     dyn_xml->num++;
245200bf5b7SAbdallah Bouassida }
246200bf5b7SAbdallah Bouassida 
247200bf5b7SAbdallah Bouassida static void arm_register_sysreg_for_xml(gpointer key, gpointer value,
248200bf5b7SAbdallah Bouassida                                         gpointer p)
249200bf5b7SAbdallah Bouassida {
2505860362dSRichard Henderson     uint32_t ri_key = (uintptr_t)key;
251200bf5b7SAbdallah Bouassida     ARMCPRegInfo *ri = value;
252200bf5b7SAbdallah Bouassida     RegisterSysregXmlParam *param = (RegisterSysregXmlParam *)p;
253200bf5b7SAbdallah Bouassida     GString *s = param->s;
254200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(param->cs);
255200bf5b7SAbdallah Bouassida     CPUARMState *env = &cpu->env;
256448d4d14SAlex Bennée     DynamicGDBXMLInfo *dyn_xml = &cpu->dyn_sysreg_xml;
257200bf5b7SAbdallah Bouassida 
258200bf5b7SAbdallah Bouassida     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
259200bf5b7SAbdallah Bouassida         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
260200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA64) {
26132d6e32aSAlex Bennée                 arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
26232d6e32aSAlex Bennée                                            param->n++);
263200bf5b7SAbdallah Bouassida             }
264200bf5b7SAbdallah Bouassida         } else {
265200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA32) {
266200bf5b7SAbdallah Bouassida                 if (!arm_feature(env, ARM_FEATURE_EL3) &&
267200bf5b7SAbdallah Bouassida                     (ri->secure & ARM_CP_SECSTATE_S)) {
268200bf5b7SAbdallah Bouassida                     return;
269200bf5b7SAbdallah Bouassida                 }
270200bf5b7SAbdallah Bouassida                 if (ri->type & ARM_CP_64BIT) {
27132d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 64,
27232d6e32aSAlex Bennée                                                param->n++);
273200bf5b7SAbdallah Bouassida                 } else {
27432d6e32aSAlex Bennée                     arm_gen_one_xml_sysreg_tag(s , dyn_xml, ri, ri_key, 32,
27532d6e32aSAlex Bennée                                                param->n++);
276200bf5b7SAbdallah Bouassida                 }
277200bf5b7SAbdallah Bouassida             }
278200bf5b7SAbdallah Bouassida         }
279200bf5b7SAbdallah Bouassida     }
280200bf5b7SAbdallah Bouassida }
281200bf5b7SAbdallah Bouassida 
2824bce95b4SRichard Henderson static int arm_gen_dynamic_sysreg_xml(CPUState *cs, int base_reg)
283200bf5b7SAbdallah Bouassida {
284200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
285200bf5b7SAbdallah Bouassida     GString *s = g_string_new(NULL);
28632d6e32aSAlex Bennée     RegisterSysregXmlParam param = {cs, s, base_reg};
287200bf5b7SAbdallah Bouassida 
288448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.num = 0;
289448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.data.cpregs.keys = g_new(uint32_t, g_hash_table_size(cpu->cp_regs));
290200bf5b7SAbdallah Bouassida     g_string_printf(s, "<?xml version=\"1.0\"?>");
291200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
292200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "<feature name=\"org.qemu.gdb.arm.sys.regs\">");
293200bf5b7SAbdallah Bouassida     g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_xml, &param);
294200bf5b7SAbdallah Bouassida     g_string_append_printf(s, "</feature>");
295448d4d14SAlex Bennée     cpu->dyn_sysreg_xml.desc = g_string_free(s, false);
296448d4d14SAlex Bennée     return cpu->dyn_sysreg_xml.num;
297200bf5b7SAbdallah Bouassida }
298200bf5b7SAbdallah Bouassida 
299893ca916SFabiano Rosas #ifdef CONFIG_TCG
3007d8b28b8SRichard Henderson typedef enum {
3017d8b28b8SRichard Henderson     M_SYSREG_MSP,
3027d8b28b8SRichard Henderson     M_SYSREG_PSP,
3037d8b28b8SRichard Henderson     M_SYSREG_PRIMASK,
3047d8b28b8SRichard Henderson     M_SYSREG_CONTROL,
3057d8b28b8SRichard Henderson     M_SYSREG_BASEPRI,
3067d8b28b8SRichard Henderson     M_SYSREG_FAULTMASK,
3077d8b28b8SRichard Henderson     M_SYSREG_MSPLIM,
3087d8b28b8SRichard Henderson     M_SYSREG_PSPLIM,
3097d8b28b8SRichard Henderson } MProfileSysreg;
3107d8b28b8SRichard Henderson 
3117d8b28b8SRichard Henderson static const struct {
3127d8b28b8SRichard Henderson     const char *name;
3137d8b28b8SRichard Henderson     int feature;
3147d8b28b8SRichard Henderson } m_sysreg_def[] = {
3157d8b28b8SRichard Henderson     [M_SYSREG_MSP] = { "msp", ARM_FEATURE_M },
3167d8b28b8SRichard Henderson     [M_SYSREG_PSP] = { "psp", ARM_FEATURE_M },
3177d8b28b8SRichard Henderson     [M_SYSREG_PRIMASK] = { "primask", ARM_FEATURE_M },
3187d8b28b8SRichard Henderson     [M_SYSREG_CONTROL] = { "control", ARM_FEATURE_M },
3197d8b28b8SRichard Henderson     [M_SYSREG_BASEPRI] = { "basepri", ARM_FEATURE_M_MAIN },
3207d8b28b8SRichard Henderson     [M_SYSREG_FAULTMASK] = { "faultmask", ARM_FEATURE_M_MAIN },
3217d8b28b8SRichard Henderson     [M_SYSREG_MSPLIM] = { "msplim", ARM_FEATURE_V8 },
3227d8b28b8SRichard Henderson     [M_SYSREG_PSPLIM] = { "psplim", ARM_FEATURE_V8 },
3237d8b28b8SRichard Henderson };
3247d8b28b8SRichard Henderson 
3257d8b28b8SRichard Henderson static uint32_t *m_sysreg_ptr(CPUARMState *env, MProfileSysreg reg, bool sec)
3267d8b28b8SRichard Henderson {
3277d8b28b8SRichard Henderson     uint32_t *ptr;
3287d8b28b8SRichard Henderson 
3297d8b28b8SRichard Henderson     switch (reg) {
3307d8b28b8SRichard Henderson     case M_SYSREG_MSP:
3317d8b28b8SRichard Henderson         ptr = arm_v7m_get_sp_ptr(env, sec, false, true);
3327d8b28b8SRichard Henderson         break;
3337d8b28b8SRichard Henderson     case M_SYSREG_PSP:
3347d8b28b8SRichard Henderson         ptr = arm_v7m_get_sp_ptr(env, sec, true, true);
3357d8b28b8SRichard Henderson         break;
3367d8b28b8SRichard Henderson     case M_SYSREG_MSPLIM:
3377d8b28b8SRichard Henderson         ptr = &env->v7m.msplim[sec];
3387d8b28b8SRichard Henderson         break;
3397d8b28b8SRichard Henderson     case M_SYSREG_PSPLIM:
3407d8b28b8SRichard Henderson         ptr = &env->v7m.psplim[sec];
3417d8b28b8SRichard Henderson         break;
3427d8b28b8SRichard Henderson     case M_SYSREG_PRIMASK:
3437d8b28b8SRichard Henderson         ptr = &env->v7m.primask[sec];
3447d8b28b8SRichard Henderson         break;
3457d8b28b8SRichard Henderson     case M_SYSREG_BASEPRI:
3467d8b28b8SRichard Henderson         ptr = &env->v7m.basepri[sec];
3477d8b28b8SRichard Henderson         break;
3487d8b28b8SRichard Henderson     case M_SYSREG_FAULTMASK:
3497d8b28b8SRichard Henderson         ptr = &env->v7m.faultmask[sec];
3507d8b28b8SRichard Henderson         break;
3517d8b28b8SRichard Henderson     case M_SYSREG_CONTROL:
3527d8b28b8SRichard Henderson         ptr = &env->v7m.control[sec];
3537d8b28b8SRichard Henderson         break;
3547d8b28b8SRichard Henderson     default:
3557d8b28b8SRichard Henderson         return NULL;
3567d8b28b8SRichard Henderson     }
3577d8b28b8SRichard Henderson     return arm_feature(env, m_sysreg_def[reg].feature) ? ptr : NULL;
3587d8b28b8SRichard Henderson }
3597d8b28b8SRichard Henderson 
3607d8b28b8SRichard Henderson static int m_sysreg_get(CPUARMState *env, GByteArray *buf,
3617d8b28b8SRichard Henderson                         MProfileSysreg reg, bool secure)
3627d8b28b8SRichard Henderson {
3637d8b28b8SRichard Henderson     uint32_t *ptr = m_sysreg_ptr(env, reg, secure);
3647d8b28b8SRichard Henderson 
3657d8b28b8SRichard Henderson     if (ptr == NULL) {
3667d8b28b8SRichard Henderson         return 0;
3677d8b28b8SRichard Henderson     }
3687d8b28b8SRichard Henderson     return gdb_get_reg32(buf, *ptr);
3697d8b28b8SRichard Henderson }
3707d8b28b8SRichard Henderson 
3717d8b28b8SRichard Henderson static int arm_gdb_get_m_systemreg(CPUARMState *env, GByteArray *buf, int reg)
3727d8b28b8SRichard Henderson {
3737d8b28b8SRichard Henderson     /*
3747d8b28b8SRichard Henderson      * Here, we emulate MRS instruction, where CONTROL has a mix of
3757d8b28b8SRichard Henderson      * banked and non-banked bits.
3767d8b28b8SRichard Henderson      */
3777d8b28b8SRichard Henderson     if (reg == M_SYSREG_CONTROL) {
3787d8b28b8SRichard Henderson         return gdb_get_reg32(buf, arm_v7m_mrs_control(env, env->v7m.secure));
3797d8b28b8SRichard Henderson     }
3807d8b28b8SRichard Henderson     return m_sysreg_get(env, buf, reg, env->v7m.secure);
3817d8b28b8SRichard Henderson }
3827d8b28b8SRichard Henderson 
3837d8b28b8SRichard Henderson static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
3847d8b28b8SRichard Henderson {
3857d8b28b8SRichard Henderson     return 0; /* TODO */
3867d8b28b8SRichard Henderson }
3877d8b28b8SRichard Henderson 
3887d8b28b8SRichard Henderson static int arm_gen_dynamic_m_systemreg_xml(CPUState *cs, int orig_base_reg)
3897d8b28b8SRichard Henderson {
3907d8b28b8SRichard Henderson     ARMCPU *cpu = ARM_CPU(cs);
3917d8b28b8SRichard Henderson     CPUARMState *env = &cpu->env;
3927d8b28b8SRichard Henderson     GString *s = g_string_new(NULL);
3937d8b28b8SRichard Henderson     int base_reg = orig_base_reg;
3947d8b28b8SRichard Henderson     int i;
3957d8b28b8SRichard Henderson 
3967d8b28b8SRichard Henderson     g_string_printf(s, "<?xml version=\"1.0\"?>");
3977d8b28b8SRichard Henderson     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
3987d8b28b8SRichard Henderson     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.m-system\">\n");
3997d8b28b8SRichard Henderson 
4007d8b28b8SRichard Henderson     for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
4017d8b28b8SRichard Henderson         if (arm_feature(env, m_sysreg_def[i].feature)) {
4027d8b28b8SRichard Henderson             g_string_append_printf(s,
4037d8b28b8SRichard Henderson                 "<reg name=\"%s\" bitsize=\"32\" regnum=\"%d\"/>\n",
4047d8b28b8SRichard Henderson                 m_sysreg_def[i].name, base_reg++);
4057d8b28b8SRichard Henderson         }
4067d8b28b8SRichard Henderson     }
4077d8b28b8SRichard Henderson 
4087d8b28b8SRichard Henderson     g_string_append_printf(s, "</feature>");
4097d8b28b8SRichard Henderson     cpu->dyn_m_systemreg_xml.desc = g_string_free(s, false);
4107d8b28b8SRichard Henderson     cpu->dyn_m_systemreg_xml.num = base_reg - orig_base_reg;
4117d8b28b8SRichard Henderson 
4127d8b28b8SRichard Henderson     return cpu->dyn_m_systemreg_xml.num;
4137d8b28b8SRichard Henderson }
4147d8b28b8SRichard Henderson 
4157d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
4167d8b28b8SRichard Henderson /*
4177d8b28b8SRichard Henderson  * For user-only, we see the non-secure registers via m_systemreg above.
4187d8b28b8SRichard Henderson  * For secext, encode the non-secure view as even and secure view as odd.
4197d8b28b8SRichard Henderson  */
4207d8b28b8SRichard Henderson static int arm_gdb_get_m_secextreg(CPUARMState *env, GByteArray *buf, int reg)
4217d8b28b8SRichard Henderson {
4227d8b28b8SRichard Henderson     return m_sysreg_get(env, buf, reg >> 1, reg & 1);
4237d8b28b8SRichard Henderson }
4247d8b28b8SRichard Henderson 
4257d8b28b8SRichard Henderson static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg)
4267d8b28b8SRichard Henderson {
4277d8b28b8SRichard Henderson     return 0; /* TODO */
4287d8b28b8SRichard Henderson }
4297d8b28b8SRichard Henderson 
4307d8b28b8SRichard Henderson static int arm_gen_dynamic_m_secextreg_xml(CPUState *cs, int orig_base_reg)
4317d8b28b8SRichard Henderson {
4327d8b28b8SRichard Henderson     ARMCPU *cpu = ARM_CPU(cs);
4337d8b28b8SRichard Henderson     GString *s = g_string_new(NULL);
4347d8b28b8SRichard Henderson     int base_reg = orig_base_reg;
4357d8b28b8SRichard Henderson     int i;
4367d8b28b8SRichard Henderson 
4377d8b28b8SRichard Henderson     g_string_printf(s, "<?xml version=\"1.0\"?>");
4387d8b28b8SRichard Henderson     g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
4397d8b28b8SRichard Henderson     g_string_append_printf(s, "<feature name=\"org.gnu.gdb.arm.secext\">\n");
4407d8b28b8SRichard Henderson 
4417d8b28b8SRichard Henderson     for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
4427d8b28b8SRichard Henderson         g_string_append_printf(s,
4437d8b28b8SRichard Henderson             "<reg name=\"%s_ns\" bitsize=\"32\" regnum=\"%d\"/>\n",
4447d8b28b8SRichard Henderson             m_sysreg_def[i].name, base_reg++);
4457d8b28b8SRichard Henderson         g_string_append_printf(s,
4467d8b28b8SRichard Henderson             "<reg name=\"%s_s\" bitsize=\"32\" regnum=\"%d\"/>\n",
4477d8b28b8SRichard Henderson             m_sysreg_def[i].name, base_reg++);
4487d8b28b8SRichard Henderson     }
4497d8b28b8SRichard Henderson 
4507d8b28b8SRichard Henderson     g_string_append_printf(s, "</feature>");
4517d8b28b8SRichard Henderson     cpu->dyn_m_secextreg_xml.desc = g_string_free(s, false);
4527d8b28b8SRichard Henderson     cpu->dyn_m_secextreg_xml.num = base_reg - orig_base_reg;
4537d8b28b8SRichard Henderson 
4547d8b28b8SRichard Henderson     return cpu->dyn_m_secextreg_xml.num;
4557d8b28b8SRichard Henderson }
4567d8b28b8SRichard Henderson #endif
457893ca916SFabiano Rosas #endif /* CONFIG_TCG */
4587d8b28b8SRichard Henderson 
459200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
460200bf5b7SAbdallah Bouassida {
461200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
462200bf5b7SAbdallah Bouassida 
463200bf5b7SAbdallah Bouassida     if (strcmp(xmlname, "system-registers.xml") == 0) {
464448d4d14SAlex Bennée         return cpu->dyn_sysreg_xml.desc;
465d12379c5SAlex Bennée     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
466d12379c5SAlex Bennée         return cpu->dyn_svereg_xml.desc;
4677d8b28b8SRichard Henderson     } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
4687d8b28b8SRichard Henderson         return cpu->dyn_m_systemreg_xml.desc;
4697d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
4707d8b28b8SRichard Henderson     } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
4717d8b28b8SRichard Henderson         return cpu->dyn_m_secextreg_xml.desc;
4727d8b28b8SRichard Henderson #endif
473200bf5b7SAbdallah Bouassida     }
474200bf5b7SAbdallah Bouassida     return NULL;
475200bf5b7SAbdallah Bouassida }
47689f4f20eSPeter Maydell 
47789f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
47889f4f20eSPeter Maydell {
47989f4f20eSPeter Maydell     CPUState *cs = CPU(cpu);
48089f4f20eSPeter Maydell     CPUARMState *env = &cpu->env;
48189f4f20eSPeter Maydell 
48289f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
48389f4f20eSPeter Maydell         /*
48489f4f20eSPeter Maydell          * The lower part of each SVE register aliases to the FPU
48589f4f20eSPeter Maydell          * registers so we don't need to include both.
48689f4f20eSPeter Maydell          */
48789f4f20eSPeter Maydell #ifdef TARGET_AARCH64
48889f4f20eSPeter Maydell         if (isar_feature_aa64_sve(&cpu->isar)) {
489963a6b91SRichard Henderson             int nreg = arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs);
490963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
491963a6b91SRichard Henderson                                      aarch64_gdb_set_sve_reg, nreg,
49289f4f20eSPeter Maydell                                      "sve-registers.xml", 0);
49389f4f20eSPeter Maydell         } else {
494963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
495963a6b91SRichard Henderson                                      aarch64_gdb_set_fpu_reg,
49689f4f20eSPeter Maydell                                      34, "aarch64-fpu.xml", 0);
49789f4f20eSPeter Maydell         }
4985787d17aSPeter Maydell         /*
4997bdd67a5SPeter Maydell          * Note that we report pauth information via the feature name
5007bdd67a5SPeter Maydell          * org.gnu.gdb.aarch64.pauth_v2, not org.gnu.gdb.aarch64.pauth.
5017bdd67a5SPeter Maydell          * GDB versions 9 through 12 have a bug where they will crash
5027bdd67a5SPeter Maydell          * if they see the latter XML from QEMU.
5035787d17aSPeter Maydell          */
504e995d5ccSRichard Henderson         if (isar_feature_aa64_pauth(&cpu->isar)) {
505e995d5ccSRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
506e995d5ccSRichard Henderson                                      aarch64_gdb_set_pauth_reg,
507e995d5ccSRichard Henderson                                      4, "aarch64-pauth.xml", 0);
508e995d5ccSRichard Henderson         }
50989f4f20eSPeter Maydell #endif
510b355f08aSPeter Maydell     } else {
511b355f08aSPeter Maydell         if (arm_feature(env, ARM_FEATURE_NEON)) {
51289f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
513b355f08aSPeter Maydell                                      49, "arm-neon.xml", 0);
51489f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
51589f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
516b355f08aSPeter Maydell                                      33, "arm-vfp3.xml", 0);
51789f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
51889f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
519b355f08aSPeter Maydell                                      17, "arm-vfp.xml", 0);
520b355f08aSPeter Maydell         }
521b355f08aSPeter Maydell         if (!arm_feature(env, ARM_FEATURE_M)) {
522b355f08aSPeter Maydell             /*
523b355f08aSPeter Maydell              * A and R profile have FP sysregs FPEXC and FPSID that we
524b355f08aSPeter Maydell              * expose to gdb.
525b355f08aSPeter Maydell              */
526b355f08aSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
527b355f08aSPeter Maydell                                      2, "arm-vfp-sysregs.xml", 0);
528b355f08aSPeter Maydell         }
52989f4f20eSPeter Maydell     }
53046e3b237SPhilippe Mathieu-Daudé     if (cpu_isar_feature(aa32_mve, cpu) && tcg_enabled()) {
531dbd9e084SPeter Maydell         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
532dbd9e084SPeter Maydell                                  1, "arm-m-profile-mve.xml", 0);
533dbd9e084SPeter Maydell     }
53489f4f20eSPeter Maydell     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
53589f4f20eSPeter Maydell                              arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
53689f4f20eSPeter Maydell                              "system-registers.xml", 0);
53789f4f20eSPeter Maydell 
538893ca916SFabiano Rosas #ifdef CONFIG_TCG
53946e3b237SPhilippe Mathieu-Daudé     if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
5407d8b28b8SRichard Henderson         gdb_register_coprocessor(cs,
5417d8b28b8SRichard Henderson             arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
5427d8b28b8SRichard Henderson             arm_gen_dynamic_m_systemreg_xml(cs, cs->gdb_num_regs),
5437d8b28b8SRichard Henderson             "arm-m-system.xml", 0);
5447d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
5457d8b28b8SRichard Henderson         if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
5467d8b28b8SRichard Henderson             gdb_register_coprocessor(cs,
5477d8b28b8SRichard Henderson                 arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
5487d8b28b8SRichard Henderson                 arm_gen_dynamic_m_secextreg_xml(cs, cs->gdb_num_regs),
5497d8b28b8SRichard Henderson                 "arm-m-secext.xml", 0);
5507d8b28b8SRichard Henderson         }
5517d8b28b8SRichard Henderson #endif
5527d8b28b8SRichard Henderson     }
553893ca916SFabiano Rosas #endif /* CONFIG_TCG */
55489f4f20eSPeter Maydell }
555