162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/* Copyright (C) 2019 ARM Limited */
362306a36Sopenharmony_ci#ifndef __TESTCASES_H__
462306a36Sopenharmony_ci#define __TESTCASES_H__
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <stddef.h>
762306a36Sopenharmony_ci#include <stdio.h>
862306a36Sopenharmony_ci#include <stdbool.h>
962306a36Sopenharmony_ci#include <stdint.h>
1062306a36Sopenharmony_ci#include <stdlib.h>
1162306a36Sopenharmony_ci#include <ucontext.h>
1262306a36Sopenharmony_ci#include <signal.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/* Architecture specific sigframe definitions */
1562306a36Sopenharmony_ci#include <asm/sigcontext.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define FPSIMD_CTX	(1 << 0)
1862306a36Sopenharmony_ci#define SVE_CTX		(1 << 1)
1962306a36Sopenharmony_ci#define ZA_CTX		(1 << 2)
2062306a36Sopenharmony_ci#define EXTRA_CTX	(1 << 3)
2162306a36Sopenharmony_ci#define ZT_CTX		(1 << 4)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define KSFT_BAD_MAGIC	0xdeadbeef
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define HDR_SZ \
2662306a36Sopenharmony_ci	sizeof(struct _aarch64_ctx)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define GET_SF_RESV_HEAD(sf) \
2962306a36Sopenharmony_ci	(struct _aarch64_ctx *)(&(sf).uc.uc_mcontext.__reserved)
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define GET_SF_RESV_SIZE(sf) \
3262306a36Sopenharmony_ci	sizeof((sf).uc.uc_mcontext.__reserved)
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define GET_BUF_RESV_HEAD(buf) \
3562306a36Sopenharmony_ci	(struct _aarch64_ctx *)(&(buf).uc.uc_mcontext.__reserved)
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define GET_BUF_RESV_SIZE(buf) \
3862306a36Sopenharmony_ci	(sizeof(buf) - sizeof(buf.uc) +	\
3962306a36Sopenharmony_ci	 sizeof((buf).uc.uc_mcontext.__reserved))
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define GET_UCP_RESV_SIZE(ucp) \
4262306a36Sopenharmony_ci	sizeof((ucp)->uc_mcontext.__reserved)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci#define ASSERT_BAD_CONTEXT(uc) do {					\
4562306a36Sopenharmony_ci	char *err = NULL;						\
4662306a36Sopenharmony_ci	if (!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err)) {	\
4762306a36Sopenharmony_ci		if (err)						\
4862306a36Sopenharmony_ci			fprintf(stderr,					\
4962306a36Sopenharmony_ci				"Using badly built context - ERR: %s\n",\
5062306a36Sopenharmony_ci				err);					\
5162306a36Sopenharmony_ci	} else {							\
5262306a36Sopenharmony_ci		abort();						\
5362306a36Sopenharmony_ci	}								\
5462306a36Sopenharmony_ci} while (0)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#define ASSERT_GOOD_CONTEXT(uc) do {					 \
5762306a36Sopenharmony_ci	char *err = NULL;						 \
5862306a36Sopenharmony_ci	if (!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err)) {	 \
5962306a36Sopenharmony_ci		if (err)						 \
6062306a36Sopenharmony_ci			fprintf(stderr,					 \
6162306a36Sopenharmony_ci				"Detected BAD context - ERR: %s\n", err);\
6262306a36Sopenharmony_ci		abort();						 \
6362306a36Sopenharmony_ci	} else {							 \
6462306a36Sopenharmony_ci		fprintf(stderr, "uc context validated.\n");		 \
6562306a36Sopenharmony_ci	}								 \
6662306a36Sopenharmony_ci} while (0)
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci/*
6962306a36Sopenharmony_ci * A simple record-walker for __reserved area: it walks through assuming
7062306a36Sopenharmony_ci * only to find a proper struct __aarch64_ctx header descriptor.
7162306a36Sopenharmony_ci *
7262306a36Sopenharmony_ci * Instead it makes no assumptions on the content and ordering of the
7362306a36Sopenharmony_ci * records, any needed bounds checking must be enforced by the caller
7462306a36Sopenharmony_ci * if wanted: this way can be used by caller on any maliciously built bad
7562306a36Sopenharmony_ci * contexts.
7662306a36Sopenharmony_ci *
7762306a36Sopenharmony_ci * head->size accounts both for payload and header _aarch64_ctx size !
7862306a36Sopenharmony_ci */
7962306a36Sopenharmony_ci#define GET_RESV_NEXT_HEAD(h) \
8062306a36Sopenharmony_ci	(struct _aarch64_ctx *)((char *)(h) + (h)->size)
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistruct fake_sigframe {
8362306a36Sopenharmony_ci	siginfo_t	info;
8462306a36Sopenharmony_ci	ucontext_t	uc;
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_cibool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistruct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
9162306a36Sopenharmony_ci				size_t resv_sz, size_t *offset);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic inline struct _aarch64_ctx *get_terminator(struct _aarch64_ctx *head,
9462306a36Sopenharmony_ci						  size_t resv_sz,
9562306a36Sopenharmony_ci						  size_t *offset)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	return get_header(head, 0, resv_sz, offset);
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic inline void write_terminator_record(struct _aarch64_ctx *tail)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	if (tail) {
10362306a36Sopenharmony_ci		tail->magic = 0;
10462306a36Sopenharmony_ci		tail->size = 0;
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci}
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistruct _aarch64_ctx *get_starting_head(struct _aarch64_ctx *shead,
10962306a36Sopenharmony_ci				       size_t need_sz, size_t resv_sz,
11062306a36Sopenharmony_ci				       size_t *offset);
11162306a36Sopenharmony_ci#endif
112