aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/include/arm-netbsd-eabi/machine/mcontext.h
blob: 7d4b3fa8155b10185260bd806b822985b24f4bed (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
/*	$NetBSD: mcontext.h,v 1.23 2021/10/06 05:33:15 skrll Exp $	*/

/*-
 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by Klaus Klein and by Jason R. Thorpe of Wasabi Systems, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _ARM_MCONTEXT_H_
#define _ARM_MCONTEXT_H_

#include <sys/stdint.h>

/*
 * General register state
 */
#if defined(__aarch64__)
#define _NGREG		35	/* GR0-30, SP, PC, SPSR, TPIDR */
#define _NGREG32	17
typedef __uint64_t	__greg_t;
typedef unsigned int	__greg32_t;

typedef __greg32_t	__gregset32_t[_NGREG32];
#elif defined(__arm__)
#define _NGREG		17
typedef unsigned int	__greg_t;
#endif

typedef __greg_t	__gregset_t[_NGREG];

#define _REG_R0		0
#define _REG_R1		1
#define _REG_R2		2
#define _REG_R3		3
#define _REG_R4		4
#define _REG_R5		5
#define _REG_R6		6
#define _REG_R7		7
#define _REG_R8		8
#define _REG_R9		9
#define _REG_R10	10
#define _REG_R11	11
#define _REG_R12	12
#define _REG_R13	13
#define _REG_R14	14
#define _REG_R15	15
#define _REG_CPSR	16

#define _REG_X0		0
#define _REG_X1		1
#define _REG_X2		2
#define _REG_X3		3
#define _REG_X4		4
#define _REG_X5		5
#define _REG_X6		6
#define _REG_X7		7
#define _REG_X8		8
#define _REG_X9		9
#define _REG_X10	10
#define _REG_X11	11
#define _REG_X12	12
#define _REG_X13	13
#define _REG_X14	14
#define _REG_X15	15
#define _REG_X16	16
#define _REG_X17	17
#define _REG_X18	18
#define _REG_X19	19
#define _REG_X20	20
#define _REG_X21	21
#define _REG_X22	22
#define _REG_X23	23
#define _REG_X24	24
#define _REG_X25	25
#define _REG_X26	26
#define _REG_X27	27
#define _REG_X28	28
#define _REG_X29	29
#define _REG_X30	30
#define _REG_X31	31
#define _REG_ELR	32
#define _REG_SPSR	33
#define _REG_TPIDR	34

/* Convenience synonyms */

#if defined(__aarch64__)
#define _REG_RV		_REG_X0
#define _REG_FP		_REG_X29
#define _REG_LR		_REG_X30
#define _REG_SP		_REG_X31
#define _REG_PC		_REG_ELR
#elif defined(__arm__)
#define _REG_RV		_REG_R0
#define _REG_FP		_REG_R11
#define _REG_SP		_REG_R13
#define _REG_LR		_REG_R14
#define _REG_PC		_REG_R15
#endif

/*
 * Floating point register state
 */
#if defined(__aarch64__)

#define _NFREG	32			/* Number of SIMD registers */

typedef struct {
	union __freg {
		__uint8_t	__b8[16];
		__uint16_t	__h16[8];
		__uint32_t	__s32[4];
		__uint64_t	__d64[2];
		__uint128_t	__q128[1];
	}		__qregs[_NFREG] __aligned(16);
	__uint32_t	__fpcr;		/* FPCR */
	__uint32_t	__fpsr;		/* FPSR */
} __fregset_t;

/* Compat structures */
typedef struct {
#if 1 /* __ARM_EABI__ is default on aarch64 */
	unsigned int	__vfp_fpscr;
	uint64_t	__vfp_fstmx[32];
	unsigned int	__vfp_fpsid;
#else
	unsigned int	__vfp_fpscr;
	unsigned int	__vfp_fstmx[33];
	unsigned int	__vfp_fpsid;
#endif
} __vfpregset32_t;

typedef struct {
	__gregset32_t	__gregs;
	__vfpregset32_t __vfpregs;
	__greg32_t	_mc_tlsbase;
	__greg32_t	_mc_user_tpid;
} mcontext32_t;

typedef struct {
	__gregset_t	__gregs;	/* General Purpose Register set */
	__fregset_t	__fregs;	/* FPU/SIMD Register File */
	__greg_t	__spare[8];	/* future proof */
} mcontext_t;

#elif defined(__arm__)
/* Note: the storage layout of this structure must be identical to ARMFPE! */
typedef struct {
	unsigned int	__fp_fpsr;
	struct {
		unsigned int	__fp_exponent;
		unsigned int	__fp_mantissa_hi;
		unsigned int	__fp_mantissa_lo;
	}		__fp_fr[8];
} __fpregset_t;

typedef struct {
#ifdef __ARM_EABI__
	unsigned int	__vfp_fpscr;
	uint64_t	__vfp_fstmx[32];
	unsigned int	__vfp_fpsid;
#else
	unsigned int	__vfp_fpscr;
	unsigned int	__vfp_fstmx[33];
	unsigned int	__vfp_fpsid;
#endif
} __vfpregset_t;

typedef struct {
	__gregset_t	__gregs;
	union {
		__fpregset_t __fpregs;
		__vfpregset_t __vfpregs;
	} __fpu;
	__greg_t	_mc_tlsbase;
	__greg_t	_mc_user_tpid;
} mcontext_t, mcontext32_t;


#define _UC_MACHINE_PAD	1		/* Padding appended to ucontext_t */

#ifdef __ARM_EABI__
#define	__UCONTEXT_SIZE	(256 + 144)
#else
#define	__UCONTEXT_SIZE	256
#endif

#endif

#if defined(_RTLD_SOURCE) || defined(_LIBC_SOURCE) || \
    defined(__LIBPTHREAD_SOURCE__)

#include <sys/tls.h>

#if defined(__aarch64__)

__BEGIN_DECLS
static __inline void *
__lwp_getprivate_fast(void)
{
	void *__tpidr;
	__asm __volatile("mrs\t%0, tpidr_el0" : "=r"(__tpidr));
	return __tpidr;
}
__END_DECLS

#elif defined(__arm__)

__BEGIN_DECLS
static __inline void *
__lwp_getprivate_fast(void)
{
#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
	extern void *_lwp_getprivate(void);
	void *rv;
	__asm("mrc p15, 0, %0, c13, c0, 3" : "=r"(rv));
	if (__predict_true(rv))
		return rv;
	/*
	 * Some ARM cores are broken and don't raise an undefined fault when an
	 * unrecogized mrc instruction is encountered, but just return zero.
	 * To do deal with that, if we get a zero we (re-)fetch the value using
	 * syscall.
	 */
	return _lwp_getprivate();
#else
	extern void *__aeabi_read_tp(void);
	return __aeabi_read_tp();
#endif /* !__thumb__ || _ARM_ARCH_T2 */
}
__END_DECLS
#endif

#endif /* _RTLD_SOURCE || _LIBC_SOURCE || __LIBPTHREAD_SOURCE__ */

/* Machine-dependent uc_flags */
#define _UC_TLSBASE	0x00080000	/* see <sys/ucontext.h> */

/* Machine-dependent uc_flags for arm */
#define	_UC_ARM_VFP	0x00010000	/* FPU field is VFP */

/* used by signal delivery to indicate status of signal stack */
#define _UC_SETSTACK	0x00020000
#define _UC_CLRSTACK	0x00040000

#define _UC_MACHINE_SP(uc)	((uc)->uc_mcontext.__gregs[_REG_SP])
#define _UC_MACHINE_FP(uc)	((uc)->uc_mcontext.__gregs[_REG_FP])
#define _UC_MACHINE_PC(uc)	((uc)->uc_mcontext.__gregs[_REG_PC])
#define _UC_MACHINE_INTRV(uc)	((uc)->uc_mcontext.__gregs[_REG_RV])

#define _UC_MACHINE_SET_PC(uc, pc)	\
				_UC_MACHINE_PC(uc) = (pc)

#if defined(_KERNEL)
__BEGIN_DECLS
void vfp_getcontext(struct lwp *, mcontext_t *, int *);
void vfp_setcontext(struct lwp *, const mcontext_t *);
__END_DECLS
#endif

#endif	/* !_ARM_MCONTEXT_H_ */