summaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/arm64/signal/testcases/testcases.h
blob: 98b97efdda232944664b26467726a9003063b5ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019 ARM Limited */
#ifndef __TESTCASES_H__
#define __TESTCASES_H__

#include <stddef.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <ucontext.h>
#include <signal.h>

/* Architecture specific sigframe definitions */
#include <asm/sigcontext.h>

#define FPSIMD_CTX	(1 << 0)
#define SVE_CTX		(1 << 1)
#define ZA_CTX		(1 << 2)
#define EXTRA_CTX	(1 << 3)
#define ZT_CTX		(1 << 4)
#define FPMR_CTX	(1 << 5)
#define GCS_CTX		(1 << 6)

#define KSFT_BAD_MAGIC	0xdeadbeef

#define HDR_SZ \
	sizeof(struct _aarch64_ctx)

#define GET_UC_RESV_HEAD(uc) \
	(struct _aarch64_ctx *)(&(uc->uc_mcontext.__reserved))

#define GET_SF_RESV_HEAD(sf) \
	(struct _aarch64_ctx *)(&(sf).uc.uc_mcontext.__reserved)

#define GET_SF_RESV_SIZE(sf) \
	sizeof((sf).uc.uc_mcontext.__reserved)

#define GET_BUF_RESV_HEAD(buf) \
	(struct _aarch64_ctx *)(&(buf).uc.uc_mcontext.__reserved)

#define GET_BUF_RESV_SIZE(buf) \
	(sizeof(buf) - sizeof(buf.uc) +	\
	 sizeof((buf).uc.uc_mcontext.__reserved))

#define GET_UCP_RESV_SIZE(ucp) \
	sizeof((ucp)->uc_mcontext.__reserved)

#define ASSERT_BAD_CONTEXT(uc) do {					\
	char *err = NULL;						\
	if (!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err)) {	\
		if (err)						\
			fprintf(stderr,					\
				"Using badly built context - ERR: %s\n",\
				err);					\
	} else {							\
		abort();						\
	}								\
} while (0)

#define ASSERT_GOOD_CONTEXT(uc) do {					 \
	char *err = NULL;						 \
	if (!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err)) {	 \
		if (err)						 \
			fprintf(stderr,					 \
				"Detected BAD context - ERR: %s\n", err);\
		abort();						 \
	} else {							 \
		fprintf(stderr, "uc context validated.\n");		 \
	}								 \
} while (0)

/*
 * A simple record-walker for __reserved area: it walks through assuming
 * only to find a proper struct __aarch64_ctx header descriptor.
 *
 * Instead it makes no assumptions on the content and ordering of the
 * records, any needed bounds checking must be enforced by the caller
 * if wanted: this way can be used by caller on any maliciously built bad
 * contexts.
 *
 * head->size accounts both for payload and header _aarch64_ctx size !
 */
#define GET_RESV_NEXT_HEAD(h) \
	(struct _aarch64_ctx *)((char *)(h) + (h)->size)

struct fake_sigframe {
	siginfo_t	info;
	ucontext_t	uc;
};


bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err);

static inline struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
				size_t resv_sz, size_t *offset)
{
	size_t offs = 0;
	struct _aarch64_ctx *found = NULL;

	if (!head || resv_sz < HDR_SZ)
		return found;

	while (offs <= resv_sz - HDR_SZ &&
	       head->magic != magic && head->magic) {
		offs += head->size;
		head = GET_RESV_NEXT_HEAD(head);
	}
	if (head->magic == magic) {
		found = head;
		if (offset)
			*offset = offs;
	}

	return found;
}


static inline struct _aarch64_ctx *get_terminator(struct _aarch64_ctx *head,
						  size_t resv_sz,
						  size_t *offset)
{
	return get_header(head, 0, resv_sz, offset);
}

static inline void write_terminator_record(struct _aarch64_ctx *tail)
{
	if (tail) {
		tail->magic = 0;
		tail->size = 0;
	}
}

struct _aarch64_ctx *get_starting_head(struct _aarch64_ctx *shead,
				       size_t need_sz, size_t resv_sz,
				       size_t *offset);
#endif