xref: /openbmc/qemu/target/arm/gdbstub.c (revision 66260159a72ecd6c384197ba3d6e6f660ca5b482)
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 
29690bd97bSAkihiko Odaki typedef struct RegisterSysregFeatureParam {
30200bf5b7SAbdallah Bouassida     CPUState *cs;
31690bd97bSAkihiko Odaki     GDBFeatureBuilder builder;
3232d6e32aSAlex Bennée     int n;
33690bd97bSAkihiko 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 
109*66260159SAkihiko Odaki static int vfp_gdb_get_reg(CPUState *cs, GByteArray *buf, int reg)
11089f4f20eSPeter Maydell {
111*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
112*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
11389f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
11489f4f20eSPeter Maydell 
11589f4f20eSPeter Maydell     /* VFP data registers are always little-endian.  */
11689f4f20eSPeter Maydell     if (reg < nregs) {
11789f4f20eSPeter Maydell         return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg));
11889f4f20eSPeter Maydell     }
11989f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
12089f4f20eSPeter Maydell         /* Aliases for Q regs.  */
12189f4f20eSPeter Maydell         nregs += 16;
12289f4f20eSPeter Maydell         if (reg < nregs) {
12389f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
12489f4f20eSPeter Maydell             return gdb_get_reg128(buf, q[0], q[1]);
12589f4f20eSPeter Maydell         }
12689f4f20eSPeter Maydell     }
12789f4f20eSPeter Maydell     switch (reg - nregs) {
12889f4f20eSPeter Maydell     case 0:
12989f4f20eSPeter Maydell         return gdb_get_reg32(buf, vfp_get_fpscr(env));
13089f4f20eSPeter Maydell     }
13189f4f20eSPeter Maydell     return 0;
13289f4f20eSPeter Maydell }
13389f4f20eSPeter Maydell 
134*66260159SAkihiko Odaki static int vfp_gdb_set_reg(CPUState *cs, uint8_t *buf, int reg)
13589f4f20eSPeter Maydell {
136*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
137*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
13889f4f20eSPeter Maydell     int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16;
13989f4f20eSPeter Maydell 
14089f4f20eSPeter Maydell     if (reg < nregs) {
14189f4f20eSPeter Maydell         *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
14289f4f20eSPeter Maydell         return 8;
14389f4f20eSPeter Maydell     }
14489f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_NEON)) {
14589f4f20eSPeter Maydell         nregs += 16;
14689f4f20eSPeter Maydell         if (reg < nregs) {
14789f4f20eSPeter Maydell             uint64_t *q = aa32_vfp_qreg(env, reg - 32);
14889f4f20eSPeter Maydell             q[0] = ldq_le_p(buf);
14989f4f20eSPeter Maydell             q[1] = ldq_le_p(buf + 8);
15089f4f20eSPeter Maydell             return 16;
15189f4f20eSPeter Maydell         }
15289f4f20eSPeter Maydell     }
15389f4f20eSPeter Maydell     switch (reg - nregs) {
15489f4f20eSPeter Maydell     case 0:
155b355f08aSPeter Maydell         vfp_set_fpscr(env, ldl_p(buf));
156b355f08aSPeter Maydell         return 4;
157b355f08aSPeter Maydell     }
158b355f08aSPeter Maydell     return 0;
159b355f08aSPeter Maydell }
160b355f08aSPeter Maydell 
161*66260159SAkihiko Odaki static int vfp_gdb_get_sysreg(CPUState *cs, GByteArray *buf, int reg)
162b355f08aSPeter Maydell {
163*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
164*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
165*66260159SAkihiko Odaki 
166b355f08aSPeter Maydell     switch (reg) {
167b355f08aSPeter Maydell     case 0:
168b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]);
169b355f08aSPeter Maydell     case 1:
170b355f08aSPeter Maydell         return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]);
171b355f08aSPeter Maydell     }
172b355f08aSPeter Maydell     return 0;
173b355f08aSPeter Maydell }
174b355f08aSPeter Maydell 
175*66260159SAkihiko Odaki static int vfp_gdb_set_sysreg(CPUState *cs, uint8_t *buf, int reg)
176b355f08aSPeter Maydell {
177*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
178*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
179*66260159SAkihiko Odaki 
180b355f08aSPeter Maydell     switch (reg) {
181b355f08aSPeter Maydell     case 0:
18289f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf);
18389f4f20eSPeter Maydell         return 4;
18489f4f20eSPeter Maydell     case 1:
18589f4f20eSPeter Maydell         env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30);
18689f4f20eSPeter Maydell         return 4;
18789f4f20eSPeter Maydell     }
18889f4f20eSPeter Maydell     return 0;
18989f4f20eSPeter Maydell }
19089f4f20eSPeter Maydell 
191*66260159SAkihiko Odaki static int mve_gdb_get_reg(CPUState *cs, GByteArray *buf, int reg)
192dbd9e084SPeter Maydell {
193*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
194*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
195*66260159SAkihiko Odaki 
196dbd9e084SPeter Maydell     switch (reg) {
197dbd9e084SPeter Maydell     case 0:
198dbd9e084SPeter Maydell         return gdb_get_reg32(buf, env->v7m.vpr);
199dbd9e084SPeter Maydell     default:
200dbd9e084SPeter Maydell         return 0;
201dbd9e084SPeter Maydell     }
202dbd9e084SPeter Maydell }
203dbd9e084SPeter Maydell 
204*66260159SAkihiko Odaki static int mve_gdb_set_reg(CPUState *cs, uint8_t *buf, int reg)
205dbd9e084SPeter Maydell {
206*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
207*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
208*66260159SAkihiko Odaki 
209dbd9e084SPeter Maydell     switch (reg) {
210dbd9e084SPeter Maydell     case 0:
211dbd9e084SPeter Maydell         env->v7m.vpr = ldl_p(buf);
212dbd9e084SPeter Maydell         return 4;
213dbd9e084SPeter Maydell     default:
214dbd9e084SPeter Maydell         return 0;
215dbd9e084SPeter Maydell     }
216dbd9e084SPeter Maydell }
217dbd9e084SPeter Maydell 
21889f4f20eSPeter Maydell /**
21989f4f20eSPeter Maydell  * arm_get/set_gdb_*: get/set a gdb register
22089f4f20eSPeter Maydell  * @env: the CPU state
22189f4f20eSPeter Maydell  * @buf: a buffer to copy to/from
22289f4f20eSPeter Maydell  * @reg: register number (offset from start of group)
22389f4f20eSPeter Maydell  *
22489f4f20eSPeter Maydell  * We return the number of bytes copied
22589f4f20eSPeter Maydell  */
22689f4f20eSPeter Maydell 
227*66260159SAkihiko Odaki static int arm_gdb_get_sysreg(CPUState *cs, GByteArray *buf, int reg)
22889f4f20eSPeter Maydell {
229*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
230*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
23189f4f20eSPeter Maydell     const ARMCPRegInfo *ri;
23289f4f20eSPeter Maydell     uint32_t key;
23389f4f20eSPeter Maydell 
234690bd97bSAkihiko Odaki     key = cpu->dyn_sysreg_feature.data.cpregs.keys[reg];
23589f4f20eSPeter Maydell     ri = get_arm_cp_reginfo(cpu->cp_regs, key);
23689f4f20eSPeter Maydell     if (ri) {
23789f4f20eSPeter Maydell         if (cpreg_field_is_64bit(ri)) {
23889f4f20eSPeter Maydell             return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri));
23989f4f20eSPeter Maydell         } else {
24089f4f20eSPeter Maydell             return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri));
24189f4f20eSPeter Maydell         }
24289f4f20eSPeter Maydell     }
24389f4f20eSPeter Maydell     return 0;
24489f4f20eSPeter Maydell }
24589f4f20eSPeter Maydell 
246*66260159SAkihiko Odaki static int arm_gdb_set_sysreg(CPUState *cs, uint8_t *buf, int reg)
24789f4f20eSPeter Maydell {
24889f4f20eSPeter Maydell     return 0;
24989f4f20eSPeter Maydell }
25089f4f20eSPeter Maydell 
251690bd97bSAkihiko Odaki static void arm_gen_one_feature_sysreg(GDBFeatureBuilder *builder,
252690bd97bSAkihiko Odaki                                        DynamicGDBFeatureInfo *dyn_feature,
253200bf5b7SAbdallah Bouassida                                        ARMCPRegInfo *ri, uint32_t ri_key,
254690bd97bSAkihiko Odaki                                        int bitsize, int n)
255200bf5b7SAbdallah Bouassida {
256690bd97bSAkihiko Odaki     gdb_feature_builder_append_reg(builder, ri->name, bitsize, n,
257690bd97bSAkihiko Odaki                                    "int", "cp_regs");
258690bd97bSAkihiko Odaki 
259690bd97bSAkihiko Odaki     dyn_feature->data.cpregs.keys[n] = ri_key;
260200bf5b7SAbdallah Bouassida }
261200bf5b7SAbdallah Bouassida 
262690bd97bSAkihiko Odaki static void arm_register_sysreg_for_feature(gpointer key, gpointer value,
263200bf5b7SAbdallah Bouassida                                             gpointer p)
264200bf5b7SAbdallah Bouassida {
2655860362dSRichard Henderson     uint32_t ri_key = (uintptr_t)key;
266200bf5b7SAbdallah Bouassida     ARMCPRegInfo *ri = value;
267690bd97bSAkihiko Odaki     RegisterSysregFeatureParam *param = p;
268200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(param->cs);
269200bf5b7SAbdallah Bouassida     CPUARMState *env = &cpu->env;
270690bd97bSAkihiko Odaki     DynamicGDBFeatureInfo *dyn_feature = &cpu->dyn_sysreg_feature;
271200bf5b7SAbdallah Bouassida 
272200bf5b7SAbdallah Bouassida     if (!(ri->type & (ARM_CP_NO_RAW | ARM_CP_NO_GDB))) {
273200bf5b7SAbdallah Bouassida         if (arm_feature(env, ARM_FEATURE_AARCH64)) {
274200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA64) {
275690bd97bSAkihiko Odaki                 arm_gen_one_feature_sysreg(&param->builder, dyn_feature,
276690bd97bSAkihiko Odaki                                            ri, ri_key, 64, param->n++);
277200bf5b7SAbdallah Bouassida             }
278200bf5b7SAbdallah Bouassida         } else {
279200bf5b7SAbdallah Bouassida             if (ri->state == ARM_CP_STATE_AA32) {
280200bf5b7SAbdallah Bouassida                 if (!arm_feature(env, ARM_FEATURE_EL3) &&
281200bf5b7SAbdallah Bouassida                     (ri->secure & ARM_CP_SECSTATE_S)) {
282200bf5b7SAbdallah Bouassida                     return;
283200bf5b7SAbdallah Bouassida                 }
284200bf5b7SAbdallah Bouassida                 if (ri->type & ARM_CP_64BIT) {
285690bd97bSAkihiko Odaki                     arm_gen_one_feature_sysreg(&param->builder, dyn_feature,
286690bd97bSAkihiko Odaki                                                ri, ri_key, 64, param->n++);
287200bf5b7SAbdallah Bouassida                 } else {
288690bd97bSAkihiko Odaki                     arm_gen_one_feature_sysreg(&param->builder, dyn_feature,
289690bd97bSAkihiko Odaki                                                ri, ri_key, 32, param->n++);
290200bf5b7SAbdallah Bouassida                 }
291200bf5b7SAbdallah Bouassida             }
292200bf5b7SAbdallah Bouassida         }
293200bf5b7SAbdallah Bouassida     }
294200bf5b7SAbdallah Bouassida }
295200bf5b7SAbdallah Bouassida 
296690bd97bSAkihiko Odaki static GDBFeature *arm_gen_dynamic_sysreg_feature(CPUState *cs, int base_reg)
297200bf5b7SAbdallah Bouassida {
298200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
299690bd97bSAkihiko Odaki     RegisterSysregFeatureParam param = {cs};
300690bd97bSAkihiko Odaki     gsize num_regs = g_hash_table_size(cpu->cp_regs);
301200bf5b7SAbdallah Bouassida 
302690bd97bSAkihiko Odaki     gdb_feature_builder_init(&param.builder,
303690bd97bSAkihiko Odaki                              &cpu->dyn_sysreg_feature.desc,
304690bd97bSAkihiko Odaki                              "org.qemu.gdb.arm.sys.regs",
305690bd97bSAkihiko Odaki                              "system-registers.xml",
306690bd97bSAkihiko Odaki                              base_reg);
307690bd97bSAkihiko Odaki     cpu->dyn_sysreg_feature.data.cpregs.keys = g_new(uint32_t, num_regs);
308690bd97bSAkihiko Odaki     g_hash_table_foreach(cpu->cp_regs, arm_register_sysreg_for_feature, &param);
309690bd97bSAkihiko Odaki     gdb_feature_builder_end(&param.builder);
310690bd97bSAkihiko Odaki     return &cpu->dyn_sysreg_feature.desc;
311200bf5b7SAbdallah Bouassida }
312200bf5b7SAbdallah Bouassida 
313893ca916SFabiano Rosas #ifdef CONFIG_TCG
3147d8b28b8SRichard Henderson typedef enum {
3157d8b28b8SRichard Henderson     M_SYSREG_MSP,
3167d8b28b8SRichard Henderson     M_SYSREG_PSP,
3177d8b28b8SRichard Henderson     M_SYSREG_PRIMASK,
3187d8b28b8SRichard Henderson     M_SYSREG_CONTROL,
3197d8b28b8SRichard Henderson     M_SYSREG_BASEPRI,
3207d8b28b8SRichard Henderson     M_SYSREG_FAULTMASK,
3217d8b28b8SRichard Henderson     M_SYSREG_MSPLIM,
3227d8b28b8SRichard Henderson     M_SYSREG_PSPLIM,
3237d8b28b8SRichard Henderson } MProfileSysreg;
3247d8b28b8SRichard Henderson 
3257d8b28b8SRichard Henderson static const struct {
3267d8b28b8SRichard Henderson     const char *name;
3277d8b28b8SRichard Henderson     int feature;
3287d8b28b8SRichard Henderson } m_sysreg_def[] = {
3297d8b28b8SRichard Henderson     [M_SYSREG_MSP] = { "msp", ARM_FEATURE_M },
3307d8b28b8SRichard Henderson     [M_SYSREG_PSP] = { "psp", ARM_FEATURE_M },
3317d8b28b8SRichard Henderson     [M_SYSREG_PRIMASK] = { "primask", ARM_FEATURE_M },
3327d8b28b8SRichard Henderson     [M_SYSREG_CONTROL] = { "control", ARM_FEATURE_M },
3337d8b28b8SRichard Henderson     [M_SYSREG_BASEPRI] = { "basepri", ARM_FEATURE_M_MAIN },
3347d8b28b8SRichard Henderson     [M_SYSREG_FAULTMASK] = { "faultmask", ARM_FEATURE_M_MAIN },
3357d8b28b8SRichard Henderson     [M_SYSREG_MSPLIM] = { "msplim", ARM_FEATURE_V8 },
3367d8b28b8SRichard Henderson     [M_SYSREG_PSPLIM] = { "psplim", ARM_FEATURE_V8 },
3377d8b28b8SRichard Henderson };
3387d8b28b8SRichard Henderson 
3397d8b28b8SRichard Henderson static uint32_t *m_sysreg_ptr(CPUARMState *env, MProfileSysreg reg, bool sec)
3407d8b28b8SRichard Henderson {
3417d8b28b8SRichard Henderson     uint32_t *ptr;
3427d8b28b8SRichard Henderson 
3437d8b28b8SRichard Henderson     switch (reg) {
3447d8b28b8SRichard Henderson     case M_SYSREG_MSP:
3457d8b28b8SRichard Henderson         ptr = arm_v7m_get_sp_ptr(env, sec, false, true);
3467d8b28b8SRichard Henderson         break;
3477d8b28b8SRichard Henderson     case M_SYSREG_PSP:
3487d8b28b8SRichard Henderson         ptr = arm_v7m_get_sp_ptr(env, sec, true, true);
3497d8b28b8SRichard Henderson         break;
3507d8b28b8SRichard Henderson     case M_SYSREG_MSPLIM:
3517d8b28b8SRichard Henderson         ptr = &env->v7m.msplim[sec];
3527d8b28b8SRichard Henderson         break;
3537d8b28b8SRichard Henderson     case M_SYSREG_PSPLIM:
3547d8b28b8SRichard Henderson         ptr = &env->v7m.psplim[sec];
3557d8b28b8SRichard Henderson         break;
3567d8b28b8SRichard Henderson     case M_SYSREG_PRIMASK:
3577d8b28b8SRichard Henderson         ptr = &env->v7m.primask[sec];
3587d8b28b8SRichard Henderson         break;
3597d8b28b8SRichard Henderson     case M_SYSREG_BASEPRI:
3607d8b28b8SRichard Henderson         ptr = &env->v7m.basepri[sec];
3617d8b28b8SRichard Henderson         break;
3627d8b28b8SRichard Henderson     case M_SYSREG_FAULTMASK:
3637d8b28b8SRichard Henderson         ptr = &env->v7m.faultmask[sec];
3647d8b28b8SRichard Henderson         break;
3657d8b28b8SRichard Henderson     case M_SYSREG_CONTROL:
3667d8b28b8SRichard Henderson         ptr = &env->v7m.control[sec];
3677d8b28b8SRichard Henderson         break;
3687d8b28b8SRichard Henderson     default:
3697d8b28b8SRichard Henderson         return NULL;
3707d8b28b8SRichard Henderson     }
3717d8b28b8SRichard Henderson     return arm_feature(env, m_sysreg_def[reg].feature) ? ptr : NULL;
3727d8b28b8SRichard Henderson }
3737d8b28b8SRichard Henderson 
3747d8b28b8SRichard Henderson static int m_sysreg_get(CPUARMState *env, GByteArray *buf,
3757d8b28b8SRichard Henderson                         MProfileSysreg reg, bool secure)
3767d8b28b8SRichard Henderson {
3777d8b28b8SRichard Henderson     uint32_t *ptr = m_sysreg_ptr(env, reg, secure);
3787d8b28b8SRichard Henderson 
3797d8b28b8SRichard Henderson     if (ptr == NULL) {
3807d8b28b8SRichard Henderson         return 0;
3817d8b28b8SRichard Henderson     }
3827d8b28b8SRichard Henderson     return gdb_get_reg32(buf, *ptr);
3837d8b28b8SRichard Henderson }
3847d8b28b8SRichard Henderson 
385*66260159SAkihiko Odaki static int arm_gdb_get_m_systemreg(CPUState *cs, GByteArray *buf, int reg)
3867d8b28b8SRichard Henderson {
387*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
388*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
389*66260159SAkihiko Odaki 
3907d8b28b8SRichard Henderson     /*
3917d8b28b8SRichard Henderson      * Here, we emulate MRS instruction, where CONTROL has a mix of
3927d8b28b8SRichard Henderson      * banked and non-banked bits.
3937d8b28b8SRichard Henderson      */
3947d8b28b8SRichard Henderson     if (reg == M_SYSREG_CONTROL) {
3957d8b28b8SRichard Henderson         return gdb_get_reg32(buf, arm_v7m_mrs_control(env, env->v7m.secure));
3967d8b28b8SRichard Henderson     }
3977d8b28b8SRichard Henderson     return m_sysreg_get(env, buf, reg, env->v7m.secure);
3987d8b28b8SRichard Henderson }
3997d8b28b8SRichard Henderson 
400*66260159SAkihiko Odaki static int arm_gdb_set_m_systemreg(CPUState *cs, uint8_t *buf, int reg)
4017d8b28b8SRichard Henderson {
4027d8b28b8SRichard Henderson     return 0; /* TODO */
4037d8b28b8SRichard Henderson }
4047d8b28b8SRichard Henderson 
405690bd97bSAkihiko Odaki static GDBFeature *arm_gen_dynamic_m_systemreg_feature(CPUState *cs,
406690bd97bSAkihiko Odaki                                                        int base_reg)
4077d8b28b8SRichard Henderson {
4087d8b28b8SRichard Henderson     ARMCPU *cpu = ARM_CPU(cs);
4097d8b28b8SRichard Henderson     CPUARMState *env = &cpu->env;
410690bd97bSAkihiko Odaki     GDBFeatureBuilder builder;
411690bd97bSAkihiko Odaki     int reg = 0;
4127d8b28b8SRichard Henderson     int i;
4137d8b28b8SRichard Henderson 
414690bd97bSAkihiko Odaki     gdb_feature_builder_init(&builder, &cpu->dyn_m_systemreg_feature.desc,
415690bd97bSAkihiko Odaki                              "org.gnu.gdb.arm.m-system", "arm-m-system.xml",
416690bd97bSAkihiko Odaki                              base_reg);
4177d8b28b8SRichard Henderson 
4187d8b28b8SRichard Henderson     for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
4197d8b28b8SRichard Henderson         if (arm_feature(env, m_sysreg_def[i].feature)) {
420690bd97bSAkihiko Odaki             gdb_feature_builder_append_reg(&builder, m_sysreg_def[i].name, 32,
421690bd97bSAkihiko Odaki                                            reg++, "int", NULL);
4227d8b28b8SRichard Henderson         }
4237d8b28b8SRichard Henderson     }
4247d8b28b8SRichard Henderson 
425690bd97bSAkihiko Odaki     gdb_feature_builder_end(&builder);
4267d8b28b8SRichard Henderson 
427690bd97bSAkihiko Odaki     return &cpu->dyn_m_systemreg_feature.desc;
4287d8b28b8SRichard Henderson }
4297d8b28b8SRichard Henderson 
4307d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
4317d8b28b8SRichard Henderson /*
4327d8b28b8SRichard Henderson  * For user-only, we see the non-secure registers via m_systemreg above.
4337d8b28b8SRichard Henderson  * For secext, encode the non-secure view as even and secure view as odd.
4347d8b28b8SRichard Henderson  */
435*66260159SAkihiko Odaki static int arm_gdb_get_m_secextreg(CPUState *cs, GByteArray *buf, int reg)
4367d8b28b8SRichard Henderson {
437*66260159SAkihiko Odaki     ARMCPU *cpu = ARM_CPU(cs);
438*66260159SAkihiko Odaki     CPUARMState *env = &cpu->env;
439*66260159SAkihiko Odaki 
4407d8b28b8SRichard Henderson     return m_sysreg_get(env, buf, reg >> 1, reg & 1);
4417d8b28b8SRichard Henderson }
4427d8b28b8SRichard Henderson 
443*66260159SAkihiko Odaki static int arm_gdb_set_m_secextreg(CPUState *cs, uint8_t *buf, int reg)
4447d8b28b8SRichard Henderson {
4457d8b28b8SRichard Henderson     return 0; /* TODO */
4467d8b28b8SRichard Henderson }
4477d8b28b8SRichard Henderson 
448690bd97bSAkihiko Odaki static GDBFeature *arm_gen_dynamic_m_secextreg_feature(CPUState *cs,
449690bd97bSAkihiko Odaki                                                        int base_reg)
4507d8b28b8SRichard Henderson {
4517d8b28b8SRichard Henderson     ARMCPU *cpu = ARM_CPU(cs);
452690bd97bSAkihiko Odaki     GDBFeatureBuilder builder;
453690bd97bSAkihiko Odaki     char *name;
454690bd97bSAkihiko Odaki     int reg = 0;
4557d8b28b8SRichard Henderson     int i;
4567d8b28b8SRichard Henderson 
457690bd97bSAkihiko Odaki     gdb_feature_builder_init(&builder, &cpu->dyn_m_secextreg_feature.desc,
458690bd97bSAkihiko Odaki                              "org.gnu.gdb.arm.secext", "arm-m-secext.xml",
459690bd97bSAkihiko Odaki                              base_reg);
4607d8b28b8SRichard Henderson 
4617d8b28b8SRichard Henderson     for (i = 0; i < ARRAY_SIZE(m_sysreg_def); i++) {
462690bd97bSAkihiko Odaki         name = g_strconcat(m_sysreg_def[i].name, "_ns", NULL);
463690bd97bSAkihiko Odaki         gdb_feature_builder_append_reg(&builder, name, 32, reg++,
464690bd97bSAkihiko Odaki                                        "int", NULL);
465690bd97bSAkihiko Odaki         name = g_strconcat(m_sysreg_def[i].name, "_s", NULL);
466690bd97bSAkihiko Odaki         gdb_feature_builder_append_reg(&builder, name, 32, reg++,
467690bd97bSAkihiko Odaki                                        "int", NULL);
4687d8b28b8SRichard Henderson     }
4697d8b28b8SRichard Henderson 
470690bd97bSAkihiko Odaki     gdb_feature_builder_end(&builder);
4717d8b28b8SRichard Henderson 
472690bd97bSAkihiko Odaki     return &cpu->dyn_m_secextreg_feature.desc;
4737d8b28b8SRichard Henderson }
4747d8b28b8SRichard Henderson #endif
475893ca916SFabiano Rosas #endif /* CONFIG_TCG */
4767d8b28b8SRichard Henderson 
477200bf5b7SAbdallah Bouassida const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
478200bf5b7SAbdallah Bouassida {
479200bf5b7SAbdallah Bouassida     ARMCPU *cpu = ARM_CPU(cs);
480200bf5b7SAbdallah Bouassida 
481200bf5b7SAbdallah Bouassida     if (strcmp(xmlname, "system-registers.xml") == 0) {
482690bd97bSAkihiko Odaki         return cpu->dyn_sysreg_feature.desc.xml;
483d12379c5SAlex Bennée     } else if (strcmp(xmlname, "sve-registers.xml") == 0) {
484690bd97bSAkihiko Odaki         return cpu->dyn_svereg_feature.desc.xml;
4857d8b28b8SRichard Henderson     } else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
486690bd97bSAkihiko Odaki         return cpu->dyn_m_systemreg_feature.desc.xml;
4877d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
4887d8b28b8SRichard Henderson     } else if (strcmp(xmlname, "arm-m-secext.xml") == 0) {
489690bd97bSAkihiko Odaki         return cpu->dyn_m_secextreg_feature.desc.xml;
4907d8b28b8SRichard Henderson #endif
491200bf5b7SAbdallah Bouassida     }
492200bf5b7SAbdallah Bouassida     return NULL;
493200bf5b7SAbdallah Bouassida }
49489f4f20eSPeter Maydell 
49589f4f20eSPeter Maydell void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
49689f4f20eSPeter Maydell {
49789f4f20eSPeter Maydell     CPUState *cs = CPU(cpu);
49889f4f20eSPeter Maydell     CPUARMState *env = &cpu->env;
49989f4f20eSPeter Maydell 
50089f4f20eSPeter Maydell     if (arm_feature(env, ARM_FEATURE_AARCH64)) {
50189f4f20eSPeter Maydell         /*
50289f4f20eSPeter Maydell          * The lower part of each SVE register aliases to the FPU
50389f4f20eSPeter Maydell          * registers so we don't need to include both.
50489f4f20eSPeter Maydell          */
50589f4f20eSPeter Maydell #ifdef TARGET_AARCH64
50689f4f20eSPeter Maydell         if (isar_feature_aa64_sve(&cpu->isar)) {
507ac1e8671SAkihiko Odaki             GDBFeature *feature = arm_gen_dynamic_svereg_feature(cs, cs->gdb_num_regs);
508963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_sve_reg,
509ac1e8671SAkihiko Odaki                                      aarch64_gdb_set_sve_reg, feature, 0);
51089f4f20eSPeter Maydell         } else {
511963a6b91SRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_fpu_reg,
512963a6b91SRichard Henderson                                      aarch64_gdb_set_fpu_reg,
513ac1e8671SAkihiko Odaki                                      gdb_find_static_feature("aarch64-fpu.xml"),
514ac1e8671SAkihiko Odaki                                      0);
51589f4f20eSPeter Maydell         }
5165787d17aSPeter Maydell         /*
5177bdd67a5SPeter Maydell          * Note that we report pauth information via the feature name
5187bdd67a5SPeter Maydell          * org.gnu.gdb.aarch64.pauth_v2, not org.gnu.gdb.aarch64.pauth.
5197bdd67a5SPeter Maydell          * GDB versions 9 through 12 have a bug where they will crash
5207bdd67a5SPeter Maydell          * if they see the latter XML from QEMU.
5215787d17aSPeter Maydell          */
522e995d5ccSRichard Henderson         if (isar_feature_aa64_pauth(&cpu->isar)) {
523e995d5ccSRichard Henderson             gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
524e995d5ccSRichard Henderson                                      aarch64_gdb_set_pauth_reg,
525ac1e8671SAkihiko Odaki                                      gdb_find_static_feature("aarch64-pauth.xml"),
526ac1e8671SAkihiko Odaki                                      0);
527e995d5ccSRichard Henderson         }
52889f4f20eSPeter Maydell #endif
529b355f08aSPeter Maydell     } else {
530b355f08aSPeter Maydell         if (arm_feature(env, ARM_FEATURE_NEON)) {
53189f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
532ac1e8671SAkihiko Odaki                                      gdb_find_static_feature("arm-neon.xml"),
533ac1e8671SAkihiko Odaki                                      0);
53489f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_simd_r32, cpu)) {
53589f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
536ac1e8671SAkihiko Odaki                                      gdb_find_static_feature("arm-vfp3.xml"),
537ac1e8671SAkihiko Odaki                                      0);
53889f4f20eSPeter Maydell         } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
53989f4f20eSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
540ac1e8671SAkihiko Odaki                                      gdb_find_static_feature("arm-vfp.xml"), 0);
541b355f08aSPeter Maydell         }
542b355f08aSPeter Maydell         if (!arm_feature(env, ARM_FEATURE_M)) {
543b355f08aSPeter Maydell             /*
544b355f08aSPeter Maydell              * A and R profile have FP sysregs FPEXC and FPSID that we
545b355f08aSPeter Maydell              * expose to gdb.
546b355f08aSPeter Maydell              */
547b355f08aSPeter Maydell             gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg,
548ac1e8671SAkihiko Odaki                                      gdb_find_static_feature("arm-vfp-sysregs.xml"),
549ac1e8671SAkihiko Odaki                                      0);
550b355f08aSPeter Maydell         }
55189f4f20eSPeter Maydell     }
55246e3b237SPhilippe Mathieu-Daudé     if (cpu_isar_feature(aa32_mve, cpu) && tcg_enabled()) {
553dbd9e084SPeter Maydell         gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
554ac1e8671SAkihiko Odaki                                  gdb_find_static_feature("arm-m-profile-mve.xml"),
555ac1e8671SAkihiko Odaki                                  0);
556dbd9e084SPeter Maydell     }
55789f4f20eSPeter Maydell     gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
558ac1e8671SAkihiko Odaki                              arm_gen_dynamic_sysreg_feature(cs, cs->gdb_num_regs),
559ac1e8671SAkihiko Odaki                              0);
56089f4f20eSPeter Maydell 
561893ca916SFabiano Rosas #ifdef CONFIG_TCG
56246e3b237SPhilippe Mathieu-Daudé     if (arm_feature(env, ARM_FEATURE_M) && tcg_enabled()) {
5637d8b28b8SRichard Henderson         gdb_register_coprocessor(cs,
5647d8b28b8SRichard Henderson             arm_gdb_get_m_systemreg, arm_gdb_set_m_systemreg,
565ac1e8671SAkihiko Odaki             arm_gen_dynamic_m_systemreg_feature(cs, cs->gdb_num_regs), 0);
5667d8b28b8SRichard Henderson #ifndef CONFIG_USER_ONLY
5677d8b28b8SRichard Henderson         if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
5687d8b28b8SRichard Henderson             gdb_register_coprocessor(cs,
5697d8b28b8SRichard Henderson                 arm_gdb_get_m_secextreg, arm_gdb_set_m_secextreg,
570ac1e8671SAkihiko Odaki                 arm_gen_dynamic_m_secextreg_feature(cs, cs->gdb_num_regs), 0);
5717d8b28b8SRichard Henderson         }
5727d8b28b8SRichard Henderson #endif
5737d8b28b8SRichard Henderson     }
574893ca916SFabiano Rosas #endif /* CONFIG_TCG */
57589f4f20eSPeter Maydell }
576