master
  1/*	$NetBSD: mcontext.h,v 1.23 2021/10/06 05:33:15 skrll Exp $	*/
  2
  3/*-
  4 * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc.
  5 * All rights reserved.
  6 *
  7 * This code is derived from software contributed to The NetBSD Foundation
  8 * by Klaus Klein and by Jason R. Thorpe of Wasabi Systems, Inc.
  9 *
 10 * Redistribution and use in source and binary forms, with or without
 11 * modification, are permitted provided that the following conditions
 12 * are met:
 13 * 1. Redistributions of source code must retain the above copyright
 14 *    notice, this list of conditions and the following disclaimer.
 15 * 2. Redistributions in binary form must reproduce the above copyright
 16 *    notice, this list of conditions and the following disclaimer in the
 17 *    documentation and/or other materials provided with the distribution.
 18 *
 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 29 * POSSIBILITY OF SUCH DAMAGE.
 30 */
 31
 32#ifndef _ARM_MCONTEXT_H_
 33#define _ARM_MCONTEXT_H_
 34
 35#include <sys/stdint.h>
 36
 37/*
 38 * General register state
 39 */
 40#if defined(__aarch64__)
 41#define _NGREG		35	/* GR0-30, SP, PC, SPSR, TPIDR */
 42#define _NGREG32	17
 43typedef __uint64_t	__greg_t;
 44typedef unsigned int	__greg32_t;
 45
 46typedef __greg32_t	__gregset32_t[_NGREG32];
 47#elif defined(__arm__)
 48#define _NGREG		17
 49typedef unsigned int	__greg_t;
 50#endif
 51
 52typedef __greg_t	__gregset_t[_NGREG];
 53
 54#define _REG_R0		0
 55#define _REG_R1		1
 56#define _REG_R2		2
 57#define _REG_R3		3
 58#define _REG_R4		4
 59#define _REG_R5		5
 60#define _REG_R6		6
 61#define _REG_R7		7
 62#define _REG_R8		8
 63#define _REG_R9		9
 64#define _REG_R10	10
 65#define _REG_R11	11
 66#define _REG_R12	12
 67#define _REG_R13	13
 68#define _REG_R14	14
 69#define _REG_R15	15
 70#define _REG_CPSR	16
 71
 72#define _REG_X0		0
 73#define _REG_X1		1
 74#define _REG_X2		2
 75#define _REG_X3		3
 76#define _REG_X4		4
 77#define _REG_X5		5
 78#define _REG_X6		6
 79#define _REG_X7		7
 80#define _REG_X8		8
 81#define _REG_X9		9
 82#define _REG_X10	10
 83#define _REG_X11	11
 84#define _REG_X12	12
 85#define _REG_X13	13
 86#define _REG_X14	14
 87#define _REG_X15	15
 88#define _REG_X16	16
 89#define _REG_X17	17
 90#define _REG_X18	18
 91#define _REG_X19	19
 92#define _REG_X20	20
 93#define _REG_X21	21
 94#define _REG_X22	22
 95#define _REG_X23	23
 96#define _REG_X24	24
 97#define _REG_X25	25
 98#define _REG_X26	26
 99#define _REG_X27	27
