xref: /openbmc/qemu/target/arm/gdbstub.c (revision 690bd97b5b18b9198300e09a55ff980ab57ba665)
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"
265a534314SPeter Maydell #include "cpu-features.h"
27cf7c6d10SRichard Henderson #include "cpregs.h"
28fcf5ef2aSThomas Huth 
29*690bd97bSAkihiko Odaki typedef struct RegisterSysregFeatureParam {
30200bf5b7SAbdallah Bouassida     CPUState *cs;
31*690bd97bSAkihiko Odaki     GDBFeatureBuilder builder;
3232d6e32aSAlex Bennée     int n;
33*690bd97bSAkihiko Odaki } RegisterSysregFeatureParam;
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 
219*690bd97bSAkihiko Odaki     key = cpu->dyn_sysreg_feature.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 
236*690bd97bSAkihiko Odaki static void arm_gen_one_feature_sysreg(GDBFeatureBuilder *builder,
237*690bd97bSAkihiko Odaki                                        DynamicGDBFeatureInfo *dyn_feature,
238200bf5b7SAbdallah Bouassida                                        ARMCPRegInfo *ri, uint32_t ri_key,
239*690bd97bSAkihiko Odaki                                        int bitsize, int n)
240200bf5b7SAbdallah Bouassida {
241*690bd97bSAkihiko Odaki     gdb_feature_builder_append_reg(builder, ri->name, bitsize, n,
242*690bd97bSAkihiko Odaki                                    "int", "cp_regs");
243*690bd97bSAkihiko Odaki 
244*690bd97bSAkihiko Odaki     dyn_feature->data.cpregs.keys[n] = ri_key;
245200bf5b7SAbdallah Bouassida }
246200bf5b7SAbdallah Bouassida 
247*690bd97bSAkihiko Odaki static void arm_register_sysreg_for_feature(gpointer key, gpointer value,
248200bf5b7SAbdallah Bouassida                                             gpointer p)
249200bf5b7SAbdallah Bouassida {
2505860362dSRichard Henderson     uint32_t ri_key = (uintptr_t)key;
251200bf5b7SAbdallah Bouassida     ARMCPRegInfo *ri = value;
252*690bd97bSAkihiko Odaki     RegisterSysregFeatureParam *param = p;
253200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(param->cs);
254200bf5b7SAbdallah Bouassida     CPUARMState *env = &cpu->env;
255*690bd97bSAkihiko Odaki     DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
256200bf5b7SAbdallah Bouassida 
257200bf5b7SAbdallah Bouassida     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
258200bf5b7SAbdallah Bouassida         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
259200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA64) {
260*690bd97bSAkihiko Odaki                 arm_gen_one_feature_sysreg(&param->builder, dyn_feature,
261*690bd97bSAkihiko Odaki                                            ri, ri_key, 64, param->n++);
262200bf5b7SAbdallah Bouassida             }
263200bf5b7SAbdallah Bouassida         } else {
264200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA32) {
265200bf5b7SAbdallah Bouassida                 if (!arm_feature(env, ARM_FEATURE_EL3) &&
266200bf5b7SAbdallah Bouassida                     (ri->secure & ARM_CP_SECSTATE_S)) {
267200bf5b7SAbdallah Bouassida                     return;
268200bf5b7SAbdallah Bouassida                 }
269200bf5b7SAbdallah Bouassida                 if (ri->type & ARM_CP_64BIT) {
270*690bd97bSAkihiko Odaki                     arm_gen_one_feature_sysreg(&param->builder, dyn_feature,
271*690bd97bSAkihiko Odaki                                                ri, ri_key, 64, param->n++);
272200bf5b7SAbdallah Bouassida                 } else {
273*690bd97bSAkihiko Odaki                     arm_gen_one_feature_sysreg(&param->builder, dyn_feature,
274*690bd97bSAkihiko Odaki                                                ri, ri_key, 32, param->n++);
275200bf5b7SAbdallah Bouassida                 }
276200bf5b7SAbdallah Bouassida             }
277200bf5b7SAbdallah Bouassida         }
278200bf5b7SAbdallah Bouassida     }
279200bf5b7SAbdallah Bouassida }
280200bf5b7SAbdallah Bouassida 
281*690bd97bSAkihiko Odaki static GDBFeature *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
282200bf5b7SAbdallah Bouassida {
283200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
284*690bd97bSAkihiko Odaki     RegisterSysregFeatureParam param = {cs};
285*690bd97bSAkihiko Odaki     gsize num_regs = g_hash_table_size(cpu->cp_regs);
286200bf5b7SAbdallah Bouassida 
287*690bd97bSAkihiko Odaki     gdb_feature_builder_init(&param.builder,
288*690bd97bSAkihiko Odaki                              &cpu->dyn_sysreg_feature.desc,
289*690bd97bSAkihiko Odaki                              "org.qemu.gdb.arm.sys.regs",
290*690bd97bSAkihiko Odaki                              "system-registers.xml",
291*690bd97bSAkihiko Odaki                              base_reg);
292*690bd97bSAkihiko Odaki     cpu->dyn_sysreg_feature.data.cpregs.keys = g_new(uint32_t, num_regs);
293*690bd97bSAkihiko Odaki     g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_feature, &param);
294*690bd97bSAkihiko Odaki     gdb_feature_builder_end(&param.builder);
295*690bd97bSAkihiko Odaki     return &cpu->dyn_sysreg_feature.desc;
296200bf5b7SAbdallah Bouassida }
297200bf5b7SAbdallah Bouassida 
298893ca916SFabiano Rosas #ifdef CONFIG_TCG
2997d8b28b8SRichard Henderson typedef enum {
3007d8b28b8SRichard Henderson     M_SYSREG_MSP,
3017d8b28b8SRichard Henderson     M_SYSREG_PSP,
3027d8b28b8SRichard Henderson     M_SYSREG_PRIMASK,
3037d8b28b8SRichard Henderson     M_SYSREG_CONTROL,
3047d8b28b8SRichard Henderson     M_SYSREG_BASEPRI,
3057d8b28b8SRichard Henderson     M_SYSREG_FAULTMASK,
3067d8b28b8SRichard Henderson     M_SYSREG_MSPLIM,
3077d8b28b8SRichard Henderson     M_SYSREG_PSPLIM,
3087d8b28b8SRichard Henderson } MProfileSysreg;
3097d8b28b8SRichard Henderson 
3107d8b28b8SRichard Henderson static const struct {
3117d8b28b8SRichard Henderson     const char *name;
3127d8b28b8SRichard Henderson     int feature;
3137d8b28b8SRichard Henderson } m_sysreg_def[] = {
3147d8b28b8SRichard Henderson     [M_SYSREG_MSP] = { "msp", ARM_FEATURE_M },
3157d8b28b8SRichard Henderson     [M_SYSREG_PSP] = { "psp", ARM_FEATURE_M },
3167d8b28b8SRichard Henderson     [M_SYSREG_PRIMASK] = { "primask", ARM_FEATURE_M },
3177d8b28b8SRichard Henderson     [M_SYSREG_CONTROL] = { "control", ARM_FEATURE_M },
3187d8b28b8SRichard Henderson     [M_SYSREG_BASEPRI] = { "basepri", ARM_FEATURE_M_MAIN },
3197d8b28b8SRichard Henderson     [M_SYSREG_FAULTMASK] = { "faultmask", ARM_FEATURE_M_MAIN },
3207d8b28b8SRichard Henderson     [M_SYSREG_MSPLIM] = { "msplim", ARM_FEATURE_V8 },
3217d8b28b8SRichard Henderson     [M_SYSREG_PSPLIM] = { "psplim", ARM_FEATURE_V8 },
3227d8b28b8SRichard Henderson };
3237d8b28b8SRichard Henderson 
3247d8b28b8SRichard Henderson static uint32_t *m_sysreg_ptr(CPUARMState *env, MProfileSysreg reg, bool sec)
3257d8b28b8SRichard Henderson {
3267d8b28b8SRichard Henderson     uint32_t *ptr;
3277d8b28b8SRichard Henderson 
3287d8b28b8SRichard Henderson     switch (reg) {
3297d8b28b8SRichard Henderson     case M_SYSREG_MSP:
3307d8b28b8SRichard Henderson         ptr = arm_v7m_get_sp_ptr(env, sec, false, true);
3317d8b28b8SRichard Henderson         break;
3327d8b28b8SRichard Henderson     case M_SYSREG_PSP:
3337d8b28b8SRichard Henderson         ptr = arm_v7m_get_sp_ptr(env, sec, true, true);
3347d8b28b8SRichard Henderson         break;
3357d8b28b8SRichard Henderson     case M_SYSREG_MSPLIM:
3367d8b28b8SRichard Henderson         ptr = &env->v7m.msplim[sec];
3377d8b28b8SRichard Henderson         break;
3387d8b28b8SRichard Henderson     case M_SYSREG_PSPLIM:
3397d8b28b8SRichard Henderson         ptr = &env->v7m.psplim[sec];
3407d8b28b8SRichard Henderson         break;
3417d8b28b8SRichard Henderson     case M_SYSREG_PRIMASK:
3427d8b28b8SRichard Henderson         ptr = &env->v7m.primask[sec];
3437d8b28b8SRichard Henderson         break;
3447d8b28b8SRichard Henderson     case M_SYSREG_BASEPRI:
3457d8b28b8SRichard Henderson         ptr = &env->v7m.basepri[sec];
3467d8b28b8SRichard Henderson         break;
3477d8b28b8SRichard Henderson     case M_SYSREG_FAULTMASK:
3487d8b28b8SRichard Henderson         ptr = &env->v7m.faultmask[sec];
3497d8b28b8SRichard Henderson         break;
3507d8b28b8SRichard Henderson     case M_SYSREG_CONTROL:
3517d8b28b8SRichard Henderson         ptr = &env->v7m.control[sec];
3527d8b28b8SRichard Henderson         break;
3537d8b28b8SRichard Henderson     default:
3547d8b28b8SRichard Henderson         return NULL;
3557d8b28b8SRichard Henderson     }
3567d8b28b8SRichard Henderson     return arm_feature(env, m_sysreg_def[reg].feature) ? ptr : NULL;
3577d8b28b8SRichard Henderson }
3587d8b28b8SRichard Henderson 
3597d8b28b8SRichard Henderson static int m_sysreg_get(CPUARMState *env, GByteArray *buf,
3607d8b28b8SRichard Henderson                         MProfileSysreg reg, bool secure)
3617d8b28b8SRichard Henderson {
3627d8b28b8SRichard Henderson     uint32_t *ptr = m_sysreg_ptr(env, reg, secure);
3637d8b28b8SRichard Henderson 
3647d8b28b8SRichard Henderson     if (ptr == NULL) {
3657d8b28b8SRichard Henderson         return 0;
3667d8b28b8SRichard Henderson     }
3677d8b28b8SRichard Henderson     return gdb_get_reg32(buf, *ptr);
3687d8b28b8SRichard Henderson }
3697d8b28b8SRichard Henderson 
3707d8b28b8SRichard Henderson static int arm_gdb_get_m_systemreg(CPUARMState *env, GByteArray *buf, int reg)
3717d8b28b8SRichard Henderson {
3727d8b28b8SRichard Henderson     /*
3737d8b28b8SRichard Henderson      * Here, we emulate MRS instruction, where CONTROL has a mix of
3747d8b28b8SRichard Henderson      * banked and non-banked bits.
3757d8b28b8SRichard Henderson      */
3767d8b28b8SRichard Henderson     if (reg == M_SYSREG_CONTROL) {
3777d8b28b8SRichard Henderson         return gdb_get_reg32(buf, arm_v7m_mrs_control(env, env->v7m.secure));
3787d8b28b8SRichard Henderson     }
3797d8b28b8SRichard Henderson     return m_sysreg_get(env, buf, reg, env->v7m.secure);
3807d8b28b8SRichard Henderson }
3817d8b28b8SRichard Henderson 
3827d8b28b8SRichard Henderson static int arm_gdb_set_m_systemreg(CPUARMState *env, uint8_t *buf, int reg)
3837d8b28b8SRichard Henderson {
3847d8b28b8SRichard Henderson     return 0; /* TODO */
3857d8b28b8SRichard Henderson }
3867d8b28b8SRichard Henderson 
387*690bd97bSAkihiko Odaki static GDBFeature *arm_gen_dynamic_m_systemreg_feature(CPUState *cs,
388*690bd97bSAkihiko Odaki                                                        int base_reg)
3897d8b28b8SRichard Henderson {
3907d8b28b8SRichard Henderson     ARMCPU *cpu = ARM_CPU(cs);
3917d8b28b8SRichard Henderson     CPUARMState *env = &cpu->env;
392*690bd97bSAkihiko Odaki     GDBFeatureBuilder builder;
393*690bd97bSAkihiko Odaki     int reg = 0;
3947d8b28b8SRichard Henderson     int i;
3957d8b28b8SRichard Henderson 
396*690bd97bSAkihiko Odaki     gdb_feature_builder_init(&builder, &cpu->dyn_m_systemreg_feature.desc,
397*690bd97bSAkihiko Odaki                              "org.gnu.gdb.arm.m-system", "arm-m-system.xml",
398*690bd97bSAkihiko Odaki                              base_reg);
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)) {
402*690bd97bSAkihiko Odaki             gdb_feature_builder_append_reg(&builder, m_sysreg_def[i].name, 32,
403*690bd97bSAkihiko Odaki                                            reg++, "int", NULL);
4047d8b28b8SRichard Henderson         }
4057d8b28b8SRichard Henderson     }
4067d8b28b8SRichard Henderson 
407*690bd97bSAkihiko Odaki     gdb_feature_builder_end(&builder);
4087d8b28b8SRichard Henderson 
409*690bd97bSAkihiko Odaki     return &cpu->dyn_m_systemreg_feature.desc;
4107d8b28b8SRichard Henderson }
4117d8b28b8SRichard Henderson 
4127d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
4137d8b28b8SRichard Henderson /*
4147d8b28b8SRichard Henderson  * For user-only, we see the non-secure registers via m_systemreg above.
4157d8b28b8SRichard Henderson  * For secext, encode the non-secure view as even and secure view as odd.
4167d8b28b8SRichard Henderson  */
4177d8b28b8SRichard Henderson static int arm_gdb_get_m_secextreg(CPUARMState *env, GByteArray *buf, int reg)
4187d8b28b8SRichard Henderson {
4197d8b28b8SRichard Henderson     return m_sysreg_get(env, buf, reg >> 1, reg & 1);
4207d8b28b8SRichard Henderson }
4217d8b28b8SRichard Henderson 
4227d8b28b8SRichard Henderson static int arm_gdb_set_m_secextreg(CPUARMState *env, uint8_t *buf, int reg)
4237d8b28b8SRichard Henderson {
4247d8b28b8SRichard Henderson     return 0; /* TODO */
4257d8b28b8SRichard Henderson }
4267d8b28b8SRichard Henderson 
427*690bd97bSAkihiko Odaki static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
428*690bd97bSAkihiko Odaki                                                        int base_reg)
4297d8b28b8SRichard Henderson {
4307d8b28b8SRichard Henderson     ARMCPU *cpu = ARM_CPU(cs);
431*690bd97bSAkihiko Odaki     GDBFeatureBuilder builder;
432*690bd97bSAkihiko Odaki     char *name;
433*690bd97bSAkihiko Odaki     int reg = 0;
4347d8b28b8SRichard Henderson     int i;
4357d8b28b8SRichard Henderson 
436*690bd97bSAkihiko Odaki     gdb_feature_builder_init(&builder, &cpu->dyn_m_secextreg_feature.desc,
437*690bd97bSAkihiko Odaki                              "org.gnu.gdb.arm.secext", "arm-m-secext.xml",
438*690bd97bSAkihiko Odaki                              base_reg);
4397d8b28b8SRichard Henderson 
4407d8b28b8SRichard Henderson     for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
441*690bd97bSAkihiko Odaki         name = g_strconcat(m_sysreg_def[i].name, "_ns", NULL);
442*690bd97bSAkihiko Odaki         gdb_feature_builder_append_reg(&builder, name, 32, reg++,
443*690bd97bSAkihiko Odaki                                        "int", NULL);
444*690bd97bSAkihiko Odaki         name = g_strconcat(m_sysreg_def[i].name, "_s", NULL);
445*690bd97bSAkihiko Odaki         gdb_feature_builder_append_reg(&builder, name, 32, reg++,
446*690bd97bSAkihiko Odaki                                        "int", NULL);
4477d8b28b8SRichard Henderson     }
4487d8b28b8SRichard Henderson 
449*690bd97bSAkihiko Odaki     gdb_feature_builder_end(&builder);
4507d8b28b8SRichard Henderson 
451*690bd97bSAkihiko Odaki     return &cpu->dyn_m_secextreg_feature.desc;
4527d8b28b8SRichard Henderson }
4537d8b28b8SRichard Henderson #endif
454893ca916SFabiano Rosas #endif /* CONFIG_TCG */
4557d8b28b8SRichard Henderson 
456200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
457200bf5b7SAbdallah Bouassida {
458200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
459200bf5b7SAbdallah Bouassida 
460200bf5b7SAbdallah Bouassida     if (strcmp(xmlname, "system-registers.xml") == 0) {
461*690bd97bSAkihiko Odaki         return cpu->dyn_sysreg_feature.desc.xml;
462d12379c5SAlex Bennée     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
463*690bd97bSAkihiko Odaki         return cpu->dyn_svereg_feature.desc.xml;
4647d8b28b8SRichard Henderson     } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
465*690bd97bSAkihiko Odaki         return cpu->dyn_m_systemreg_feature.desc.xml;
4667d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
4677d8b28b8SRichard Henderson     } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
468*690bd97bSAkihiko Odaki         return cpu->dyn_m_secextreg_feature.desc.xml;
4697d8b28b8SRichard Henderson #endif
470200bf5b7SAbdallah Bouassida     }
471200bf5b7SAbdallah Bouassida     return NULL;
472200bf5b7SAbdallah Bouassida }
47389f4f20eSPeter Maydell 
47489f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
47589f4f20eSPeter Maydell {
47689f4f20eSPeter Maydell     CPUState *cs = CPU(cpu);
47789f4f20eSPeter Maydell     CPUARMState *env = &cpu->env;
47889f4f20eSPeter Maydell 
47989f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
48089f4f20eSPeter Maydell         /*
48189f4f20eSPeter Maydell          * The lower part of each SVE register aliases to the FPU
48289f4f20eSPeter Maydell          * registers so we don't need to include both.
48389f4f20eSPeter Maydell          */
48489f4f20eSPeter Maydell #ifdef TARGET_AARCH64
48589f4f20eSPeter Maydell         if (isar_feature_aa64_sve(&cpu->isar)) {
486*690bd97bSAkihiko Odaki             int nreg = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs)->num_regs;
487963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
488963a6b91SRichard Henderson                                      aarch64_gdb_set_sve_reg, nreg,
48989f4f20eSPeter Maydell                                      "sve-registers.xml", 0);
49089f4f20eSPeter Maydell         } else {
491963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
492963a6b91SRichard Henderson                                      aarch64_gdb_set_fpu_reg,
49389f4f20eSPeter Maydell                                      34, "aarch64-fpu.xml", 0);
49489f4f20eSPeter Maydell         }
4955787d17aSPeter Maydell         /*
4967bdd67a5SPeter Maydell          * Note that we report pauth information via the feature name
4977bdd67a5SPeter Maydell          * org.gnu.gdb.aarch64.pauth_v2, not org.gnu.gdb.aarch64.pauth.
4987bdd67a5SPeter Maydell          * GDB versions 9 through 12 have a bug where they will crash
4997bdd67a5SPeter Maydell          * if they see the latter XML from QEMU.
5005787d17aSPeter Maydell          */
501e995d5ccSRichard Henderson         if (isar_feature_aa64_pauth(&cpu->isar)) {
502e995d5ccSRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
503e995d5ccSRichard Henderson                                      aarch64_gdb_set_pauth_reg,
504e995d5ccSRichard Henderson                                      4, "aarch64-pauth.xml", 0);
505e995d5ccSRichard Henderson         }
50689f4f20eSPeter Maydell #endif
507b355f08aSPeter Maydell     } else {
508b355f08aSPeter Maydell         if (arm_feature(env, ARM_FEATURE_NEON)) {
50989f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
510b355f08aSPeter Maydell                                      49, "arm-neon.xml", 0);
51189f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
51289f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
513b355f08aSPeter Maydell                                      33, "arm-vfp3.xml", 0);
51489f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
51589f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
516b355f08aSPeter Maydell                                      17, "arm-vfp.xml", 0);
517b355f08aSPeter Maydell         }
518b355f08aSPeter Maydell         if (!arm_feature(env, ARM_FEATURE_M)) {
519b355f08aSPeter Maydell             /*
520b355f08aSPeter Maydell              * A and R profile have FP sysregs FPEXC and FPSID that we
521b355f08aSPeter Maydell              * expose to gdb.
522b355f08aSPeter Maydell              */
523b355f08aSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
524b355f08aSPeter Maydell                                      2, "arm-vfp-sysregs.xml", 0);
525b355f08aSPeter Maydell         }
52689f4f20eSPeter Maydell     }
52746e3b237SPhilippe Mathieu-Daudé     if (cpu_isar_feature(aa32_mve, cpu) && tcg_enabled()) {
528dbd9e084SPeter Maydell         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
529dbd9e084SPeter Maydell                                  1, "arm-m-profile-mve.xml", 0);
530dbd9e084SPeter Maydell     }
53189f4f20eSPeter Maydell     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
532*690bd97bSAkihiko Odaki                              arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs)->num_regs,
53389f4f20eSPeter Maydell                              "system-registers.xml", 0);
53489f4f20eSPeter Maydell 
535893ca916SFabiano Rosas #ifdef CONFIG_TCG
53646e3b237SPhilippe Mathieu-Daudé     if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
5377d8b28b8SRichard Henderson         gdb_register_coprocessor(cs,
5387d8b28b8SRichard Henderson             arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
539*690bd97bSAkihiko Odaki             arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs)->num_regs,
5407d8b28b8SRichard Henderson             "arm-m-system.xml", 0);
5417d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
5427d8b28b8SRichard Henderson         if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
5437d8b28b8SRichard Henderson             gdb_register_coprocessor(cs,
5447d8b28b8SRichard Henderson                 arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
545*690bd97bSAkihiko Odaki                 arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs)->num_regs,
5467d8b28b8SRichard Henderson                 "arm-m-secext.xml", 0);
5477d8b28b8SRichard Henderson         }
5487d8b28b8SRichard Henderson #endif
5497d8b28b8SRichard Henderson     }
550893ca916SFabiano Rosas #endif /* CONFIG_TCG */
55189f4f20eSPeter Maydell }
552