xref: /openbsd-src/sys/arch/mips64/mips64/lcore_access.S (revision d8417bd7da1c4c9f6786edfd187f5ed8fdaf04fb)
1/*	$OpenBSD: lcore_access.S,v 1.36 2023/12/12 07:37:21 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2001-2003 Opsycon AB  (www.opsycon.se / www.opsycon.com)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28#include <sys/errno.h>
29#include <sys/syscall.h>
30
31#include <machine/param.h>
32#include <machine/asm.h>
33#include <machine/cpu.h>
34#include <mips64/mips_cpu.h>
35#include <machine/regnum.h>
36#include <machine/cpustate.h>
37#include <machine/trap.h>
38
39#include "assym.h"
40
41	.set	mips3
42
43	.set	noreorder		# Noreorder is default style!
44
45/*
46 * Primitives
47 */
48
49/*
50 * This table is indexed by u.u_pcb.pcb_onfault in trap().
51 * The reason for using this table rather than storing an address in
52 * u.u_pcb.pcb_onfault is simply to make the code faster.
53 * This table must match with definitions in trap.h.
54 */
55	.globl	onfault_table
56	.data
57	.align	3
58onfault_table:
59	PTR_VAL	0		# invalid index number
60	PTR_VAL	_copyerr
61	PTR_VAL	_kcopyerr
62#if defined(DDB) || defined(DEBUG)
63	PTR_VAL	kt_ddberr
64#else
65	PTR_VAL	0
66#endif
67	.text
68
69/*
70 * This code is copied the user's stack for returning from signal handlers
71 * (see sendsig() and sigreturn()). We have to compute the address
72 * of the sigcontext struct for the sigreturn call.
73 */
74	.globl	sigcode
75sigcode:
76	PTR_ADDU a0, sp, 4*REGSZ		# address of sigcontext
77	LI	v0, SYS_sigreturn	# sigreturn(scp)
78	.globl	sigcodecall
79sigcodecall:
80	syscall
81	.globl	sigcoderet
82sigcoderet:
83	.globl	esigcode
84esigcode:
85	/* FALLTHROUGH */
86	.globl	sigfill
87sigfill:
88	teq	zero, zero, 0x52
89esigfill:
90
91	.data
92	.globl	sigfillsiz
93sigfillsiz:
94	.long	esigfill - sigfill
95
96	.text
97
98/*
99 * Copy a null terminated string within the kernel address space.
100 * Maxlength may be null if count not wanted.
101 *	copystr(fromaddr, toaddr, maxlength, &lencopied)
102 *		caddr_t fromaddr;
103 *		caddr_t toaddr;
104 *		u_int maxlength;
105 *		u_long *lencopied;
106 */
107LEAF(copystr, 0)
108	beq	a2, zero, 9f
109	 move	t2, a2			# Save the number of bytes
110	move	v0, zero
1111:
112	lbu	t0, 0(a0)
113	PTR_SUBU a2, a2, 1
114	sb	t0, 0(a1)
115	PTR_ADDU a0, a0, 1
116	beq	t0, zero, 2f
117	 PTR_ADDU a1, a1, 1
118	bne	a2, zero, 1b
119	 NOP
1209:
121	LI	v0, ENAMETOOLONG	# String is longer than maxlength
1222:
123	beq	a3, zero, 3f
124	 PTR_SUBU a2, t2, a2		# Compute length copied
125	REG_S	a2, 0(a3)
1263:
127	j	ra
128	 NOP
129END(copystr)
130
131/*
132 * Optimized memory zero code.
133 * mem_zero_page(addr);
134 */
135LEAF(mem_zero_page, 0)
136	LI	v0, PAGE_SIZE
1371:
138	PTR_SUBU v0, 8
139	sd	zero, 0(a0)
140	bne	zero, v0, 1b
141	 PTR_ADDU a0, 8
142	jr	ra
143	 NOP
144END(mem_zero_page)
145
146/*
147 * Copy a null terminated string from the user address space into
148 * the kernel address space.
149 *
150 *	_copyinstr(fromaddr, toaddr, maxlength, &lencopied)
151 *		caddr_t fromaddr;
152 *		caddr_t toaddr;
153 *		u_int maxlength;
154 *		u_int *lencopied;
155 */
156NON_LEAF(_copyinstr, FRAMESZ(CF_SZ), ra)
157	PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
158	.mask	0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
159	PTR_S	ra, CF_RA_OFFS(sp)
160	blt	a0, zero, _copyerr	# make sure address is in user space
161	 LI	v0, KT_COPYERR
162	GET_CPU_INFO(t1, t0)
163	PTR_L	t3, CI_CURPROCPADDR(t1)
164	jal	copystr
165	 sw	v0, PCB_ONFAULT(t3)
166
167	PTR_L	ra, CF_RA_OFFS(sp)
168	GET_CPU_INFO(t1, t0)
169	PTR_L	t3, CI_CURPROCPADDR(t1)
170	sw	zero, PCB_ONFAULT(t3)
171	PTR_ADDU sp, sp, FRAMESZ(CF_SZ)
172	j	ra
173	 NOP
174END(_copyinstr)
175
176/*
177 * Copy a null terminated string from the kernel address space into
178 * the user address space.
179 *
180 *	copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
181 *		caddr_t fromaddr;
182 *		caddr_t toaddr;
183 *		u_int maxlength;
184 *		u_int *lencopied;
185 */
186NON_LEAF(copyoutstr, FRAMESZ(CF_SZ), ra)
187	PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
188	.mask	0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
189	PTR_S	ra, CF_RA_OFFS(sp)
190	blt	a1, zero, _copyerr	# make sure address is in user space
191	 LI	v0, KT_COPYERR
192	GET_CPU_INFO(t1, t0)
193	PTR_L	t3, CI_CURPROCPADDR(t1)
194	jal	copystr
195	 sw	v0, PCB_ONFAULT(t3)
196
197	PTR_L	ra, CF_RA_OFFS(sp)
198	GET_CPU_INFO(t1, t0)
199	PTR_L	t3, CI_CURPROCPADDR(t1)
200	sw	zero, PCB_ONFAULT(t3)
201	PTR_ADDU sp, sp, FRAMESZ(CF_SZ)
202	j	ra
203	 NOP
204END(copyoutstr)
205
206/*
207 * Copy specified amount of data from user space into the kernel
208 *	_copyin(from, to, len)
209 *		caddr_t *from;	(user source address)
210 *		caddr_t *to;	(kernel destination address)
211 *		unsigned len;
212 */
213NON_LEAF(_copyin, FRAMESZ(CF_SZ), ra)
214	PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
215	.mask	0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
216	PTR_S	ra, CF_RA_OFFS(sp)
217	blt	a0, zero, _copyerr	# make sure address is in user space
218	 li	v0, KT_COPYERR
219	GET_CPU_INFO(t1, t0)
220	PTR_L	t3, CI_CURPROCPADDR(t1)
221	jal	bcopy
222	 sw	v0, PCB_ONFAULT(t3)
223
224	PTR_L	ra, CF_RA_OFFS(sp)
225	GET_CPU_INFO(t1, t0)
226	PTR_L	t3, CI_CURPROCPADDR(t1)
227	sw	zero, PCB_ONFAULT(t3)
228	PTR_ADDU sp, sp, FRAMESZ(CF_SZ)
229	j	ra
230	 move	v0, zero
231END(_copyin)
232
233/*
234 * Copy specified amount of data from kernel to the user space
235 *	copyout(from, to, len)
236 *		caddr_t *from;	(kernel source address)
237 *		caddr_t *to;	(user destination address)
238 *		unsigned len;
239 */
240NON_LEAF(copyout, FRAMESZ(CF_SZ), ra)
241	PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
242	.mask	0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
243	PTR_S	ra, CF_RA_OFFS(sp)
244	blt	a1, zero, _copyerr	# make sure address is in user space
245	 li	v0, KT_COPYERR
246	GET_CPU_INFO(t1, t0)
247	PTR_L	t3, CI_CURPROCPADDR(t1)
248	jal	bcopy
249	 sw	v0, PCB_ONFAULT(t3)
250
251	PTR_L	ra, CF_RA_OFFS(sp)
252	GET_CPU_INFO(t1, t0)
253	PTR_L	t3, CI_CURPROCPADDR(t1)
254	sw	zero, PCB_ONFAULT(t3)
255	PTR_ADDU sp, sp, FRAMESZ(CF_SZ)
256	j	ra
257	 move	v0, zero
258END(copyout)
259
260/*
261 * Copy an aligned 32-bit word atomically from user space into the kernel
262 *	copyin32(from, to)
263 *		uint32_t *from;	(user source address)
264 *		uint32_t *to;	(kernel destination address)
265 */
266NON_LEAF(copyin32, FRAMESZ(CF_SZ), ra)
267	PTR_SUBU sp, sp, FRAMESZ(CF_SZ)
268	.mask	0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ))
269	PTR_S	ra, CF_RA_OFFS(sp)
270	blt	a0, zero, _copyerr	# make sure address is in user space
271	 li	v0, KT_COPYERR
272	GET_CPU_INFO(t1, t0)
273	PTR_L	t3, CI_CURPROCPADDR(t1)
274	sw	v0, PCB_ONFAULT(t3)
275
276	lw	v1, 0(a0)
277	sw	v1, 0(a1)
278
279	sw	zero, PCB_ONFAULT(t3)
280	PTR_ADDU sp, sp, FRAMESZ(CF_SZ)
281	j	ra
282	 move	v0, zero
283END(copyin32)
284
285_copyerr:
286	PTR_L	ra, CF_RA_OFFS(sp)
287	GET_CPU_INFO(t1, t0)
288	PTR_L	t3, CI_CURPROCPADDR(t1)
289	sw	zero, PCB_ONFAULT(t3)
290	PTR_ADDU sp, sp, FRAMESZ(CF_SZ)
291	j	ra
292	 li	v0, EFAULT		# return error
293
294/*
295 *  kcopy is a wrapper around bcopy that catches bad memory references.
296 */
297NON_LEAF(kcopy, FRAMESZ(CF_SZ + REGSZ), ra)
298	PTR_SUBU sp, sp, FRAMESZ(CF_SZ + REGSZ)
299	.mask	0x80000000, (CF_RA_OFFS - FRAMESZ(CF_SZ + REGSZ))
300	PTR_S	ra, CF_RA_OFFS + REGSZ(sp)
301	GET_CPU_INFO(t1, t0)
302	PTR_L	t3, CI_CURPROCPADDR(t1)
303	lw	v1, PCB_ONFAULT(t3)
304	li	v0, KT_KCOPYERR
305	PTR_S	v1, CF_ARGSZ(sp)	# save old pcb_onfault
306	jal	bcopy
307	 sw	v0, PCB_ONFAULT(t3)
308
309	PTR_L	v0, CF_ARGSZ(sp)
310	GET_CPU_INFO(t1, t0)
311	PTR_L	t3, CI_CURPROCPADDR(t1)
312	PTR_L	ra, CF_RA_OFFS + REGSZ(sp)
313	sw	v0, PCB_ONFAULT(t3)
314	PTR_ADDU sp, sp, FRAMESZ(CF_SZ + REGSZ)
315	j	ra
316	 move	v0, zero
317END(kcopy)
318
319_kcopyerr:
320	PTR_L	v0, CF_ARGSZ(sp)
321	GET_CPU_INFO(t1, t0)
322	PTR_L	t3, CI_CURPROCPADDR(t1)
323	PTR_L	ra, CF_RA_OFFS + REGSZ(sp)
324	sw	v0, PCB_ONFAULT(t3)
325	PTR_ADDU sp, sp, FRAMESZ(CF_SZ + REGSZ)
326	j	ra
327	 li	v0, EFAULT		# return error
328