100#define _REG_X28	28
101#define _REG_X29	29
102#define _REG_X30	30
103#define _REG_X31	31
104#define _REG_ELR	32
105#define _REG_SPSR	33
106#define _REG_TPIDR	34
107
108/* Convenience synonyms */
109
110#if defined(__aarch64__)
111#define _REG_RV		_REG_X0
112#define _REG_FP		_REG_X29
113#define _REG_LR		_REG_X30
114#define _REG_SP		_REG_X31
115#define _REG_PC		_REG_ELR
116#elif defined(__arm__)
117#define _REG_RV		_REG_R0
118#define _REG_FP		_REG_R11
119#define _REG_SP		_REG_R13
120#define _REG_LR		_REG_R14
121#define _REG_PC		_REG_R15
122#endif
123
124/*
125 * Floating point register state
126 */
127#if defined(__aarch64__)
128
129#define _NFREG	32			/* Number of SIMD registers */
130
131typedef struct {
132	union __freg {
133		__uint8_t	__b8[16];
134		__uint16_t	__h16[8];
135		__uint32_t	__s32[4];
136		__uint64_t	__d64[2];
137		__uint128_t	__q128[1];
138	}		__qregs[_NFREG] __aligned(16);
139	__uint32_t	__fpcr;		/* FPCR */
140	__uint32_t	__fpsr;		/* FPSR */
141} __fregset_t;
142
143/* Compat structures */
144typedef struct {
145#if 1 /* __ARM_EABI__ is default on aarch64 */
146	unsigned int	__vfp_fpscr;
147	uint64_t	__vfp_fstmx[32];
148	unsigned int	__vfp_fpsid;
149#else
150	unsigned int	__vfp_fpscr;
151	unsigned int	__vfp_fstmx[33];
152	unsigned int	__vfp_fpsid;
153#endif
154} __vfpregset32_t;
155
156typedef struct {
157	__gregset32_t	__gregs;
158	__vfpregset32_t __vfpregs;
159	__greg32_t	_mc_tlsbase;
160	__greg32_t	_mc_user_tpid;
161} mcontext32_t;
162
163typedef struct {
164	__gregset_t	__gregs;	/* General Purpose Register set */
165	__fregset_t	__fregs;	/* FPU/SIMD Register File */
166	__greg_t	__spare[8];	/* future proof */
167} mcontext_t;
168
169#elif defined(__arm__)
170/* Note: the storage layout of this structure must be identical to ARMFPE! */
171typedef struct {
172	unsigned int	__fp_fpsr;
173	struct {
174		unsigned int	__fp_exponent;
175		unsigned int	__fp_mantissa_hi;
176		unsigned int	__fp_mantissa_lo;
177	}		__fp_fr[8];
178} __fpregset_t;
179
180typedef struct {
181#ifdef __ARM_EABI__
182	unsigned int	__vfp_fpscr;
183	uint64_t	__vfp_fstmx[32];
184	unsigned int	__vfp_fpsid;
185#else
186	unsigned int	__vfp_fpscr;
187	unsigned int	__vfp_fstmx[33];
188	unsigned int	__vfp_fpsid;
189#endif
190} __vfpregset_t;
191
192typedef struct {
193	__gregset_t	__gregs;
194	union {
195		__fpregset_t __fpregs;
196		__vfpregset_t __vfpregs;
197	} __fpu;
198	__greg_t	_mc_tlsbase;
199	__greg_t	_mc_user_tpid;
200} mcontext_t, mcontext32_t;
201
202
203#define _UC_MACHINE_PAD	1		/* Padding appended to ucontext_t */
204
205#ifdef __ARM_EABI__
206#define	__UCONTEXT_SIZE	(256 + 144)
207#else
208#define	__UCONTEXT_SIZE	256
209#endif
210
211#endif
212
213#if defined(_RTLD_SOURCE) || defined(_LIBC_SOURCE) || \
214    defined(__LIBPTHREAD_SOURCE__)
215
216#include <sys/tls.h>
217
218#if defined(__aarch64__)
219
220__BEGIN_DECLS
221static __inline void *
222__lwp_getprivate_fast(void)
223{
224	void *__tpidr;
225	__asm __volatile("mrs\t%0, tpidr_el0" : "=r"(__tpidr));
226	return __tpidr;
227}
228__END_DECLS
229
230#elif defined(__arm__)
231
232__BEGIN_DECLS
233static __inline void *
234__lwp_getprivate_fast(void)
235{
236#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
237	extern void *_lwp_getprivate(void);
238	void *rv;
239	__asm("mrc p15, 0, %0, c13, c0, 3" : "=r"(rv));
240	if (__predict_true(rv))
241		return rv;
242	/*
243	 * Some ARM cores are broken and don't raise an undefined fault when an
244	 * unrecogized mrc instruction is encountered, but just return zero.
245	 * To do deal with that, if we get a zero we (re-)fetch the value using
246	 * syscall.
247	 */
248	return _lwp_getprivate();
249#else
250	extern void *__aeabi_read_tp(void);
251	return __aeabi_read_tp();
252#endif /* !__thumb__ || _ARM_ARCH_T2 */
253}
254__END_DECLS
255#endif
256
257#endif /* _RTLD_SOURCE || _LIBC_SOURCE || __LIBPTHREAD_SOURCE__ */
258
259/* Machine-dependent uc_flags */
260#define _UC_TLSBASE	0x00080000	/* see <sys/ucontext.h> */
261
262/* Machine-dependent uc_flags for arm */
263#define	_UC_ARM_VFP	0x00010000	/* FPU field is VFP */
264
265/* used by signal delivery to indicate status of signal stack */
266#define _UC_SETSTACK	0x00020000
267#define _UC_CLRSTACK	0x00040000
268
269#define _UC_MACHINE_SP(uc)	((uc)->uc_mcontext.__gregs[_REG_SP])
270#define _UC_MACHINE_FP(uc)	((uc)->uc_mcontext.__gregs[_REG_FP])
271#define _UC_MACHINE_PC(uc)	((uc)->uc_mcontext.__gregs[_REG_PC])
272#define _UC_MACHINE_INTRV(uc)	((uc)->uc_mcontext.__gregs[_REG_RV])
273
274#define _UC_MACHINE_SET_PC(uc, pc)	\
275				_UC_MACHINE_PC(uc) = (pc)
276
277#if defined(_KERNEL)
278__BEGIN_DECLS
279void vfp_getcontext(struct lwp *, mcontext_t *, int *);
280void vfp_setcontext(struct lwp *, const mcontext_t *);
281__END_DECLS
282#endif
283
284#endif	/* !_ARM_MCONTEXT_H_ */