From 9fcd15b9193e819b6cc2fd0a45e3506148812bb4 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Thu, 16 Sep 2021 17:54:04 +0200 Subject: arm: tcg: Adhere to SMCCC 1.3 section 5.2 The SMCCC 1.3 spec section 5.2 says The Unknown SMC Function Identifier is a sign-extended value of (-1) that is returned in the R0, W0 or X0 registers. An implementation must return this error code when it receives: * An SMC or HVC call with an unknown Function Identifier * An SMC or HVC call for a removed Function Identifier * An SMC64/HVC64 call from AArch32 state To comply with these statements, let's always return -1 when we encounter an unknown HVC or SMC call. Signed-off-by: Alexander Graf Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/psci.c | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) (limited to 'target') diff --git a/target/arm/psci.c b/target/arm/psci.c index 6709e28..b279c0b 100644 --- a/target/arm/psci.c +++ b/target/arm/psci.c @@ -27,15 +27,13 @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type) { - /* Return true if the r0/x0 value indicates a PSCI call and - * the exception type matches the configured PSCI conduit. This is - * called before the SMC/HVC instruction is executed, to decide whether - * we should treat it as a PSCI call or with the architecturally + /* + * Return true if the exception type matches the configured PSCI conduit. + * This is called before the SMC/HVC instruction is executed, to decide + * whether we should treat it as a PSCI call or with the architecturally * defined behaviour for an SMC or HVC (which might be UNDEF or trap * to EL2 or to EL3). */ - CPUARMState *env = &cpu->env; - uint64_t param = is_a64(env) ? env->xregs[0] : env->regs[0]; switch (excp_type) { case EXCP_HVC: @@ -52,27 +50,7 @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type) return false; } - switch (param) { - case QEMU_PSCI_0_2_FN_PSCI_VERSION: - case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: - case QEMU_PSCI_0_2_FN_AFFINITY_INFO: - case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: - case QEMU_PSCI_0_2_FN_SYSTEM_RESET: - case QEMU_PSCI_0_2_FN_SYSTEM_OFF: - case QEMU_PSCI_0_1_FN_CPU_ON: - case QEMU_PSCI_0_2_FN_CPU_ON: - case QEMU_PSCI_0_2_FN64_CPU_ON: - case QEMU_PSCI_0_1_FN_CPU_OFF: - case QEMU_PSCI_0_2_FN_CPU_OFF: - case QEMU_PSCI_0_1_FN_CPU_SUSPEND: - case QEMU_PSCI_0_2_FN_CPU_SUSPEND: - case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: - case QEMU_PSCI_0_1_FN_MIGRATE: - case QEMU_PSCI_0_2_FN_MIGRATE: - return true; - default: - return false; - } + return true; } void arm_handle_psci_call(ARMCPU *cpu) @@ -194,10 +172,9 @@ void arm_handle_psci_call(ARMCPU *cpu) break; case QEMU_PSCI_0_1_FN_MIGRATE: case QEMU_PSCI_0_2_FN_MIGRATE: + default: ret = QEMU_PSCI_RET_NOT_SUPPORTED; break; - default: - g_assert_not_reached(); } err: -- cgit v1.1 From d59b7cdccc6558f126c3081f7582131029c35660 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 21 Sep 2021 17:28:58 +0100 Subject: target/arm: Fix coding style issues in gdbstub code in helper.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're going to move this code to a different file; fix the coding style first so checkpatch doesn't complain. This includes deleting the spurious 'break' statements after returns in the vfp_gdb_get_reg() function. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20210921162901.17508-3-peter.maydell@linaro.org --- target/arm/helper.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'target') diff --git a/target/arm/helper.c b/target/arm/helper.c index 6274221..84bba9a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -72,9 +72,12 @@ static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) } } switch (reg - nregs) { - case 0: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); break; - case 1: return gdb_get_reg32(buf, vfp_get_fpscr(env)); break; - case 2: return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); break; + case 0: + return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); + case 1: + return gdb_get_reg32(buf, vfp_get_fpscr(env)); + case 2: + return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); } return 0; } @@ -98,9 +101,15 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) } } switch (reg - nregs) { - case 0: env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4; - case 1: vfp_set_fpscr(env, ldl_p(buf)); return 4; - case 2: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4; + case 0: + env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); + return 4; + case 1: + vfp_set_fpscr(env, ldl_p(buf)); + return 4; + case 2: + env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); + return 4; } return 0; } @@ -119,7 +128,7 @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) return gdb_get_reg32(buf, vfp_get_fpsr(env)); case 33: /* FPCR */ - return gdb_get_reg32(buf,vfp_get_fpcr(env)); + return gdb_get_reg32(buf, vfp_get_fpcr(env)); default: return 0; } -- cgit v1.1 From 89f4f20e276e6e5dc08fca5e75e2bfbd92280072 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 21 Sep 2021 17:28:59 +0100 Subject: target/arm: Move gdbstub related code out of helper.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently helper.c includes some code which is part of the arm target's gdbstub support. This code has a better home: in gdbstub.c and gdbstub64.c. Move it there. Because aarch64_fpu_gdb_get_reg() and aarch64_fpu_gdb_set_reg() move into gdbstub64.c, this means that they're now compiled only for TARGET_AARCH64 rather than always. That is the only case when they would ever be used, but it does mean that the ifdef in arm_cpu_register_gdb_regs_for_features() needs to be adjusted to match. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-id: 20210921162901.17508-4-peter.maydell@linaro.org --- target/arm/gdbstub.c | 130 ++++++++++++++++++++++++ target/arm/gdbstub64.c | 140 +++++++++++++++++++++++++ target/arm/helper.c | 271 ------------------------------------------------- target/arm/internals.h | 7 ++ 4 files changed, 277 insertions(+), 271 deletions(-) (limited to 'target') diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index 826601b..cbf156d 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" #include "cpu.h" +#include "internals.h" #include "exec/gdbstub.h" typedef struct RegisterSysregXmlParam { @@ -124,6 +125,98 @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) return 0; } +static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) +{ + ARMCPU *cpu = env_archcpu(env); + int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; + + /* VFP data registers are always little-endian. */ + if (reg < nregs) { + return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg)); + } + if (arm_feature(env, ARM_FEATURE_NEON)) { + /* Aliases for Q regs. */ + nregs += 16; + if (reg < nregs) { + uint64_t *q = aa32_vfp_qreg(env, reg - 32); + return gdb_get_reg128(buf, q[0], q[1]); + } + } + switch (reg - nregs) { + case 0: + return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); + case 1: + return gdb_get_reg32(buf, vfp_get_fpscr(env)); + case 2: + return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); + } + return 0; +} + +static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) +{ + ARMCPU *cpu = env_archcpu(env); + int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; + + if (reg < nregs) { + *aa32_vfp_dreg(env, reg) = ldq_le_p(buf); + return 8; + } + if (arm_feature(env, ARM_FEATURE_NEON)) { + nregs += 16; + if (reg < nregs) { + uint64_t *q = aa32_vfp_qreg(env, reg - 32); + q[0] = ldq_le_p(buf); + q[1] = ldq_le_p(buf + 8); + return 16; + } + } + switch (reg - nregs) { + case 0: + env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); + return 4; + case 1: + vfp_set_fpscr(env, ldl_p(buf)); + return 4; + case 2: + env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); + return 4; + } + return 0; +} + +/** + * arm_get/set_gdb_*: get/set a gdb register + * @env: the CPU state + * @buf: a buffer to copy to/from + * @reg: register number (offset from start of group) + * + * We return the number of bytes copied + */ + +static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) +{ + ARMCPU *cpu = env_archcpu(env); + const ARMCPRegInfo *ri; + uint32_t key; + + key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg]; + ri = get_arm_cp_reginfo(cpu->cp_regs, key); + if (ri) { + if (cpreg_field_is_64bit(ri)) { + return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri)); + } else { + return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri)); + } + } + return 0; +} + +static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) +{ + return 0; +} + static void arm_gen_one_xml_sysreg_tag(GString *s, DynamicGDBXMLInfo *dyn_xml, ARMCPRegInfo *ri, uint32_t ri_key, int bitsize, int regnum) @@ -319,3 +412,40 @@ const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) } return NULL; } + +void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) +{ + CPUState *cs = CPU(cpu); + CPUARMState *env = &cpu->env; + + if (arm_feature(env, ARM_FEATURE_AARCH64)) { + /* + * The lower part of each SVE register aliases to the FPU + * registers so we don't need to include both. + */ +#ifdef TARGET_AARCH64 + if (isar_feature_aa64_sve(&cpu->isar)) { + gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg, + arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs), + "sve-registers.xml", 0); + } else { + gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg, + aarch64_fpu_gdb_set_reg, + 34, "aarch64-fpu.xml", 0); + } +#endif + } else if (arm_feature(env, ARM_FEATURE_NEON)) { + gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, + 51, "arm-neon.xml", 0); + } else if (cpu_isar_feature(aa32_simd_r32, cpu)) { + gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, + 35, "arm-vfp3.xml", 0); + } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) { + gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, + 19, "arm-vfp.xml", 0); + } + gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg, + arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs), + "system-registers.xml", 0); + +} diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index 251539e..5968786 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -17,7 +17,9 @@ * License along with this library; if not, see . */ #include "qemu/osdep.h" +#include "qemu/log.h" #include "cpu.h" +#include "internals.h" #include "exec/gdbstub.h" int aarch64_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) @@ -69,3 +71,141 @@ int aarch64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) /* Unknown register. */ return 0; } + +int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) +{ + switch (reg) { + case 0 ... 31: + { + /* 128 bit FP register - quads are in LE order */ + uint64_t *q = aa64_vfp_qreg(env, reg); + return gdb_get_reg128(buf, q[1], q[0]); + } + case 32: + /* FPSR */ + return gdb_get_reg32(buf, vfp_get_fpsr(env)); + case 33: + /* FPCR */ + return gdb_get_reg32(buf, vfp_get_fpcr(env)); + default: + return 0; + } +} + +int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) +{ + switch (reg) { + case 0 ... 31: + /* 128 bit FP register */ + { + uint64_t *q = aa64_vfp_qreg(env, reg); + q[0] = ldq_le_p(buf); + q[1] = ldq_le_p(buf + 8); + return 16; + } + case 32: + /* FPSR */ + vfp_set_fpsr(env, ldl_p(buf)); + return 4; + case 33: + /* FPCR */ + vfp_set_fpcr(env, ldl_p(buf)); + return 4; + default: + return 0; + } +} + +int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg) +{ + ARMCPU *cpu = env_archcpu(env); + + switch (reg) { + /* The first 32 registers are the zregs */ + case 0 ... 31: + { + int vq, len = 0; + for (vq = 0; vq < cpu->sve_max_vq; vq++) { + len += gdb_get_reg128(buf, + env->vfp.zregs[reg].d[vq * 2 + 1], + env->vfp.zregs[reg].d[vq * 2]); + } + return len; + } + case 32: + return gdb_get_reg32(buf, vfp_get_fpsr(env)); + case 33: + return gdb_get_reg32(buf, vfp_get_fpcr(env)); + /* then 16 predicates and the ffr */ + case 34 ... 50: + { + int preg = reg - 34; + int vq, len = 0; + for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { + len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]); + } + return len; + } + case 51: + { + /* + * We report in Vector Granules (VG) which is 64bit in a Z reg + * while the ZCR works in Vector Quads (VQ) which is 128bit chunks. + */ + int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1; + return gdb_get_reg64(buf, vq * 2); + } + default: + /* gdbstub asked for something out our range */ + qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg); + break; + } + + return 0; +} + +int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg) +{ + ARMCPU *cpu = env_archcpu(env); + + /* The first 32 registers are the zregs */ + switch (reg) { + /* The first 32 registers are the zregs */ + case 0 ... 31: + { + int vq, len = 0; + uint64_t *p = (uint64_t *) buf; + for (vq = 0; vq < cpu->sve_max_vq; vq++) { + env->vfp.zregs[reg].d[vq * 2 + 1] = *p++; + env->vfp.zregs[reg].d[vq * 2] = *p++; + len += 16; + } + return len; + } + case 32: + vfp_set_fpsr(env, *(uint32_t *)buf); + return 4; + case 33: + vfp_set_fpcr(env, *(uint32_t *)buf); + return 4; + case 34 ... 50: + { + int preg = reg - 34; + int vq, len = 0; + uint64_t *p = (uint64_t *) buf; + for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { + env->vfp.pregs[preg].p[vq / 4] = *p++; + len += 8; + } + return len; + } + case 51: + /* cannot set vg via gdbstub */ + return 0; + default: + /* gdbstub asked for something out our range */ + break; + } + + return 0; +} diff --git a/target/arm/helper.c b/target/arm/helper.c index 84bba9a..9b31789 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -12,7 +12,6 @@ #include "trace.h" #include "cpu.h" #include "internals.h" -#include "exec/gdbstub.h" #include "exec/helper-proto.h" #include "qemu/host-utils.h" #include "qemu/main-loop.h" @@ -54,110 +53,6 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, static void switch_mode(CPUARMState *env, int mode); static int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx); -static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) -{ - ARMCPU *cpu = env_archcpu(env); - int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; - - /* VFP data registers are always little-endian. */ - if (reg < nregs) { - return gdb_get_reg64(buf, *aa32_vfp_dreg(env, reg)); - } - if (arm_feature(env, ARM_FEATURE_NEON)) { - /* Aliases for Q regs. */ - nregs += 16; - if (reg < nregs) { - uint64_t *q = aa32_vfp_qreg(env, reg - 32); - return gdb_get_reg128(buf, q[0], q[1]); - } - } - switch (reg - nregs) { - case 0: - return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); - case 1: - return gdb_get_reg32(buf, vfp_get_fpscr(env)); - case 2: - return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); - } - return 0; -} - -static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) -{ - ARMCPU *cpu = env_archcpu(env); - int nregs = cpu_isar_feature(aa32_simd_r32, cpu) ? 32 : 16; - - if (reg < nregs) { - *aa32_vfp_dreg(env, reg) = ldq_le_p(buf); - return 8; - } - if (arm_feature(env, ARM_FEATURE_NEON)) { - nregs += 16; - if (reg < nregs) { - uint64_t *q = aa32_vfp_qreg(env, reg - 32); - q[0] = ldq_le_p(buf); - q[1] = ldq_le_p(buf + 8); - return 16; - } - } - switch (reg - nregs) { - case 0: - env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); - return 4; - case 1: - vfp_set_fpscr(env, ldl_p(buf)); - return 4; - case 2: - env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); - return 4; - } - return 0; -} - -static int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) -{ - switch (reg) { - case 0 ... 31: - { - /* 128 bit FP register - quads are in LE order */ - uint64_t *q = aa64_vfp_qreg(env, reg); - return gdb_get_reg128(buf, q[1], q[0]); - } - case 32: - /* FPSR */ - return gdb_get_reg32(buf, vfp_get_fpsr(env)); - case 33: - /* FPCR */ - return gdb_get_reg32(buf, vfp_get_fpcr(env)); - default: - return 0; - } -} - -static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) -{ - switch (reg) { - case 0 ... 31: - /* 128 bit FP register */ - { - uint64_t *q = aa64_vfp_qreg(env, reg); - q[0] = ldq_le_p(buf); - q[1] = ldq_le_p(buf + 8); - return 16; - } - case 32: - /* FPSR */ - vfp_set_fpsr(env, ldl_p(buf)); - return 4; - case 33: - /* FPCR */ - vfp_set_fpcr(env, ldl_p(buf)); - return 4; - default: - return 0; - } -} - static uint64_t raw_read(CPUARMState *env, const ARMCPRegInfo *ri) { assert(ri->fieldoffset); @@ -217,134 +112,6 @@ static void write_raw_cp_reg(CPUARMState *env, const ARMCPRegInfo *ri, } } -/** - * arm_get/set_gdb_*: get/set a gdb register - * @env: the CPU state - * @buf: a buffer to copy to/from - * @reg: register number (offset from start of group) - * - * We return the number of bytes copied - */ - -static int arm_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) -{ - ARMCPU *cpu = env_archcpu(env); - const ARMCPRegInfo *ri; - uint32_t key; - - key = cpu->dyn_sysreg_xml.data.cpregs.keys[reg]; - ri = get_arm_cp_reginfo(cpu->cp_regs, key); - if (ri) { - if (cpreg_field_is_64bit(ri)) { - return gdb_get_reg64(buf, (uint64_t)read_raw_cp_reg(env, ri)); - } else { - return gdb_get_reg32(buf, (uint32_t)read_raw_cp_reg(env, ri)); - } - } - return 0; -} - -static int arm_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) -{ - return 0; -} - -#ifdef TARGET_AARCH64 -static int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg) -{ - ARMCPU *cpu = env_archcpu(env); - - switch (reg) { - /* The first 32 registers are the zregs */ - case 0 ... 31: - { - int vq, len = 0; - for (vq = 0; vq < cpu->sve_max_vq; vq++) { - len += gdb_get_reg128(buf, - env->vfp.zregs[reg].d[vq * 2 + 1], - env->vfp.zregs[reg].d[vq * 2]); - } - return len; - } - case 32: - return gdb_get_reg32(buf, vfp_get_fpsr(env)); - case 33: - return gdb_get_reg32(buf, vfp_get_fpcr(env)); - /* then 16 predicates and the ffr */ - case 34 ... 50: - { - int preg = reg - 34; - int vq, len = 0; - for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { - len += gdb_get_reg64(buf, env->vfp.pregs[preg].p[vq / 4]); - } - return len; - } - case 51: - { - /* - * We report in Vector Granules (VG) which is 64bit in a Z reg - * while the ZCR works in Vector Quads (VQ) which is 128bit chunks. - */ - int vq = sve_zcr_len_for_el(env, arm_current_el(env)) + 1; - return gdb_get_reg64(buf, vq * 2); - } - default: - /* gdbstub asked for something out our range */ - qemu_log_mask(LOG_UNIMP, "%s: out of range register %d", __func__, reg); - break; - } - - return 0; -} - -static int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg) -{ - ARMCPU *cpu = env_archcpu(env); - - /* The first 32 registers are the zregs */ - switch (reg) { - /* The first 32 registers are the zregs */ - case 0 ... 31: - { - int vq, len = 0; - uint64_t *p = (uint64_t *) buf; - for (vq = 0; vq < cpu->sve_max_vq; vq++) { - env->vfp.zregs[reg].d[vq * 2 + 1] = *p++; - env->vfp.zregs[reg].d[vq * 2] = *p++; - len += 16; - } - return len; - } - case 32: - vfp_set_fpsr(env, *(uint32_t *)buf); - return 4; - case 33: - vfp_set_fpcr(env, *(uint32_t *)buf); - return 4; - case 34 ... 50: - { - int preg = reg - 34; - int vq, len = 0; - uint64_t *p = (uint64_t *) buf; - for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) { - env->vfp.pregs[preg].p[vq / 4] = *p++; - len += 8; - } - return len; - } - case 51: - /* cannot set vg via gdbstub */ - return 0; - default: - /* gdbstub asked for something out our range */ - break; - } - - return 0; -} -#endif /* TARGET_AARCH64 */ - static bool raw_accessors_invalid(const ARMCPRegInfo *ri) { /* Return true if the regdef would cause an assertion if you called @@ -8667,44 +8434,6 @@ void register_cp_regs_for_features(ARMCPU *cpu) #endif } -void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) -{ - CPUState *cs = CPU(cpu); - CPUARMState *env = &cpu->env; - - if (arm_feature(env, ARM_FEATURE_AARCH64)) { - /* - * The lower part of each SVE register aliases to the FPU - * registers so we don't need to include both. - */ -#ifdef TARGET_AARCH64 - if (isar_feature_aa64_sve(&cpu->isar)) { - gdb_register_coprocessor(cs, arm_gdb_get_svereg, arm_gdb_set_svereg, - arm_gen_dynamic_svereg_xml(cs, cs->gdb_num_regs), - "sve-registers.xml", 0); - } else -#endif - { - gdb_register_coprocessor(cs, aarch64_fpu_gdb_get_reg, - aarch64_fpu_gdb_set_reg, - 34, "aarch64-fpu.xml", 0); - } - } else if (arm_feature(env, ARM_FEATURE_NEON)) { - gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, - 51, "arm-neon.xml", 0); - } else if (cpu_isar_feature(aa32_simd_r32, cpu)) { - gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, - 35, "arm-vfp3.xml", 0); - } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) { - gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, - 19, "arm-vfp.xml", 0); - } - gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg, - arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs), - "system-registers.xml", 0); - -} - /* Sort alphabetically by type name, except for "any". */ static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b) { diff --git a/target/arm/internals.h b/target/arm/internals.h index 9fbb364..3612107 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1270,4 +1270,11 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env) return (1 << 31) | ((1 << pmu_num_counters(env)) - 1); } +#ifdef TARGET_AARCH64 +int arm_gdb_get_svereg(CPUARMState *env, GByteArray *buf, int reg); +int arm_gdb_set_svereg(CPUARMState *env, uint8_t *buf, int reg); +int aarch64_fpu_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg); +int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg); +#endif + #endif -- cgit v1.1 From b355f08a3724d3f29e1c177dde3a01b649108f98 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 21 Sep 2021 17:29:00 +0100 Subject: target/arm: Don't put FPEXC and FPSID in org.gnu.gdb.arm.vfp XML Currently we send VFP XML which includes D0..D15 or D0..D31, plus FPSID, FPSCR and FPEXC. The upstream GDB tolerates this, but its definition of this XML feature does not include FPSID or FPEXC. In particular, for M-profile cores there are no FPSID or FPEXC registers, so advertising those is wrong. Move FPSID and FPEXC into their own bit of XML which we only send for A and R profile cores. This brings our definition of the XML org.gnu.gdb.arm.vfp feature into line with GDB's own (at least for non-Neon cores...) and means we don't claim to have FPSID and FPEXC on M-profile. (It seems unlikely to me that any gdbstub users really care about being able to look at FPEXC and FPSID; but we've supplied them to gdb for a decade and it's not hard to keep doing so.) Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20210921162901.17508-5-peter.maydell@linaro.org --- target/arm/gdbstub.c | 56 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'target') diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c index cbf156d..e0dcb33 100644 --- a/target/arm/gdbstub.c +++ b/target/arm/gdbstub.c @@ -144,11 +144,7 @@ static int vfp_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg) } switch (reg - nregs) { case 0: - return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); - case 1: return gdb_get_reg32(buf, vfp_get_fpscr(env)); - case 2: - return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); } return 0; } @@ -173,12 +169,30 @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg) } switch (reg - nregs) { case 0: - env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); + vfp_set_fpscr(env, ldl_p(buf)); return 4; + } + return 0; +} + +static int vfp_gdb_get_sysreg(CPUARMState *env, GByteArray *buf, int reg) +{ + switch (reg) { + case 0: + return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPSID]); case 1: - vfp_set_fpscr(env, ldl_p(buf)); + return gdb_get_reg32(buf, env->vfp.xregs[ARM_VFP_FPEXC]); + } + return 0; +} + +static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg) +{ + switch (reg) { + case 0: + env->vfp.xregs[ARM_VFP_FPSID] = ldl_p(buf); return 4; - case 2: + case 1: env->vfp.xregs[ARM_VFP_FPEXC] = ldl_p(buf) & (1 << 30); return 4; } @@ -434,15 +448,25 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu) 34, "aarch64-fpu.xml", 0); } #endif - } else if (arm_feature(env, ARM_FEATURE_NEON)) { - gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, - 51, "arm-neon.xml", 0); - } else if (cpu_isar_feature(aa32_simd_r32, cpu)) { - gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, - 35, "arm-vfp3.xml", 0); - } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) { - gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, - 19, "arm-vfp.xml", 0); + } else { + if (arm_feature(env, ARM_FEATURE_NEON)) { + gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, + 49, "arm-neon.xml", 0); + } else if (cpu_isar_feature(aa32_simd_r32, cpu)) { + gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, + 33, "arm-vfp3.xml", 0); + } else if (cpu_isar_feature(aa32_vfp_simd, cpu)) { + gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg, + 17, "arm-vfp.xml", 0); + } + if (!arm_feature(env, ARM_FEATURE_M)) { + /* + * A and R profile have FP sysregs FPEXC and FPSID that we + * expose to gdb. + */ + gdb_register_coprocessor(cs, vfp_gdb_get_sysreg, vfp_gdb_set_sysreg, + 2, "arm-vfp-sysregs.xml", 0); + } } gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg, arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs), -- cgit v1.1