1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *  * Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 *  * Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *    the documentation and/or other materials provided with the
13 *    distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28/*
29 * Copyright (c) 2001-2002 Opsycon AB  (www.opsycon.se / www.opsycon.com)
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 *    notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 *    notice, this list of conditions and the following disclaimer in the
38 *    documentation and/or other materials provided with the distribution.
39 * 3. Neither the name of Opsycon AB nor the names of its contributors
40 *    may be used to endorse or promote products derived from this software
41 *    without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
44 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
47 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
55 */
56/*-
57 * Copyright (c) 1991, 1993, 1995,
58 *	The Regents of the University of California.  All rights reserved.
59 *
60 * This code is derived from software contributed to Berkeley by
61 * Havard Eidnes.
62 *
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
65 * are met:
66 * 1. Redistributions of source code must retain the above copyright
67 *    notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 *    notice, this list of conditions and the following disclaimer in the
70 *    documentation and/or other materials provided with the distribution.
71 * 3. Neither the name of the University nor the names of its contributors
72 *    may be used to endorse or promote products derived from this software
73 *    without specific prior written permission.
74 *
75 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
76 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
77 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
78 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
79 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
80 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
81 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
82 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
83 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
84 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
85 * SUCH DAMAGE.
86 */
87/*
88 * Copyright (c) 1992, 1993
89 *	The Regents of the University of California.  All rights reserved.
90 *
91 * This code is derived from software contributed to Berkeley by
92 * Ralph Campbell.
93 *
94 * Redistribution and use in source and binary forms, with or without
95 * modification, are permitted provided that the following conditions
96 * are met:
97 * 1. Redistributions of source code must retain the above copyright
98 *    notice, this list of conditions and the following disclaimer.
99 * 2. Redistributions in binary form must reproduce the above copyright
100 *    notice, this list of conditions and the following disclaimer in the
101 *    documentation and/or other materials provided with the distribution.
102 * 3. Neither the name of the University nor the names of its contributors
103 *    may be used to endorse or promote products derived from this software
104 *    without specific prior written permission.
105 *
106 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
107 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
108 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
109 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
110 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
111 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
112 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
113 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
114 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
115 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
116 * SUCH DAMAGE.
117 *
118 *	@(#)signal.h	8.1 (Berkeley) 6/10/93
119 */
120
121#include <private/bionic_asm.h>
122
123/* jmpbuf is declared to users as an array of longs, which is only
124 * 4-byte aligned in 32-bit builds.  The Mips jmpbuf begins with a
125 * dynamically-sized 0- or 4-byte unused filler so that double-prec FP regs
126 * are saved to 8-byte-aligned mem cells.
127 * All the following jmpbuf offsets are from the rounded-DOWN base addr.
128 */
129
130/* Fields of same size on all MIPS abis: */
131/*     	field:		byte offset:	size:						*/
132/*     	dynam filler	(0*4)		   0-4 bytes of rounddown filler, DON'T TOUCH!!
133						often overlays user storage!!		*/
134#define	SC_FPSR_OFFSET	(1*4)		/* 4 bytes, floating point control/status reg */
135/* following fields are 8-byte aligned */
136#define	SC_FLAG_OFFSET	(2*4)		/* 8 bytes, cookie and savesigs flag, first actual field  */
137#define	SC_MASK_OFFSET	(4*4)		/* 16 bytes, mips32/mips64 version of sigset_t */
138#define	SC_CKSUM_OFFSET	(8*4)		/* 8 bytes, used for checksum */
139
140/* Registers that are 4-byte on mips32 o32, and 8-byte on mips64 n64 abi */
141#define	SC_REGS_OFFSET	(10*4)		/* SC_REGS_BYTES */
142#define	SC_REGS_SAVED	12 /*regs*/	/* ra,s0-s8,gp,sp */
143#define	SC_REGS_BYTES   (SC_REGS_SAVED*REGSZ)
144#define	SC_REGS		SC_REGS_OFFSET
145
146/* Double floating pt registers are 8-bytes on all abis,
147 * but the number of saved fp regs varies for o32/n32 versus n64 abis:
148 */
149
150#ifdef __LP64__
151#define	SC_FPREGS_SAVED	8  /* all  fp regs f24,f25,f26,f27,f28,f29,f30,f31 */
152#else
153#define	SC_FPREGS_SAVED	6  /* even fp regs f20,f22,f24,f26,f28,f30 */
154#endif
155
156#define	SC_FPREGS_OFFSET (SC_REGS_OFFSET + SC_REGS_BYTES)  /* SC_FPREGS_BYTES */
157#define	SC_FPREGS_BYTES (SC_FPREGS_SAVED*REGSZ_FP)
158#define	SC_FPREGS	SC_FPREGS_OFFSET
159
160#define	SC_TOTAL_BYTES	(SC_FPREGS_OFFSET + SC_FPREGS_BYTES)
161#define	SC_TOTAL_LONGS	(SC_TOTAL_BYTES/REGSZ)
162
163#define USE_CHECKSUM 1
164
165.macro m_mangle_reg_and_store reg, cookie, temp, offset
166	xor	\temp, \reg, \cookie
167	REG_S	\temp, \offset
168.endm
169
170.macro m_unmangle_reg_and_load reg, cookie, temp, offset
171	REG_L	\temp, \offset
172	xor	\reg, \temp, \cookie
173.endm
174
175.macro m_calculate_checksum dst, src, scratch
176	REG_L \dst, REGSZ(\src)
177#ifdef __LP64__
178	/* 64 bit: checksum offset is 4 (actual _JBLEN is 25) */
179	.irp i,2,3,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24
180#else
181	/* 32 bit: checksum offset is 8 (actual _JBLEN is 34) */
182	.irp i,2,3,4,5,6,7,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33
183#endif
184		REG_L \scratch, \i*REGSZ(\src)
185		xor \dst, \dst, \scratch
186	.endr
187.endm
188
189/*
190 *
191 *  GPOFF and FRAMESIZE must be the same for all setjmp/longjmp routines
192 *
193 */
194
195FRAMESZ= MKFSIZ(2,6)
196A1OFF= FRAMESZ-4*REGSZ
197A0OFF= FRAMESZ-3*REGSZ
198GPOFF= FRAMESZ-2*REGSZ
199RAOFF= FRAMESZ-1*REGSZ
200
201NON_LEAF(sigsetjmp, FRAMESZ, $ra)
202__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(sigsetjmp)
203	.mask	0x80000000, RAOFF
204	PTR_SUBU $sp, FRAMESZ			# allocate stack frame
205	SETUP_GP64(GPOFF, sigsetjmp)
206	SAVE_GP(GPOFF)
207	.set	reorder
208
209setjmp_common:
210#ifndef __LP64__
211	li	$t0, ~7
212	and	$a0, $t0				# round jmpbuf addr DOWN to 8-byte boundary
213#endif
214	REG_S	$ra, RAOFF($sp)			# spill state
215	REG_S	$a0, A0OFF($sp)
216
217	# get the cookie and store it along with the signal flag.
218	move	$a0, $a1
219	jal	__bionic_setjmp_cookie_get
220	REG_L	$a0, A0OFF($sp)
221
222	REG_S	$v0, SC_FLAG_OFFSET($a0)		# save cookie and savesigs flag
223	andi	$t0, $v0, 1			# extract savesigs flag
224
225	beqz	$t0, 1f				# do saving of signal mask?
226
227	# call sigprocmask(int how ignored, sigset_t* null, sigset_t* SC_MASK(a0)):
228	LA	$a2, SC_MASK_OFFSET($a0)		# gets current signal mask
229	li	$a0, 0				# how; ignored when new mask is null
230	li	$a1, 0				# null new mask
231	jal	sigprocmask			# get current signal mask
232	REG_L	$a0, A0OFF($sp)
2331:
234	REG_L	$gp, GPOFF($sp)			# restore spills
235	REG_L	$ra, RAOFF($sp)
236	REG_L	$t0, SC_FLAG_OFFSET($a0)		# move cookie to temp reg
237
238	# callee-saved long-sized regs:
239	PTR_ADDU $v1, $sp, FRAMESZ		# save orig sp
240
241	# m_mangle_reg_and_store reg, cookie, temp, offset
242	m_mangle_reg_and_store	$ra, $t0, $t1, SC_REGS+0*REGSZ($a0)
243	m_mangle_reg_and_store	$s0, $t0, $t2, SC_REGS+1*REGSZ($a0)
244	m_mangle_reg_and_store	$s1, $t0, $t3, SC_REGS+2*REGSZ($a0)
245	m_mangle_reg_and_store	$s2, $t0, $t1, SC_REGS+3*REGSZ($a0)
246	m_mangle_reg_and_store	$s3, $t0, $t2, SC_REGS+4*REGSZ($a0)
247	m_mangle_reg_and_store	$s4, $t0, $t3, SC_REGS+5*REGSZ($a0)
248	m_mangle_reg_and_store	$s5, $t0, $t1, SC_REGS+6*REGSZ($a0)
249	m_mangle_reg_and_store	$s6, $t0, $t2, SC_REGS+7*REGSZ($a0)
250	m_mangle_reg_and_store	$s7, $t0, $t3, SC_REGS+8*REGSZ($a0)
251	m_mangle_reg_and_store	$s8, $t0, $t1, SC_REGS+9*REGSZ($a0)
252	m_mangle_reg_and_store	$gp, $t0, $t2, SC_REGS+10*REGSZ($a0)
253	m_mangle_reg_and_store	$v1, $t0, $t3, SC_REGS+11*REGSZ($a0)
254
255	cfc1	$v0, $31
256
257#ifdef __LP64__
258	# callee-saved fp regs on mips n64 ABI are $f24..$f31
259	s.d	$f24, SC_FPREGS+0*REGSZ_FP($a0)
260	s.d	$f25, SC_FPREGS+1*REGSZ_FP($a0)
261	s.d	$f26, SC_FPREGS+2*REGSZ_FP($a0)
262	s.d	$f27, SC_FPREGS+3*REGSZ_FP($a0)
263	s.d	$f28, SC_FPREGS+4*REGSZ_FP($a0)
264	s.d	$f29, SC_FPREGS+5*REGSZ_FP($a0)
265	s.d	$f30, SC_FPREGS+6*REGSZ_FP($a0)
266	s.d	$f31, SC_FPREGS+7*REGSZ_FP($a0)
267#else
268	# callee-saved fp regs on mips o32 ABI are
269	#   the even-numbered double fp regs $f20,$f22,...$f30
270	s.d	$f20, SC_FPREGS+0*REGSZ_FP($a0)
271	s.d	$f22, SC_FPREGS+1*REGSZ_FP($a0)
272	s.d	$f24, SC_FPREGS+2*REGSZ_FP($a0)
273	s.d	$f26, SC_FPREGS+3*REGSZ_FP($a0)
274	s.d	$f28, SC_FPREGS+4*REGSZ_FP($a0)
275	s.d	$f30, SC_FPREGS+5*REGSZ_FP($a0)
276#endif
277	sw	$v0, SC_FPSR_OFFSET($a0)
278#if USE_CHECKSUM
279	m_calculate_checksum $t0, $a0, $t1
280	REG_S $t0, SC_CKSUM_OFFSET($a0)
281#endif
282	move	$v0, $zero
283	RESTORE_GP64
284	PTR_ADDU $sp, FRAMESZ
285	j	$ra
286END(sigsetjmp)
287
288
289# Alternate entry points:
290
291NON_LEAF(setjmp, FRAMESZ, $ra)
292__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(setjmp)
293	.mask	0x80000000, RAOFF
294	PTR_SUBU $sp, FRAMESZ
295	SETUP_GP64(GPOFF, setjmp)		# can't share sigsetjmp's gp code
296	SAVE_GP(GPOFF)
297	.set	reorder
298
299	li	$a1, 1				# save/restore signals state
300	b	setjmp_common			# tail call
301END(setjmp)
302
303
304NON_LEAF(_setjmp, FRAMESZ, $ra)
305__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_setjmp)
306	.mask	0x80000000, RAOFF
307	PTR_SUBU $sp, FRAMESZ
308	SETUP_GP64(GPOFF, _setjmp)		# can't share sigsetjmp's gp code
309	SAVE_GP(GPOFF)
310	.set	reorder
311
312	li	$a1, 0				# don't save/restore signals
313	b	setjmp_common			# tail call
314END(_setjmp)
315
316
317NON_LEAF(siglongjmp, FRAMESZ, $ra)
318__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(siglongjmp)
319	.mask	0x80000000, RAOFF
320	PTR_SUBU $sp, FRAMESZ
321	SETUP_GP64(GPOFF, siglongjmp)
322	SAVE_GP(GPOFF)
323	.set	reorder
324
325#ifndef __LP64__
326	li	$t0, ~7
327	and	$a0, $t0				# round jmpbuf addr DOWN to 8-byte boundary
328#endif
329
330	move	$s1, $a1				# temp spill
331	move	$s0, $a0
332
333#if USE_CHECKSUM
334	m_calculate_checksum $t0, $s0, $s2
335	REG_L	$s2, SC_CKSUM_OFFSET($s0)
336	beq	$t0, $s2, 0f
337	nop
338	jal	__bionic_setjmp_checksum_mismatch
339	nop
3400:
341#endif
342
343	# extract savesigs flag
344	REG_L	$s2, SC_FLAG_OFFSET($s0)
345	andi	$t0, $s2, 1
346	beqz	$t0, 1f				# restore signal mask?
347
348	# call sigprocmask(int how SIG_SETMASK, sigset_t* SC_MASK(a0), sigset_t* null):
349	LA	$a1, SC_MASK_OFFSET($s0)		# signals being restored
350	li	$a0, 3				# mips SIG_SETMASK
351	li	$a2, 0				# null
352	jal	sigprocmask			# restore signal mask
3531:
354	move	$t0, $s2				# get cookie to temp reg
355	move	$a1, $s1
356	move	$a0, $s0
357
358	# callee-saved long-sized regs:
359
360	# m_unmangle_reg_and_load reg, cookie, temp, offset
361	# don't restore gp yet, old value is needed for cookie_check call
362	m_unmangle_reg_and_load $ra, $t0, $t1, SC_REGS+0*REGSZ($a0)
363	m_unmangle_reg_and_load $s0, $t0, $t2, SC_REGS+1*REGSZ($a0)
364	m_unmangle_reg_and_load $s1, $t0, $t3, SC_REGS+2*REGSZ($a0)
365	m_unmangle_reg_and_load $s2, $t0, $t1, SC_REGS+3*REGSZ($a0)
366	m_unmangle_reg_and_load $s3, $t0, $t2, SC_REGS+4*REGSZ($a0)
367	m_unmangle_reg_and_load $s4, $t0, $t3, SC_REGS+5*REGSZ($a0)
368	m_unmangle_reg_and_load $s5, $t0, $t1, SC_REGS+6*REGSZ($a0)
369	m_unmangle_reg_and_load $s6, $t0, $t2, SC_REGS+7*REGSZ($a0)
370	m_unmangle_reg_and_load $s7, $t0, $t3, SC_REGS+8*REGSZ($a0)
371	m_unmangle_reg_and_load $s8, $t0, $t1, SC_REGS+9*REGSZ($a0)
372	m_unmangle_reg_and_load $v1, $t0, $t2, SC_REGS+10*REGSZ($a0)
373	m_unmangle_reg_and_load $sp, $t0, $t3, SC_REGS+11*REGSZ($a0)
374
375	lw	$v0, SC_FPSR_OFFSET($a0)
376	ctc1	$v0, $31			# restore old fr mode before fp values
377#ifdef __LP64__
378	# callee-saved fp regs on mips n64 ABI are $f24..$f31
379	l.d	$f24, SC_FPREGS+0*REGSZ_FP($a0)
380	l.d	$f25, SC_FPREGS+1*REGSZ_FP($a0)
381	l.d	$f26, SC_FPREGS+2*REGSZ_FP($a0)
382	l.d	$f27, SC_FPREGS+3*REGSZ_FP($a0)
383	l.d	$f28, SC_FPREGS+4*REGSZ_FP($a0)
384	l.d	$f29, SC_FPREGS+5*REGSZ_FP($a0)
385	l.d	$f30, SC_FPREGS+6*REGSZ_FP($a0)
386	l.d	$f31, SC_FPREGS+7*REGSZ_FP($a0)
387#else
388	# callee-saved fp regs on mips o32 ABI are
389	#   the even-numbered double fp regs $f20,$f22,...$f30
390	l.d	$f20, SC_FPREGS+0*REGSZ_FP($a0)
391	l.d	$f22, SC_FPREGS+1*REGSZ_FP($a0)
392	l.d	$f24, SC_FPREGS+2*REGSZ_FP($a0)
393	l.d	$f26, SC_FPREGS+3*REGSZ_FP($a0)
394	l.d	$f28, SC_FPREGS+4*REGSZ_FP($a0)
395	l.d	$f30, SC_FPREGS+5*REGSZ_FP($a0)
396#endif
397
398	# check cookie
399	PTR_SUBU $sp, FRAMESZ
400	REG_S	$v1, GPOFF($sp)
401	REG_S	$ra, RAOFF($sp)
402	REG_S	$a1, A1OFF($sp)
403	move	$a0, $t0
404	jal	__bionic_setjmp_cookie_check
405	REG_L	$gp, GPOFF($sp)
406	REG_L	$ra, RAOFF($sp)
407	REG_L	$a1, A1OFF($sp)
408	PTR_ADDU $sp, FRAMESZ
409
410	sltiu	$t0, $a1, 1		# never return 0!
411	xor	$v0, $a1, $t0
412	j	$ra			# return to setjmp call site
413END(siglongjmp)
414
415ALIAS_SYMBOL(longjmp, siglongjmp)
416__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(longjmp)
417ALIAS_SYMBOL(_longjmp, siglongjmp)
418__BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(_longjmp)
419