From 688c18e9c29ea5c6b7bc4c316ff6d173c6c90bbe Mon Sep 17 00:00:00 2001 From: Assad Hashmi Date: Mon, 1 Apr 2024 22:18:08 +0000 Subject: [PATCH] Remove SVE helper macros already available in kernel header. Update VQ/vq, VL/vl and sve_vq_from_vl() to make them more descriptive and readable. Add comment describing rationale of using quadwords. --- core/unix/include/sigcontext.h | 71 ++------------------------------ core/unix/signal_linux_aarch64.c | 51 +++++++++++++---------- 2 files changed, 33 insertions(+), 89 deletions(-) diff --git a/core/unix/include/sigcontext.h b/core/unix/include/sigcontext.h index b54f9b1fb28..82ad8f1c5cc 100644 --- a/core/unix/include/sigcontext.h +++ b/core/unix/include/sigcontext.h @@ -434,74 +434,9 @@ struct esr_context { # endif -/* SVE helper macros. */ -# define __SVE_VQ_BYTES 16 /* number of bytes per quadword */ - -# define __SVE_VQ_MIN 1 -# define __SVE_VQ_MAX 512 - -# define __SVE_VL_MIN (__SVE_VQ_MIN * __SVE_VQ_BYTES) -# define __SVE_VL_MAX (__SVE_VQ_MAX * __SVE_VQ_BYTES) - -# define __SVE_NUM_ZREGS 32 -# define __SVE_NUM_PREGS 16 - -# define __sve_vl_valid(vl) \ - ((vl) % __SVE_VQ_BYTES == 0 && (vl) >= __SVE_VL_MIN && (vl) <= __SVE_VL_MAX) - -# define __sve_vq_from_vl(vl) ((vl) / __SVE_VQ_BYTES) - -# define __SVE_PREG_SIZE(vq) ((__u32)(vq) * (__SVE_VQ_BYTES / 8)) -# define __SVE_FFR_SIZE(vq) __SVE_PREG_SIZE(vq) - -# define __SVE_ZREGS_OFFSET 0 -# define __SVE_ZREG_OFFSET(vq, n) (__SVE_ZREGS_OFFSET + __SVE_ZREG_SIZE(vq) * (n)) -# define __SVE_ZREGS_SIZE(vq) \ - (__SVE_ZREG_OFFSET(vq, __SVE_NUM_ZREGS) - __SVE_ZREGS_OFFSET) - -# define __SVE_PREGS_OFFSET(vq) (__SVE_ZREGS_OFFSET + __SVE_ZREGS_SIZE(vq)) -# define __SVE_PREG_OFFSET(vq, n) (__SVE_PREGS_OFFSET(vq) + __SVE_PREG_SIZE(vq) * (n)) -# define __SVE_PREGS_SIZE(vq) \ - (__SVE_PREG_OFFSET(vq, __SVE_NUM_PREGS) - __SVE_PREGS_OFFSET(vq)) - -# define __SVE_FFR_OFFSET(vq) (__SVE_PREGS_OFFSET(vq) + __SVE_PREGS_SIZE(vq)) - -# define SVE_VQ_BYTES __SVE_VQ_BYTES /* bytes per quadword */ - -# define SVE_VQ_MIN __SVE_VQ_MIN -# define SVE_VQ_MAX __SVE_VQ_MAX - -# define SVE_VL_MIN __SVE_VL_MIN -# define SVE_VL_MAX __SVE_VL_MAX - -# define SVE_NUM_ZREGS __SVE_NUM_ZREGS -# define SVE_NUM_PREGS __SVE_NUM_PREGS - -# define sve_vl_valid(vl) __sve_vl_valid(vl) -# define sve_vq_from_vl(vl) __sve_vq_from_vl(vl) -# define sve_vl_from_vq(vq) __sve_vl_from_vq(vq) - -# define SVE_SIG_ZREG_SIZE(vq) __SVE_ZREG_SIZE(vq) -# define SVE_SIG_PREG_SIZE(vq) __SVE_PREG_SIZE(vq) -# define SVE_SIG_FFR_SIZE(vq) __SVE_FFR_SIZE(vq) - -# define SVE_SIG_REGS_OFFSET \ - ((sizeof(struct sve_context) + (__SVE_VQ_BYTES - 1)) / __SVE_VQ_BYTES * \ - __SVE_VQ_BYTES) - -# define SVE_SIG_ZREGS_OFFSET (SVE_SIG_REGS_OFFSET + __SVE_ZREGS_OFFSET) -# define SVE_SIG_ZREG_OFFSET(vq, n) (SVE_SIG_REGS_OFFSET + __SVE_ZREG_OFFSET(vq, n)) -# define SVE_SIG_ZREGS_SIZE(vq) __SVE_ZREGS_SIZE(vq) - -# define SVE_SIG_PREGS_OFFSET(vq) (SVE_SIG_REGS_OFFSET + __SVE_PREGS_OFFSET(vq)) -# define SVE_SIG_PREG_OFFSET(vq, n) (SVE_SIG_REGS_OFFSET + __SVE_PREG_OFFSET(vq, n)) -# define SVE_SIG_PREGS_SIZE(vq) __SVE_PREGS_SIZE(vq) - -# define SVE_SIG_FFR_OFFSET(vq) (SVE_SIG_REGS_OFFSET + __SVE_FFR_OFFSET(vq)) - -# define SVE_SIG_REGS_SIZE(vq) (__SVE_FFR_OFFSET(vq) + __SVE_FFR_SIZE(vq)) - -# define SVE_SIG_CONTEXT_SIZE(vq) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq)) +/* SVE helper macro. */ +# define BYTES_PER_QUADWORD 16 /* A quadword is 128 bits. */ +# define sve_vecquad_from_veclen(veclen) ((veclen) / BYTES_PER_QUADWORD) #endif /* AARCH64 */ diff --git a/core/unix/signal_linux_aarch64.c b/core/unix/signal_linux_aarch64.c index 76186b6ad22..2704cf60e93 100644 --- a/core/unix/signal_linux_aarch64.c +++ b/core/unix/signal_linux_aarch64.c @@ -102,30 +102,39 @@ dump_sigcontext(dcontext_t *dcontext, sigcontext_t *sc) case EXTRA_MAGIC: break; case SVE_MAGIC: { const struct sve_context *sve = (struct sve_context *)(next_head); - LOG(THREAD, LOG_ASYNCH, 2, "\tSVE VL %d bytes\n", sve->vl); + LOG(THREAD, LOG_ASYNCH, 2, "\tSVE vector length %d bytes\n", sve->vl); ASSERT(sve->vl == proc_get_vector_length_bytes()); - const unsigned int vq = sve_vq_from_vl(sve->vl); - LOG(THREAD, LOG_ASYNCH, 2, "\tVQ %d\n\n", vq); + const unsigned int quads_per_vector = sve_vecquad_from_veclen(sve->vl); + /* The size and offset macros below are used to access register + * state from memory. These are defined in the kernel's + * sigcontext.h. For scalable vectors, we typically deal in + * units of bytes and quadwords (128 bits). All scalable + * vectors are mutiples of 128 bits. For the purposes of signal + * context handling, these are the simplest and most consistent + * units for calculating sizes and offsets in order to access + * scalable register state in memory. + */ + LOG(THREAD, LOG_ASYNCH, 2, "\tQuadwords (128 bits) per vector %d\n\n", quads_per_vector); LOG(THREAD, LOG_ASYNCH, 2, "\tSVE_SIG_ZREG_SIZE %d\n", - SVE_SIG_ZREG_SIZE(vq)); + SVE_SIG_ZREG_SIZE(quads_per_vector)); LOG(THREAD, LOG_ASYNCH, 2, "\tSVE_SIG_PREG_SIZE %d\n", - SVE_SIG_PREG_SIZE(vq)); + SVE_SIG_PREG_SIZE(quads_per_vector)); LOG(THREAD, LOG_ASYNCH, 2, "\tSVE_SIG_FFR_SIZE %d\n", - SVE_SIG_FFR_SIZE(vq)); + SVE_SIG_FFR_SIZE(quads_per_vector)); LOG(THREAD, LOG_ASYNCH, 2, "\tsve->head.size %d\n\n", sve->head.size); LOG(THREAD, LOG_ASYNCH, 2, "\tSVE_SIG_ZREGS_OFFSET %d\n", SVE_SIG_ZREGS_OFFSET); LOG(THREAD, LOG_ASYNCH, 2, "\tSVE_SIG_PREGS_OFFSET %d\n", - SVE_SIG_PREGS_OFFSET(vq)); + SVE_SIG_PREGS_OFFSET(quads_per_vector)); LOG(THREAD, LOG_ASYNCH, 2, "\tSVE_SIG_FFR_OFFSET %d\n\n", - SVE_SIG_FFR_OFFSET(vq)); + SVE_SIG_FFR_OFFSET(quads_per_vector)); uint64 vdw; /* A vector's doubleword. */ int boff; /* Byte offset for each doubleword in a vector. */ for (i = 0; i < MCXT_NUM_SIMD_SVE_SLOTS; i++) { LOG(THREAD, LOG_ASYNCH, 2, "\tz%-2d 0x", i); - for (boff = ((vq * 2) - 1); boff >= 0; boff--) { - vdw = *((uint64 *)((((byte *)sve) + (SVE_SIG_ZREG_OFFSET(vq, i)) + + for (boff = ((quads_per_vector * 2) - 1); boff >= 0; boff--) { + vdw = *((uint64 *)((((byte *)sve) + (SVE_SIG_ZREG_OFFSET(quads_per_vector, i)) + (boff * 8)))); LOG(THREAD, LOG_ASYNCH, 2, "%016lx ", vdw); } @@ -134,11 +143,11 @@ dump_sigcontext(dcontext_t *dcontext, sigcontext_t *sc) LOG(THREAD, LOG_ASYNCH, 2, "\n"); for (i = 0; i < MCXT_NUM_SVEP_SLOTS; i++) { LOG(THREAD, LOG_ASYNCH, 2, "\tp%-2d 0x%08lx\n", i, - *((uint32 *)((byte *)sve + SVE_SIG_PREG_OFFSET(vq, i)))); + *((uint32 *)((byte *)sve + SVE_SIG_PREG_OFFSET(quads_per_vector, i)))); } LOG(THREAD, LOG_ASYNCH, 2, "\n"); LOG(THREAD, LOG_ASYNCH, 2, "\tFFR 0x%08lx\n\n", - *((uint32 *)((byte *)sve + SVE_SIG_FFR_OFFSET(vq)))); + *((uint32 *)((byte *)sve + SVE_SIG_FFR_OFFSET(quads_per_vector)))); break; } default: @@ -200,7 +209,7 @@ sigcontext_to_mcontext_simd(priv_mcontext_t *mc, sig_full_cxt_t *sc_full) case SVE_MAGIC: { const struct sve_context *sve = (struct sve_context *)(next_head); ASSERT(sve->vl == proc_get_vector_length_bytes()); - const unsigned int vq = sve_vq_from_vl(sve->vl); + const unsigned int quads_per_vector = sve_vecquad_from_veclen(sve->vl); if (sve->head.size != sizeof(struct sve_context)) { for (i = 0; i < MCXT_NUM_SIMD_SVE_SLOTS; i++) { /* SVE specifies that AArch64's SIMD&FP registers @@ -211,15 +220,15 @@ sigcontext_to_mcontext_simd(priv_mcontext_t *mc, sig_full_cxt_t *sc_full) * from the corresponding members of fpsimd_context's * vregs and not from sve_context. */ - memcpy(&mc->simd[i].u32, (byte *)sve + SVE_SIG_ZREG_OFFSET(vq, i), + memcpy(&mc->simd[i].u32, (byte *)sve + SVE_SIG_ZREG_OFFSET(quads_per_vector, i), sve->vl); memcpy(&mc->simd[i].q, &fpc->vregs[i], sizeof(mc->simd->q)); } for (i = 0; i < MCXT_NUM_SVEP_SLOTS; i++) { - memcpy(&mc->svep[i].u32, (byte *)sve + SVE_SIG_PREG_OFFSET(vq, i), + memcpy(&mc->svep[i].u32, (byte *)sve + SVE_SIG_PREG_OFFSET(quads_per_vector, i), sve->vl); } - memcpy(&mc->ffr, (byte *)sve + SVE_SIG_FFR_OFFSET(vq), sve->vl); + memcpy(&mc->ffr, (byte *)sve + SVE_SIG_FFR_OFFSET(quads_per_vector), sve->vl); } break; } @@ -263,15 +272,15 @@ mcontext_to_sigcontext_simd(sig_full_cxt_t *sc_full, priv_mcontext_t *mc) struct sve_context *sve = (void *)((byte *)esr + sizeof(struct esr_context)); sve->head.magic = SVE_MAGIC; sve->vl = proc_get_vector_length_bytes(); - const uint vq = sve_vq_from_vl(sve->vl); - sve->head.size = ALIGN_FORWARD(SVE_SIG_CONTEXT_SIZE(vq), 16); + const uint quads_per_vector = sve_vecquad_from_veclen(sve->vl); + sve->head.size = ALIGN_FORWARD(SVE_SIG_CONTEXT_SIZE(quads_per_vector), 16); for (uint i = 0; i < MCXT_NUM_SIMD_SVE_SLOTS; i++) { - memcpy((byte *)sve + SVE_SIG_ZREG_OFFSET(vq, i), &mc->simd[i].u32, sve->vl); + memcpy((byte *)sve + SVE_SIG_ZREG_OFFSET(quads_per_vector, i), &mc->simd[i].u32, sve->vl); } for (uint i = 0; i < MCXT_NUM_SVEP_SLOTS; i++) { - memcpy((byte *)sve + SVE_SIG_PREG_OFFSET(vq, i), &mc->svep[i].u32, sve->vl); + memcpy((byte *)sve + SVE_SIG_PREG_OFFSET(quads_per_vector, i), &mc->svep[i].u32, sve->vl); } - memcpy((byte *)sve + SVE_SIG_FFR_OFFSET(vq), &mc->ffr, sve->vl); + memcpy((byte *)sve + SVE_SIG_FFR_OFFSET(quads_per_vector), &mc->ffr, sve->vl); size_t offset = (proc_get_vector_length_bytes() * MCXT_NUM_SIMD_SVE_SLOTS) + ((proc_get_vector_length_bytes() / 8) * MCXT_NUM_SVEP_SLOTS) + 16;