root/tools/testing/selftests/arm64/signal/testcases/zt_regs.c
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2021 ARM Limited
 *
 * Verify that using an instruction not supported in streaming mode
 * traps when in streaming mode.
 */

#include <signal.h>
#include <ucontext.h>
#include <sys/prctl.h>

#include "test_signals_utils.h"
#include "testcases.h"

static union {
        ucontext_t uc;
        char buf[1024 * 128];
} context;

static void enable_za(void)
{
        /* smstart za; real data is TODO */
        asm volatile(".inst 0xd503457f" : : : );
}

int zt_regs_run(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
{
        size_t offset;
        struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context);
        struct zt_context *zt;
        char *zeros;

        /*
         * Get a signal context which should have a ZT frame and registers
         * in it.
         */
        enable_za();
        if (!get_current_context(td, &context.uc, sizeof(context)))
                return 1;

        head = get_header(head, ZT_MAGIC, GET_BUF_RESV_SIZE(context), &offset);
        if (!head) {
                fprintf(stderr, "No ZT context\n");
                return 1;
        }

        zt = (struct zt_context *)head;
        if (zt->nregs == 0) {
                fprintf(stderr, "Got context with no registers\n");
                return 1;
        }

        fprintf(stderr, "Got expected size %u for %d registers\n",
                head->size, zt->nregs);

        /* We didn't load any data into ZT so it should be all zeros */
        zeros = malloc(ZT_SIG_REGS_SIZE(zt->nregs));
        if (!zeros) {
                fprintf(stderr, "Out of memory, nregs=%u\n", zt->nregs);
                return 1;
        }
        memset(zeros, 0, ZT_SIG_REGS_SIZE(zt->nregs));

        if (memcmp(zeros, (char *)zt + ZT_SIG_REGS_OFFSET,
                   ZT_SIG_REGS_SIZE(zt->nregs)) != 0) {
                fprintf(stderr, "ZT data invalid\n");
                free(zeros);
                return 1;
        }

        free(zeros);

        td->pass = 1;

        return 0;
}

struct tdescr tde = {
        .name = "ZT register data",
        .descr = "Validate that ZT is present and has data when ZA is enabled",
        .feats_required = FEAT_SME2,
        .timeout = 3,
        .sanity_disabled = true,
        .run = zt_regs_run,
};