118f8729aSMark Brown // SPDX-License-Identifier: GPL-2.0
218f8729aSMark Brown /*
318f8729aSMark Brown  * Copyright (C) 2021 ARM Limited
418f8729aSMark Brown  *
518f8729aSMark Brown  * Verify that using an instruction not supported in streaming mode
618f8729aSMark Brown  * traps when in streaming mode.
718f8729aSMark Brown  */
818f8729aSMark Brown 
918f8729aSMark Brown #include <signal.h>
1018f8729aSMark Brown #include <ucontext.h>
1118f8729aSMark Brown #include <sys/prctl.h>
1218f8729aSMark Brown 
1318f8729aSMark Brown #include "test_signals_utils.h"
1418f8729aSMark Brown #include "testcases.h"
1518f8729aSMark Brown 
1618f8729aSMark Brown static union {
1718f8729aSMark Brown 	ucontext_t uc;
1818f8729aSMark Brown 	char buf[1024 * 128];
1918f8729aSMark Brown } context;
2018f8729aSMark Brown 
enable_za(void)2118f8729aSMark Brown static void enable_za(void)
2218f8729aSMark Brown {
2318f8729aSMark Brown 	/* smstart za; real data is TODO */
2418f8729aSMark Brown 	asm volatile(".inst 0xd503457f" : : : );
2518f8729aSMark Brown }
2618f8729aSMark Brown 
zt_regs_run(struct tdescr * td,siginfo_t * si,ucontext_t * uc)2718f8729aSMark Brown int zt_regs_run(struct tdescr *td, siginfo_t *si, ucontext_t *uc)
2818f8729aSMark Brown {
2918f8729aSMark Brown 	size_t offset;
3018f8729aSMark Brown 	struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context);
3118f8729aSMark Brown 	struct zt_context *zt;
3218f8729aSMark Brown 	char *zeros;
3318f8729aSMark Brown 
3418f8729aSMark Brown 	/*
3518f8729aSMark Brown 	 * Get a signal context which should have a ZT frame and registers
3618f8729aSMark Brown 	 * in it.
3718f8729aSMark Brown 	 */
3818f8729aSMark Brown 	enable_za();
3918f8729aSMark Brown 	if (!get_current_context(td, &context.uc, sizeof(context)))
4018f8729aSMark Brown 		return 1;
4118f8729aSMark Brown 
4218f8729aSMark Brown 	head = get_header(head, ZT_MAGIC, GET_BUF_RESV_SIZE(context), &offset);
4318f8729aSMark Brown 	if (!head) {
4418f8729aSMark Brown 		fprintf(stderr, "No ZT context\n");
4518f8729aSMark Brown 		return 1;
4618f8729aSMark Brown 	}
4718f8729aSMark Brown 
4818f8729aSMark Brown 	zt = (struct zt_context *)head;
4918f8729aSMark Brown 	if (zt->nregs == 0) {
5018f8729aSMark Brown 		fprintf(stderr, "Got context with no registers\n");
5118f8729aSMark Brown 		return 1;
5218f8729aSMark Brown 	}
5318f8729aSMark Brown 
5418f8729aSMark Brown 	fprintf(stderr, "Got expected size %u for %d registers\n",
5518f8729aSMark Brown 		head->size, zt->nregs);
5618f8729aSMark Brown 
5718f8729aSMark Brown 	/* We didn't load any data into ZT so it should be all zeros */
5818f8729aSMark Brown 	zeros = malloc(ZT_SIG_REGS_SIZE(zt->nregs));
5918f8729aSMark Brown 	if (!zeros) {
6018f8729aSMark Brown 		fprintf(stderr, "Out of memory, nregs=%u\n", zt->nregs);
6118f8729aSMark Brown 		return 1;
6218f8729aSMark Brown 	}
6318f8729aSMark Brown 	memset(zeros, 0, ZT_SIG_REGS_SIZE(zt->nregs));
6418f8729aSMark Brown 
6518f8729aSMark Brown 	if (memcmp(zeros, (char *)zt + ZT_SIG_REGS_OFFSET,
6618f8729aSMark Brown 		   ZT_SIG_REGS_SIZE(zt->nregs)) != 0) {
6718f8729aSMark Brown 		fprintf(stderr, "ZT data invalid\n");
68*46862da1SDing Xiang 		free(zeros);
6918f8729aSMark Brown 		return 1;
7018f8729aSMark Brown 	}
7118f8729aSMark Brown 
7218f8729aSMark Brown 	free(zeros);
7318f8729aSMark Brown 
7418f8729aSMark Brown 	td->pass = 1;
7518f8729aSMark Brown 
7618f8729aSMark Brown 	return 0;
7718f8729aSMark Brown }
7818f8729aSMark Brown 
7918f8729aSMark Brown struct tdescr tde = {
8018f8729aSMark Brown 	.name = "ZT register data",
8118f8729aSMark Brown 	.descr = "Validate that ZT is present and has data when ZA is enabled",
8218f8729aSMark Brown 	.feats_required = FEAT_SME2,
8318f8729aSMark Brown 	.timeout = 3,
8418f8729aSMark Brown 	.sanity_disabled = true,
8518f8729aSMark Brown 	.run = zt_regs_run,
8618f8729aSMark Brown };
87