Skip to content

Commit

Permalink
Remove SVE helper macros already available in kernel header.
Browse files Browse the repository at this point in the history
Update VQ/vq, VL/vl and sve_vq_from_vl() to make them more
descriptive and readable. Add comment describing rationale
of using quadwords.
  • Loading branch information
AssadHashmi committed Apr 1, 2024
1 parent ed93675 commit 688c18e
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 89 deletions.
71 changes: 3 additions & 68 deletions core/unix/include/sigcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
51 changes: 30 additions & 21 deletions core/unix/signal_linux_aarch64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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:
Expand Down Expand Up @@ -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
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 688c18e

Please sign in to comment.