* [PATCH 1/3] target/arm: Avoid splitting Zregs across lines in dump
2023-02-28 0:37 [PATCH 0/3] target/arm: dump and gdbstub support for ZA[] Richard Henderson
@ 2023-02-28 0:37 ` Richard Henderson
2023-03-06 12:35 ` Peter Maydell
2023-02-28 0:37 ` [PATCH 2/3] target/arm: Dump ZA[] when active Richard Henderson
2023-02-28 0:37 ` [PATCH 3/3] target/arm: Support reading ZA[] from gdbstub Richard Henderson
2 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2023-02-28 0:37 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Allow the line length to extend to 548 columns. While annoyingly wide,
it's still less confusing than the continuations we print. Also, the
default VL used by Linux (and max for A64FX) uses only 140 columns.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.c | 36 ++++++++++++++----------------------
1 file changed, 14 insertions(+), 22 deletions(-)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 5182ed0c91..f1f454e7a0 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -953,7 +953,7 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
ARMCPU *cpu = ARM_CPU(cs);
CPUARMState *env = &cpu->env;
uint32_t psr = pstate_read(env);
- int i;
+ int i, j;
int el = arm_current_el(env);
const char *ns_status;
bool sve;
@@ -1012,7 +1012,7 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
if (sve) {
- int j, zcr_len = sve_vqm1_for_el(env, el);
+ int zcr_len = sve_vqm1_for_el(env, el);
for (i = 0; i <= FFR_PRED_NUM; i++) {
bool eol;
@@ -1052,32 +1052,24 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
}
- for (i = 0; i < 32; i++) {
- if (zcr_len == 0) {
+ if (zcr_len == 0) {
+ /*
+ * With vl=16, there are only 37 columns per register,
+ * so output two registers per line.
+ */
+ for (i = 0; i < 32; i++) {
qemu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 "%s",
i, env->vfp.zregs[i].d[1],
env->vfp.zregs[i].d[0], i & 1 ? "\n" : " ");
- } else if (zcr_len == 1) {
- qemu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64
- ":%016" PRIx64 ":%016" PRIx64 "\n",
- i, env->vfp.zregs[i].d[3], env->vfp.zregs[i].d[2],
- env->vfp.zregs[i].d[1], env->vfp.zregs[i].d[0]);
- } else {
+ }
+ } else {
+ for (i = 0; i < 32; i++) {
+ qemu_fprintf(f, "Z%02d=", i);
for (j = zcr_len; j >= 0; j--) {
- bool odd = (zcr_len - j) % 2 != 0;
- if (j == zcr_len) {
- qemu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1);
- } else if (!odd) {
- if (j > 0) {
- qemu_fprintf(f, " [%x-%x]=", j, j - 1);
- } else {
- qemu_fprintf(f, " [%x]=", j);
- }
- }
qemu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%s",
env->vfp.zregs[i].d[j * 2 + 1],
- env->vfp.zregs[i].d[j * 2],
- odd || j == 0 ? "\n" : ":");
+ env->vfp.zregs[i].d[j * 2 + 0],
+ j ? ":" : "\n");
}
}
}
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/3] target/arm: Dump ZA[] when active
2023-02-28 0:37 [PATCH 0/3] target/arm: dump and gdbstub support for ZA[] Richard Henderson
2023-02-28 0:37 ` [PATCH 1/3] target/arm: Avoid splitting Zregs across lines in dump Richard Henderson
@ 2023-02-28 0:37 ` Richard Henderson
2023-03-06 12:36 ` Peter Maydell
2023-02-28 0:37 ` [PATCH 3/3] target/arm: Support reading ZA[] from gdbstub Richard Henderson
2 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2023-02-28 0:37 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Always print each matrix row whole, one per line, so that we
get the entire matrix in the proper shape.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index f1f454e7a0..0e54e19b05 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -1080,6 +1080,24 @@ static void aarch64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
i, q[1], q[0], (i & 1 ? "\n" : " "));
}
}
+
+ if (cpu_isar_feature(aa64_sme, cpu) &&
+ FIELD_EX64(env->svcr, SVCR, ZA) &&
+ sme_exception_el(env, el) == 0) {
+ int zcr_len = sve_vqm1_for_el_sm(env, el, true);
+ int svl = (zcr_len + 1) * 16;
+ int svl_lg10 = svl < 100 ? 2 : 3;
+
+ for (i = 0; i < svl; i++) {
+ qemu_fprintf(f, "ZA[%0*d]=", svl_lg10, i);
+ for (j = zcr_len; j >= 0; --j) {
+ qemu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%c",
+ env->zarray[i].d[2 * j + 1],
+ env->zarray[i].d[2 * j],
+ j ? ':' : '\n');
+ }
+ }
+ }
}
#else
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/3] target/arm: Support reading ZA[] from gdbstub
2023-02-28 0:37 [PATCH 0/3] target/arm: dump and gdbstub support for ZA[] Richard Henderson
2023-02-28 0:37 ` [PATCH 1/3] target/arm: Avoid splitting Zregs across lines in dump Richard Henderson
2023-02-28 0:37 ` [PATCH 2/3] target/arm: Dump ZA[] when active Richard Henderson
@ 2023-02-28 0:37 ` Richard Henderson
2023-03-06 11:06 ` Peter Maydell
2 siblings, 1 reply; 8+ messages in thread
From: Richard Henderson @ 2023-02-28 0:37 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-arm
Mirror the existing support for SVE.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 1 +
target/arm/internals.h | 3 ++
target/arm/gdbstub.c | 8 ++++
target/arm/gdbstub64.c | 88 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 6e97a256fb..9971280577 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -869,6 +869,7 @@ struct ArchCPU {
DynamicGDBXMLInfo dyn_sysreg_xml;
DynamicGDBXMLInfo dyn_svereg_xml;
+ DynamicGDBXMLInfo dyn_zareg_xml;
DynamicGDBXMLInfo dyn_m_systemreg_xml;
DynamicGDBXMLInfo dyn_m_secextreg_xml;
diff --git a/target/arm/internals.h b/target/arm/internals.h
index a03748aa10..a27e5b3f28 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1343,12 +1343,15 @@ static inline uint64_t pmu_counter_mask(CPUARMState *env)
#ifdef TARGET_AARCH64
int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg);
+int arm_gen_dynamic_zareg_xml(CPUState *cpu, int base_reg);
int aarch64_gdb_get_sve_reg(CPUARMState *env, GByteArray *buf, int reg);
int aarch64_gdb_set_sve_reg(CPUARMState *env, uint8_t *buf, int reg);
int aarch64_gdb_get_fpu_reg(CPUARMState *env, GByteArray *buf, int reg);
int aarch64_gdb_set_fpu_reg(CPUARMState *env, uint8_t *buf, int reg);
int aarch64_gdb_get_pauth_reg(CPUARMState *env, GByteArray *buf, int reg);
int aarch64_gdb_set_pauth_reg(CPUARMState *env, uint8_t *buf, int reg);
+int aarch64_gdb_get_za_reg(CPUARMState *env, GByteArray *buf, int reg);
+int aarch64_gdb_set_za_reg(CPUARMState *env, uint8_t *buf, int reg);
void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp);
void arm_cpu_sme_finalize(ARMCPU *cpu, Error **errp);
void arm_cpu_pauth_finalize(ARMCPU *cpu, Error **errp);
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 3f799f5d05..60a9ade732 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -488,6 +488,8 @@ const char *arm_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
return cpu->dyn_sysreg_xml.desc;
} else if (strcmp(xmlname, "sve-registers.xml") == 0) {
return cpu->dyn_svereg_xml.desc;
+ } else if (strcmp(xmlname, "za-registers.xml") == 0) {
+ return cpu->dyn_zareg_xml.desc;
} else if (strcmp(xmlname, "arm-m-system.xml") == 0) {
return cpu->dyn_m_systemreg_xml.desc;
#ifndef CONFIG_USER_ONLY
@@ -524,6 +526,12 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
aarch64_gdb_set_pauth_reg,
4, "aarch64-pauth.xml", 0);
}
+ if (cpu_isar_feature(aa64_sme, cpu)) {
+ int nreg = arm_gen_dynamic_zareg_xml(cs, cs->gdb_num_regs);
+ gdb_register_coprocessor(cs, aarch64_gdb_get_za_reg,
+ aarch64_gdb_set_za_reg, nreg,
+ "za-registers.xml", 0);
+ }
#endif
} else {
if (arm_feature(env, ARM_FEATURE_NEON)) {
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c
index 3bee892fb7..9210d12c4e 100644
--- a/target/arm/gdbstub64.c
+++ b/target/arm/gdbstub64.c
@@ -244,6 +244,61 @@ int aarch64_gdb_set_pauth_reg(CPUARMState *env, uint8_t *buf, int reg)
return 0;
}
+static int max_svq(ARMCPU *cpu)
+{
+ return 32 - clz32(cpu->sme_vq.map);
+}
+
+int aarch64_gdb_get_za_reg(CPUARMState *env, GByteArray *buf, int reg)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ int max_vq = max_svq(cpu);
+ int cur_vq = EX_TBFLAG_A64(env->hflags, SVL) + 1;
+ int i;
+
+ if (reg >= max_vq * 16) {
+ return 0;
+ }
+
+ /* If ZA is unset, or reg out of range, the contents are zero. */
+ if (FIELD_EX64(env->svcr, SVCR, ZA) && reg < cur_vq * 16) {
+ for (i = 0; i < cur_vq; i++) {
+ gdb_get_reg128(buf, env->zarray[reg].d[i * 2 + 1],
+ env->zarray[reg].d[i * 2]);
+ }
+ } else {
+ cur_vq = 0;
+ }
+
+ for (i = cur_vq; i < max_vq; i++) {
+ gdb_get_reg128(buf, 0, 0);
+ }
+
+ return max_vq * 16;
+}
+
+int aarch64_gdb_set_za_reg(CPUARMState *env, uint8_t *buf, int reg)
+{
+ ARMCPU *cpu = env_archcpu(env);
+ uint64_t *p = (uint64_t *) buf;
+ int max_vq = max_svq(cpu);
+ int cur_vq = EX_TBFLAG_A64(env->hflags, SVL) + 1;
+ int i;
+
+ if (reg >= max_vq * 16) {
+ return 0;
+ }
+
+ /* If ZA is unset, or reg out of range, the contents are zero. */
+ if (FIELD_EX64(env->svcr, SVCR, ZA) && reg < cur_vq * 16) {
+ for (i = 0; i < cur_vq; i++) {
+ env->zarray[reg].d[i * 2 + 1] = *p++;
+ env->zarray[reg].d[i * 2 + 0] = *p++;
+ }
+ }
+ return max_vq * 16;
+}
+
static void output_vector_union_type(GString *s, int reg_width,
const char *name)
{
@@ -376,3 +431,36 @@ int arm_gen_dynamic_svereg_xml(CPUState *cs, int orig_base_reg)
info->num = base_reg - orig_base_reg;
return info->num;
}
+
+/*
+ * Generate the xml for SME, with matrix size set to the maximum
+ * for the cpu. Returns the number of registers generated.
+ */
+int arm_gen_dynamic_zareg_xml(CPUState *cs, int base_reg)
+{
+ ARMCPU *cpu = ARM_CPU(cs);
+ GString *s = g_string_new(NULL);
+ int vq = max_svq(cpu);
+ int row_count = vq * 16;
+ int row_width = vq * 128;
+ int i;
+
+ g_string_printf(s, "<?xml version=\"1.0\"?>");
+ g_string_append_printf(s, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
+ g_string_append_printf(s, "<feature name=\"org.gnu.qemu.aarch64.za\">");
+
+ output_vector_union_type(s, row_width, "zav");
+
+ for (i = 0; i < row_count; i++) {
+ g_string_append_printf(s,
+ "<reg name=\"za%d\" bitsize=\"%d\""
+ " regnum=\"%d\" type=\"zav\"/>",
+ i, row_width, base_reg + i);
+ }
+
+ g_string_append_printf(s, "</feature>");
+
+ cpu->dyn_zareg_xml.num = row_count;
+ cpu->dyn_zareg_xml.desc = g_string_free(s, false);
+ return row_count;
+}
--
2.34.1
^ permalink raw reply related [flat|nested] 8+ messages in thread