@@ -13,27 +13,17 @@
#ifndef RISU_REGINFO_AARCH64_H
#define RISU_REGINFO_AARCH64_H
-#include <signal.h> /* for SVE_MAGIC */
-
-struct simd_reginfo {
- __uint128_t vregs[32];
- char end[0];
-};
-
-struct sve_reginfo {
- /* SVE */
- uint16_t vl; /* current VL */
- __uint128_t zregs[SVE_NUM_ZREGS][SVE_VQ_MAX];
- uint16_t pregs[SVE_NUM_PREGS][SVE_VQ_MAX];
- uint16_t ffr[SVE_VQ_MAX];
- char end[0];
-};
+#include <signal.h>
/* The kernel headers set this based on future arch extensions.
The current arch maximum is 16. Save space below. */
#undef SVE_VQ_MAX
#define SVE_VQ_MAX 16
+#define ROUND_UP(SIZE, POW2) (((SIZE) + (POW2) - 1) & -(POW2))
+#define RISU_SVE_REGS_SIZE(VQ) ROUND_UP(SVE_SIG_REGS_SIZE(VQ), 16)
+#define RISU_SIMD_REGS_SIZE (32 * 16)
+
struct reginfo {
uint64_t fault_address;
uint64_t regs[31];
@@ -45,11 +35,28 @@ struct reginfo {
/* FP/SIMD */
uint32_t fpsr;
uint32_t fpcr;
+ uint16_t sve_vl;
+ uint16_t reserved;
- union {
- struct simd_reginfo simd;
- struct sve_reginfo sve;
- };
+ char extra[RISU_SVE_REGS_SIZE(SVE_VQ_MAX)]
+ __attribute__((aligned(16)));
};
+static inline uint64_t *reginfo_vreg(struct reginfo *ri, int i)
+{
+ return (uint64_t *)&ri->extra[i * 16];
+}
+
+static inline uint64_t *reginfo_zreg(struct reginfo *ri, int vq, int i)
+{
+ return (uint64_t *)&ri->extra[SVE_SIG_ZREG_OFFSET(vq, i) -
+ SVE_SIG_REGS_OFFSET];
+}
+
+static inline uint16_t *reginfo_preg(struct reginfo *ri, int vq, int i)
+{
+ return (uint16_t *)&ri->extra[SVE_SIG_PREG_OFFSET(vq, i) -
+ SVE_SIG_REGS_OFFSET];
+}
+
#endif /* RISU_REGINFO_AARCH64_H */
@@ -61,9 +61,13 @@ void process_arch_opt(int opt, const char *arg)
int reginfo_size(struct reginfo *ri)
{
- int size = offsetof(struct reginfo, simd.end);
- if (test_sve) {
- size = offsetof(struct reginfo, sve.end);
+ int size = offsetof(struct reginfo, extra);
+
+ if (ri->sve_vl) {
+ int vq = sve_vq_from_vl(ri->sve_vl);
+ size += RISU_SVE_REGS_SIZE(vq);
+ } else {
+ size += RISU_SIMD_REGS_SIZE;
}
return size;
}
@@ -128,6 +132,7 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
fprintf(stderr, "risu_reginfo_aarch64: failed to get SVE state\n");
return;
}
+
if (sve->vl != sve_vl_from_vq(vq)) {
fprintf(stderr, "risu_reginfo_aarch64: "
"unexpected SVE state: %d != %d\n",
@@ -135,42 +140,22 @@ void reginfo_init(struct reginfo *ri, ucontext_t *uc)
return;
}
- ri->sve.vl = sve->vl;
-
- if (sve->head.size < SVE_SIG_CONTEXT_SIZE(vq)) {
- if (sve->head.size == sizeof(*sve)) {
- /* SVE state is empty -- not an error. */
- } else {
- fprintf(stderr, "risu_reginfo_aarch64: "
- "failed to get complete SVE state\n");
- }
+ if (sve->head.size <= SVE_SIG_CONTEXT_SIZE(0)) {
+ /* Only AdvSIMD state is present. */
+ } else if (sve->head.size < SVE_SIG_CONTEXT_SIZE(vq)) {
+ fprintf(stderr, "risu_reginfo_aarch64: "
+ "failed to get complete SVE state\n");
+ return;
+ } else {
+ ri->sve_vl = sve->vl;
+ memcpy(reginfo_zreg(ri, vq, 0),
+ (char *)sve + SVE_SIG_REGS_OFFSET,
+ SVE_SIG_REGS_SIZE(vq));
return;
}
-
- /* Copy ZREG's one at a time */
- for (i = 0; i < SVE_NUM_ZREGS; i++) {
- memcpy(&ri->sve.zregs[i],
- (void *)sve + SVE_SIG_ZREG_OFFSET(vq, i),
- SVE_SIG_ZREG_SIZE(vq));
- }
-
- /* Copy PREG's one at a time */
- for (i = 0; i < SVE_NUM_PREGS; i++) {
- memcpy(&ri->sve.pregs[i],
- (void *)sve + SVE_SIG_PREG_OFFSET(vq, i),
- SVE_SIG_PREG_SIZE(vq));
- }
-
- /* Finally the FFR */
- memcpy(&ri->sve.ffr, (void *)sve + SVE_SIG_FFR_OFFSET(vq),
- SVE_SIG_FFR_SIZE(vq));
-
- return;
}
- for (i = 0; i < 32; i++) {
- ri->simd.vregs[i] = fp->vregs[i];
- }
+ memcpy(reginfo_vreg(ri, 0), fp->vregs, RISU_SIMD_REGS_SIZE);
}
/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
@@ -206,18 +191,20 @@ static void sve_dump_preg_diff(FILE *f, int vq, const uint16_t *p1,
fprintf(f, "\n");
}
-static void sve_dump_zreg_diff(FILE *f, int vq, const __uint128_t *z1,
- const __uint128_t *z2)
+static void sve_dump_zreg_diff(FILE *f, int vq, const uint64_t *za,
+ const uint64_t *zb)
{
const char *pad = "";
int q;
for (q = 0; q < vq; ++q) {
- if (z1[q] != z2[q]) {
+ uint64_t za0 = za[2 * q], za1 = za[2 * q + 1];
+ uint64_t zb0 = zb[2 * q], zb1 = zb[2 * q + 1];
+
+ if (za0 != zb0 || za1 != zb1) {
fprintf(f, "%sq%-2d: %016" PRIx64 "%016" PRIx64
- " vs %016" PRIx64 "%016" PRIx64"\n", pad, q,
- (uint64_t)(z1[q] >> 64), (uint64_t)z1[q],
- (uint64_t)(z2[q] >> 64), (uint64_t)z2[q]);
+ " vs %016" PRIx64 "%016" PRIx64"\n",
+ pad, q, za1, za0, zb1, zb0);
pad = " ";
}
}
@@ -239,38 +226,41 @@ int reginfo_dump(struct reginfo *ri, FILE * f)
fprintf(f, " fpsr : %08x\n", ri->fpsr);
fprintf(f, " fpcr : %08x\n", ri->fpcr);
- if (test_sve) {
- int q, vq = test_sve;
+ if (ri->sve_vl) {
+ int vq = sve_vq_from_vl(ri->sve_vl);
+ int q;
- fprintf(f, " vl : %d\n", ri->sve.vl);
+ fprintf(f, " vl : %d\n", ri->sve_vl);
- for (i = 0; i < 32; i++) {
- fprintf(f, " Z%-2d q%-2d: %016" PRIx64 "%016" PRIx64 "\n", i, 0,
- (uint64_t)(ri->sve.zregs[i][0] >> 64),
- (uint64_t)ri->sve.zregs[i][0]);
+ for (i = 0; i < SVE_NUM_ZREGS; i++) {
+ uint64_t *z = reginfo_zreg(ri, vq, i);
+
+ fprintf(f, " Z%-2d q%-2d: %016" PRIx64 "%016" PRIx64 "\n",
+ i, 0, z[1], z[0]);
for (q = 1; q < vq; ++q) {
- fprintf(f, " q%-2d: %016" PRIx64 "%016" PRIx64 "\n", q,
- (uint64_t)(ri->sve.zregs[i][q] >> 64),
- (uint64_t)ri->sve.zregs[i][q]);
+ fprintf(f, " q%-2d: %016" PRIx64 "%016" PRIx64 "\n",
+ q, z[q * 2 + 1], z[q * 2]);
}
}
- for (i = 0; i < 16; i++) {
- fprintf(f, " P%-2d : ", i);
- sve_dump_preg(f, vq, &ri->sve.pregs[i][0]);
+ for (i = 0; i < SVE_NUM_PREGS + 1; i++) {
+ uint16_t *p = reginfo_preg(ri, vq, i);
+
+ if (i == SVE_NUM_PREGS) {
+ fprintf(f, " FFR : ");
+ } else {
+ fprintf(f, " P%-2d : ", i);
+ }
+ sve_dump_preg(f, vq, p);
fprintf(f, "\n");
}
- fprintf(f, " FFR : ");
- sve_dump_preg(f, vq, &ri->sve.ffr[0]);
- fprintf(f, "\n");
-
return !ferror(f);
}
for (i = 0; i < 32; i++) {
- fprintf(f, " V%-2d : %016" PRIx64 "%016" PRIx64 "\n", i,
- (uint64_t) (ri->simd.vregs[i] >> 64),
- (uint64_t) (ri->simd.vregs[i]));
+ uint64_t *v = reginfo_vreg(ri, i);
+ fprintf(f, " V%-2d : %016" PRIx64 "%016" PRIx64 "\n",
+ i, v[1], v[0]);
}
return !ferror(f);
@@ -314,44 +304,47 @@ int reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
fprintf(f, " fpcr : %08x vs %08x\n", m->fpcr, a->fpcr);
}
- if (test_sve) {
- int vq = sve_vq_from_vl(m->sve.vl);
+ if (m->sve_vl != a->sve_vl) {
+ fprintf(f, " vl : %d vs %d\n", m->sve_vl, a->sve_vl);
+ }
- if (m->sve.vl != a->sve.vl) {
- fprintf(f, " vl : %d vs %d\n", m->sve.vl, a->sve.vl);
- }
+ if (m->sve_vl) {
+ int vq = sve_vq_from_vl(m->sve_vl);
for (i = 0; i < SVE_NUM_ZREGS; i++) {
- if (!sve_zreg_is_eq(vq, &m->sve.zregs[i], &a->sve.zregs[i])) {
- fprintf(f, " Z%-2d ", i);
- sve_dump_zreg_diff(f, vq, &m->sve.zregs[i][0],
- &a->sve.zregs[i][0]);
- }
- }
- for (i = 0; i < SVE_NUM_PREGS; i++) {
- if (!sve_preg_is_eq(vq, &m->sve.pregs[i], &a->sve.pregs[i])) {
- fprintf(f, " P%-2d : ", i);
- sve_dump_preg_diff(f, vq, &m->sve.pregs[i][0],
- &a->sve.pregs[i][0]);
- }
- }
- if (!sve_preg_is_eq(vq, &m->sve.ffr, &a->sve.ffr)) {
- fprintf(f, " FFR : ");
- sve_dump_preg_diff(f, vq, &m->sve.pregs[i][0], &a->sve.pregs[i][0]);
- }
+ uint64_t *zm = reginfo_zreg(m, vq, i);
+ uint64_t *za = reginfo_zreg(a, vq, i);
+ if (!sve_zreg_is_eq(vq, zm, za)) {
+ fprintf(f, " Z%-2d ", i);
+ sve_dump_zreg_diff(f, vq, zm, za);
+ }
+ }
+ for (i = 0; i < SVE_NUM_PREGS + 1; i++) {
+ uint16_t *pm = reginfo_preg(m, vq, i);
+ uint16_t *pa = reginfo_preg(a, vq, i);
+
+ if (!sve_preg_is_eq(vq, pm, pa)) {
+ if (i == SVE_NUM_PREGS) {
+ fprintf(f, " FFR : ");
+ } else {
+ fprintf(f, " P%-2d : ", i);
+ }
+ sve_dump_preg_diff(f, vq, pm, pa);
+ }
+ }
return !ferror(f);
}
for (i = 0; i < 32; i++) {
- if (m->simd.vregs[i] != a->simd.vregs[i]) {
+ uint64_t *mv = reginfo_vreg(m, i);
+ uint64_t *av = reginfo_vreg(a, i);
+
+ if (mv[0] != av[0] || mv[1] != av[1]) {
fprintf(f, " V%-2d : "
"%016" PRIx64 "%016" PRIx64 " vs "
- "%016" PRIx64 "%016" PRIx64 "\n", i,
- (uint64_t) (m->simd.vregs[i] >> 64),
- (uint64_t) m->simd.vregs[i],
- (uint64_t) (a->simd.vregs[i] >> 64),
- (uint64_t) a->simd.vregs[i]);
+ "%016" PRIx64 "%016" PRIx64 "\n",
+ i, mv[1], mv[0], av[1], av[0]);
}
}
Mirror the signal frame by storing all of the registers as a lump. Use the signal macros to pull out the values. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- risu_reginfo_aarch64.h | 45 ++++++----- risu_reginfo_aarch64.c | 171 ++++++++++++++++++++--------------------- 2 files changed, 108 insertions(+), 108 deletions(-)