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