xref: /netbsd-src/sys/arch/aarch64/aarch64/netbsd32_machdep.c (revision b349331a0ba2b3ec97123008aaa9342badc1505f)
1 /*	$NetBSD: netbsd32_machdep.c,v 1.25 2024/06/18 13:29:56 rin Exp $	*/
2 
3 /*
4  * Copyright (c) 2018 Ryo Shimizu
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.25 2024/06/18 13:29:56 rin Exp $");
31 
32 #if defined(_KERNEL_OPT)
33 #include "opt_compat_netbsd.h"
34 #endif
35 
36 #include <sys/param.h>
37 #include <sys/core.h>
38 #include <sys/exec.h>
39 #include <sys/lwp.h>
40 #include <sys/ptrace.h>
41 #include <sys/ras.h>
42 #include <sys/signalvar.h>
43 #include <sys/syscallargs.h>
44 #include <sys/compat_stub.h>
45 
46 #include <uvm/uvm_extern.h>
47 
48 #include <compat/netbsd32/netbsd32.h>
49 #include <compat/netbsd32/netbsd32_exec.h>
50 #include <compat/netbsd32/netbsd32_syscallargs.h>
51 
52 #include <aarch64/armreg.h>
53 #include <aarch64/frame.h>
54 #include <aarch64/machdep.h>
55 #include <aarch64/userret.h>
56 
57 #include <arm/cpufunc.h>
58 
59 const char machine32[] = MACHINE;
60 const char machine_arch32[] = MACHINE32_ARCH;
61 
62 void
netbsd32_setregs(struct lwp * l,struct exec_package * pack,vaddr_t stack)63 netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
64 {
65 	struct proc * const p = l->l_proc;
66 	struct trapframe * const tf = lwp_trapframe(l);
67 
68 	netbsd32_adjust_limits(p);
69 
70 	aarch64_setregs_ptrauth(l, false);
71 
72 	p->p_flag |= PK_32;
73 
74 	/*
75 	 * void __start(struct ps_strings *ps_strings, const Obj_Entry *obj,
76 	 *     void (*cleanup)(void));
77 	 */
78 	memset(tf, 0, sizeof(*tf));
79 	tf->tf_reg[0] = (uint32_t)p->p_psstrp;
80 	tf->tf_reg[12] = stack;		/* r12 needed by pre 1.4 crt0.c */
81 	tf->tf_reg[13] = stack;		/* sp */
82 	tf->tf_reg[14] = pack->ep_entry;/* lr */
83 	tf->tf_reg[18] = 0x77777777;	/* svc_lr. adjust to arm_machdep.c */
84 	tf->tf_pc = pack->ep_entry;
85 
86 
87 	/* set 32bit mode, and same endian as 64bit's */
88 #ifdef __AARCH64EB__
89 	tf->tf_spsr = SPSR_M_USR32 | SPSR_A32_E;
90 #else
91 	tf->tf_spsr = SPSR_M_USR32;
92 #endif
93 
94 	/* THUMB CODE? */
95 	if (pack->ep_entry & 1)
96 		tf->tf_spsr |= SPSR_A32_T;
97 }
98 
99 int
netbsd32_ptrace_translate_request(int req)100 netbsd32_ptrace_translate_request(int req)
101 {
102 
103 	switch (req) {
104 	case 0 ... PT_FIRSTMACH - 1:
105 		return req;
106 	case PT32_GETREGS:
107 		return PT_GETREGS;
108 	case PT32_SETREGS:
109 		return PT_SETREGS;
110 	case PT32_GETFPREGS:
111 		return PT_GETFPREGS;
112 	case PT32_SETFPREGS:
113 		return PT_SETFPREGS;
114 	/* not implemented for arm32 */
115 	case PT32_STEP:
116 	case PT32_SETSTEP:
117 	case PT32_CLEARSTEP:
118 	default:
119 		return -1;
120 	}
121 }
122 
123 /* aarch32 fpscr register is assigned to two registers fpsr/fpcr on aarch64 */
124 #define FPSR_BITS							\
125 	(FPSR_N32|FPSR_Z32|FPSR_C32|FPSR_V32|FPSR_QC|			\
126 	 FPSR_IDC|FPSR_IXC|FPSR_UFC|FPSR_OFC|FPSR_DZC|FPSR_IOC)
127 #define FPCR_BITS							\
128 	(FPCR_AHP|FPCR_DN|FPCR_FZ|FPCR_RMODE|FPCR_STRIDE|FPCR_LEN|	\
129 	 FPCR_IDE|FPCR_IXE|FPCR_UFE|FPCR_OFE|FPCR_DZE|FPCR_IOE)
130 
131 int
netbsd32_process_read_regs(struct lwp * l,struct reg32 * regs)132 netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs)
133 {
134 	struct proc * const p = l->l_proc;
135 	struct trapframe *tf = lwp_trapframe(l);
136 	int i;
137 
138 	if ((p->p_flag & PK_32) == 0)
139 		return EINVAL;
140 
141 	for (i = 0; i < 13; i++)
142 		regs->r[i] = tf->tf_reg[i];	/* r0-r12 */
143 	regs->r_sp = tf->tf_reg[13];		/* r13 = sp */
144 	regs->r_lr = tf->tf_reg[14];		/* r14 = lr */
145 	regs->r_pc = tf->tf_pc;			/* r15 = pc */
146 	regs->r_cpsr = tf->tf_spsr;
147 
148 	/* THUMB CODE? */
149 	if (tf->tf_spsr & SPSR_A32_T)
150 		regs->r_pc |= 1;
151 
152 	return 0;
153 }
154 
155 int
netbsd32_process_read_fpregs(struct lwp * l,struct fpreg32 * fpregs,size_t * lenp)156 netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *fpregs,
157     size_t *lenp)
158 {
159 	struct proc * const p = l->l_proc;
160 	struct pcb * const pcb = lwp_getpcb(l);
161 	int i, j;
162 
163 	if ((p->p_flag & PK_32) == 0)
164 		return EINVAL;
165 
166 	KASSERT(*lenp <= sizeof(*fpregs));
167 	fpu_save(l);
168 
169 	/*
170 	 * convert from aarch64's struct fpreg to arm's struct fpreg32
171 	 */
172 #define VFP_FPEXC_EN		0x40000000	/* VFP Enable bit */
173 #define VFP_FPEXC_VECITR	0x00000700	/* VECtor ITeRation count */
174 	fpregs->fpr_vfp.vfp_fpexc = VFP_FPEXC_EN | VFP_FPEXC_VECITR;
175 
176 	fpregs->fpr_vfp.vfp_fpscr =
177 	    (pcb->pcb_fpregs.fpsr & FPSR_BITS) |
178 	    (pcb->pcb_fpregs.fpcr & FPCR_BITS);
179 
180 	fpregs->fpr_vfp.vfp_fpinst = 0;
181 	fpregs->fpr_vfp.vfp_fpinst2 = 0;
182 
183 	for (i = j = 0; i < 16; i++) {
184 #ifdef __AARCH64EB__
185 		fpregs->fpr_vfp.vfp_regs[j++] =
186 		    pcb->pcb_fpregs.fp_reg[i].u64[1];
187 		fpregs->fpr_vfp.vfp_regs[j++] =
188 		    pcb->pcb_fpregs.fp_reg[i].u64[0];
189 #else
190 		fpregs->fpr_vfp.vfp_regs[j++] =
191 		    pcb->pcb_fpregs.fp_reg[i].u64[0];
192 		fpregs->fpr_vfp.vfp_regs[j++] =
193 		    pcb->pcb_fpregs.fp_reg[i].u64[1];
194 #endif
195 	}
196 
197 	return 0;
198 }
199 
200 int
netbsd32_process_write_regs(struct lwp * l,const struct reg32 * regs)201 netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs)
202 {
203 	struct proc * const p = l->l_proc;
204 	struct trapframe *tf = lwp_trapframe(l);
205 	int i;
206 
207 	if ((p->p_flag & PK_32) == 0)
208 		return EINVAL;
209 
210 	if (regs->r_pc >= VM_MAXUSER_ADDRESS32 ||
211 	    regs->r_sp >= VM_MAXUSER_ADDRESS32)
212 		return EINVAL;
213 
214 	for (i = 0; i < 13; i++)
215 		tf->tf_reg[i] = regs->r[i];	/* r0-r12 */
216 	tf->tf_reg[13] = regs->r_sp;		/* r13 = sp */
217 	tf->tf_reg[14] = regs->r_lr;		/* r14 = lr */
218 	tf->tf_pc = regs->r_pc;			/* r15 = pc */
219 	tf->tf_spsr &= ~(SPSR_NZCV | SPSR_A32_T);
220 	tf->tf_spsr |= regs->r_cpsr & (SPSR_NZCV | SPSR_A32_T);
221 
222 	/* THUMB CODE? */
223 	if (regs->r_pc & 1)
224 		tf->tf_spsr |= SPSR_A32_T;
225 
226 	return 0;
227 }
228 
229 int
netbsd32_process_write_fpregs(struct lwp * l,const struct fpreg32 * fpregs,size_t len)230 netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *fpregs,
231     size_t len)
232 {
233 	struct proc * const p = l->l_proc;
234 	struct pcb * const pcb = lwp_getpcb(l);
235 	int i, j;
236 
237 	if ((p->p_flag & PK_32) == 0)
238 		return EINVAL;
239 
240 	KASSERT(len <= sizeof(*fpregs));
241 	fpu_discard(l, true);		// set used flag
242 
243 	pcb->pcb_fpregs.fpsr = fpregs->fpr_vfp.vfp_fpscr & FPSR_BITS;
244 	pcb->pcb_fpregs.fpcr = fpregs->fpr_vfp.vfp_fpscr & FPCR_BITS;
245 
246 	for (i = j = 0; i < 16; i++) {
247 #ifdef __AARCH64EB__
248 		pcb->pcb_fpregs.fp_reg[i].u64[1] =
249 		    fpregs->fpr_vfp.vfp_regs[j++];
250 		pcb->pcb_fpregs.fp_reg[i].u64[0] =
251 		    fpregs->fpr_vfp.vfp_regs[j++];
252 #else
253 		pcb->pcb_fpregs.fp_reg[i].u64[0] =
254 		    fpregs->fpr_vfp.vfp_regs[j++];
255 		pcb->pcb_fpregs.fp_reg[i].u64[1] =
256 		    fpregs->fpr_vfp.vfp_regs[j++];
257 #endif
258 	}
259 
260 	return 0;
261 }
262 
263 int
cpu_coredump32(struct lwp * l,struct coredump_iostate * iocookie,struct core32 * chdr)264 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie,
265     struct core32 *chdr)
266 {
267 	struct netbsd32_cpustate md_core32;
268 	struct coreseg32 cseg;
269 	int error;
270 
271 	if (iocookie == NULL) {
272 		CORE_SETMAGIC(*chdr, COREMAGIC, MID_ARM6, 0);
273 		chdr->c_hdrsize = ALIGN32(sizeof(*chdr));
274 		chdr->c_seghdrsize = ALIGN32(sizeof(cseg));
275 		chdr->c_cpusize = sizeof(md_core32);
276 		chdr->c_nseg++;
277 		return 0;
278 	}
279 
280 	error = netbsd32_process_read_regs(l, &md_core32.regs);
281 	if (error)
282 		return error;
283 
284 	error = netbsd32_process_read_fpregs(l, &md_core32.fpregs, NULL);
285 	if (error)
286 		return error;
287 
288 	CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_ARM6, CORE_CPU);
289 	cseg.c_addr = 0;
290 	cseg.c_size = chdr->c_cpusize;
291 
292 	MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE,
293 	    &cseg, chdr->c_seghdrsize), ENOSYS, error);
294 	if (error)
295 		return error;
296 
297 	MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE,
298 	    &md_core32, sizeof(md_core32)), ENOSYS, error);
299 
300 	return error;
301 }
302 
303 void
netbsd32_sendsig_siginfo(const ksiginfo_t * ksi,const sigset_t * mask)304 netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
305 {
306 	struct lwp * const l = curlwp;
307 	struct proc * const p = l->l_proc;
308 	struct trapframe * const tf = lwp_trapframe(l);
309 	stack_t * const ss = &l->l_sigstk;
310 	const int signo = ksi->ksi_signo;
311 	const struct sigaction * const sa = &SIGACTION(p, signo);
312 	const struct sigact_sigdesc * const sdesc =
313 	    &p->p_sigacts->sa_sigdesc[signo];
314 	const sig_t handler = sa->sa_handler;
315 	struct netbsd32_sigframe_siginfo *fp, frame;
316 	int error;
317 
318 	const bool onstack_p =
319 	    (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
320 	    (sa->sa_flags & SA_ONSTACK);
321 
322 	vaddr_t sp = onstack_p ?
323 	    ((vaddr_t)ss->ss_sp + ss->ss_size) :
324 	    tf->tf_reg[13];	/* r13 = sp on aarch32 */
325 
326 	fp = (struct netbsd32_sigframe_siginfo *)sp;
327 	fp = (struct netbsd32_sigframe_siginfo *)STACK_ALIGN(fp - 1, (8 - 1));
328 
329 	memset(&frame, 0, sizeof(frame));
330 
331 	/* XXX: netbsd32_ksi_to_si32 */
332 	netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info);
333 
334 	frame.sf_uc.uc_flags = _UC_SIGMASK;
335 	frame.sf_uc.uc_sigmask = *mask;
336 	frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink;
337 	frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) ?
338 	    _UC_SETSTACK : _UC_CLRSTACK;
339 	sendsig_reset(l, signo);
340 
341 	mutex_exit(p->p_lock);
342 	cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags);
343 	error = copyout(&frame, fp, sizeof(frame));
344 	mutex_enter(p->p_lock);
345 
346 	if (error != 0) {
347 		/*
348 		 * Process has trashed its stack;
349 		 * give it an illegal instruction to halt it in its tracks.
350 		 */
351 		sigexit(l, SIGILL);
352 		/* NOTREACHED */
353 	}
354 
355 	tf->tf_reg[0] = signo;
356 	tf->tf_reg[1] = (uint32_t)(uintptr_t)&fp->sf_si;
357 	tf->tf_reg[2] = (uint32_t)(uintptr_t)&fp->sf_uc;
358 
359 	/* the trampoline uses r5 as the uc address */
360 	tf->tf_reg[5] = (uint32_t)(uintptr_t)&fp->sf_uc;
361 	tf->tf_pc = (uint32_t)(uintptr_t)handler;
362 
363 	/* THUMB CODE? */
364 	if (((uintptr_t)handler) & 1)
365 		tf->tf_spsr |= SPSR_A32_T;
366 	else
367 		tf->tf_spsr &= ~SPSR_A32_T;
368 
369 	tf->tf_reg[13] = (uint32_t)(uintptr_t)fp;		/* sp */
370 	tf->tf_reg[14] = (uint32_t)(uintptr_t)sdesc->sd_tramp;	/* lr */
371 
372 	/* Remember if we're now on the signal stack */
373 	if (onstack_p)
374 		ss->ss_flags |= SS_ONSTACK;
375 }
376 
377 void
startlwp32(void * arg)378 startlwp32(void *arg)
379 {
380 	ucontext32_t *uc = arg;
381 	lwp_t *l = curlwp;
382 	int error __diagused;
383 
384 	/*
385 	 * entity of *uc is ucontext_t. therefore
386 	 * ucontext_t must be greater than ucontext32_t
387 	 */
388 	CTASSERT(sizeof(ucontext_t) >= sizeof(ucontext32_t));
389 
390 	error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags);
391 	KASSERT(error == 0);
392 
393 	/* Note: we are freeing ucontext_t, not ucontext32_t. */
394 	kmem_free(uc, sizeof(ucontext_t));
395 	userret(l);
396 }
397 
398 int
cpu_mcontext32_validate(struct lwp * l,const mcontext32_t * mcp)399 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp)
400 {
401 	struct proc * const p __diagused = l->l_proc;
402 	const uint32_t spsr = mcp->__gregs[_REG_CPSR];
403 
404 	KASSERT(p->p_flag & PK_32);
405 
406 	if (__SHIFTOUT(spsr, SPSR_M) != SPSR_M_USR32)
407 		return EINVAL;
408 
409 #ifdef __AARCH64EB__
410 	if ((spsr & SPSR_A32_E) == 0)
411 		return EINVAL;
412 #else
413 	if ((spsr & SPSR_A32_E) != 0)
414 		return EINVAL;
415 #endif
416 
417 	if ((spsr & (SPSR_A|SPSR_I|SPSR_F)) != 0)
418 		return EINVAL;
419 
420 	return 0;
421 }
422 void
cpu_getmcontext32(struct lwp * l,mcontext32_t * mcp,unsigned int * flagsp)423 cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flagsp)
424 {
425 	struct trapframe * const tf = lwp_trapframe(l);
426 	__greg32_t *gr = mcp->__gregs;
427 	void *ras_pc;
428 
429 	gr[_REG_R0]  = tf->tf_reg[0];
430 	gr[_REG_R1]  = tf->tf_reg[1];
431 	gr[_REG_R2]  = tf->tf_reg[2];
432 	gr[_REG_R3]  = tf->tf_reg[3];
433 	gr[_REG_R4]  = tf->tf_reg[4];
434 	gr[_REG_R5]  = tf->tf_reg[5];
435 	gr[_REG_R6]  = tf->tf_reg[6];
436 	gr[_REG_R7]  = tf->tf_reg[7];
437 	gr[_REG_R8]  = tf->tf_reg[8];
438 	gr[_REG_R9]  = tf->tf_reg[9];
439 	gr[_REG_R10] = tf->tf_reg[10];
440 	gr[_REG_R11] = tf->tf_reg[11];
441 	gr[_REG_R12] = tf->tf_reg[12];
442 	gr[_REG_R13] = tf->tf_reg[13];
443 	gr[_REG_R14] = tf->tf_reg[14];
444 	gr[_REG_R15] = tf->tf_pc;
445 	gr[_REG_CPSR] = tf->tf_spsr;
446 
447 	ras_pc = ras_lookup(l->l_proc, (void *)(uintptr_t)gr[_REG_R15]);
448 	if (ras_pc != (void *)-1) {
449 		gr[_REG_R15] = (__greg32_t)(uintptr_t)ras_pc;
450 	}
451 	*flagsp |= _UC_CPU;
452 
453 	/* fpu context */
454 	if (fpu_used_p(l)) {
455 		const struct pcb * const pcb = lwp_getpcb(l);
456 		int i, j;
457 
458 		fpu_save(l);
459 
460 		for (i = j = 0; i < 16; i++) {
461 #ifdef __AARCH64EB__
462 			mcp->__vfpregs.__vfp_fstmx[j++] =
463 			    pcb->pcb_fpregs.fp_reg[i].u64[1];
464 			mcp->__vfpregs.__vfp_fstmx[j++] =
465 			    pcb->pcb_fpregs.fp_reg[i].u64[0];
466 #else
467 			mcp->__vfpregs.__vfp_fstmx[j++] =
468 			    pcb->pcb_fpregs.fp_reg[i].u64[0];
469 			mcp->__vfpregs.__vfp_fstmx[j++] =
470 			    pcb->pcb_fpregs.fp_reg[i].u64[1];
471 #endif
472 		}
473 
474 		mcp->__vfpregs.__vfp_fpscr =
475 		    (pcb->pcb_fpregs.fpsr & FPSR_BITS) |
476 		    (pcb->pcb_fpregs.fpcr & FPCR_BITS);
477 		mcp->__vfpregs.__vfp_fpsid = 0;	/* XXX: build FPSID from MIDR */
478 
479 		*flagsp |= _UC_FPU;
480 	}
481 
482 	mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private;
483 	*flagsp |= _UC_TLSBASE;
484 }
485 
486 int
cpu_setmcontext32(struct lwp * l,const mcontext32_t * mcp,unsigned int flags)487 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags)
488 {
489 	struct trapframe * const tf = lwp_trapframe(l);
490 	const __greg32_t * const gr = mcp->__gregs;
491 	struct proc * const p = l->l_proc;
492 	int error, i, j;
493 
494 	if (flags & _UC_CPU) {
495 		error = cpu_mcontext32_validate(l, mcp);
496 		if (error != 0)
497 			return error;
498 
499 		tf->tf_reg[0]  = gr[_REG_R0];
500 		tf->tf_reg[1]  = gr[_REG_R1];
501 		tf->tf_reg[2]  = gr[_REG_R2];
502 		tf->tf_reg[3]  = gr[_REG_R3];
503 		tf->tf_reg[4]  = gr[_REG_R4];
504 		tf->tf_reg[5]  = gr[_REG_R5];
505 		tf->tf_reg[6]  = gr[_REG_R6];
506 		tf->tf_reg[7]  = gr[_REG_R7];
507 		tf->tf_reg[8]  = gr[_REG_R8];
508 		tf->tf_reg[9]  = gr[_REG_R9];
509 		tf->tf_reg[10] = gr[_REG_R10];
510 		tf->tf_reg[11] = gr[_REG_R11];
511 		tf->tf_reg[12] = gr[_REG_R12];
512 		tf->tf_reg[13] = gr[_REG_R13];
513 		tf->tf_reg[14] = gr[_REG_R14];
514 		tf->tf_pc      = gr[_REG_R15];
515 		tf->tf_spsr    = gr[_REG_CPSR];
516 	}
517 
518 	if (flags & _UC_FPU) {
519 		struct pcb * const pcb = lwp_getpcb(l);
520 		fpu_discard(l, true);
521 
522 		for (i = j = 0; i < 16; i++) {
523 #ifdef __AARCH64EB__
524 			pcb->pcb_fpregs.fp_reg[i].u64[1] =
525 			    mcp->__vfpregs.__vfp_fstmx[j++];
526 			pcb->pcb_fpregs.fp_reg[i].u64[0] =
527 			    mcp->__vfpregs.__vfp_fstmx[j++];
528 #else
529 			pcb->pcb_fpregs.fp_reg[i].u64[0] =
530 			    mcp->__vfpregs.__vfp_fstmx[j++];
531 			pcb->pcb_fpregs.fp_reg[i].u64[1] =
532 			    mcp->__vfpregs.__vfp_fstmx[j++];
533 #endif
534 		}
535 		pcb->pcb_fpregs.fpsr =
536 		    mcp->__vfpregs.__vfp_fpscr & FPSR_BITS;
537 		pcb->pcb_fpregs.fpcr =
538 		    mcp->__vfpregs.__vfp_fpscr & FPCR_BITS;
539 	}
540 
541 	if (flags &_UC_TLSBASE)
542 		l->l_private = (void *)(uintptr_t)mcp->_mc_tlsbase;
543 
544 	mutex_enter(p->p_lock);
545 	if (flags & _UC_SETSTACK)
546 		l->l_sigstk.ss_flags |= SS_ONSTACK;
547 	if (flags & _UC_CLRSTACK)
548 		l->l_sigstk.ss_flags &= ~SS_ONSTACK;
549 	mutex_exit(p->p_lock);
550 
551 	return 0;
552 }
553 
554 static int
arm32_sync_icache(struct lwp * l,const void * args,register_t * retval)555 arm32_sync_icache(struct lwp *l, const void *args, register_t *retval)
556 {
557 	struct netbsd32_arm_sync_icache_args ua;
558 	struct faultbuf fb;
559 	int error;
560 
561 	error = copyin(args, &ua, sizeof(ua));
562 	if (error != 0)
563 		return error;
564 
565 	if ((vaddr_t)ua.addr + ua.len > VM_MAXUSER_ADDRESS32)
566 		return EINVAL;
567 
568 	/* use cpu_set_onfault() by way of precaution */
569 	if ((error = cpu_set_onfault(&fb)) == 0) {
570 		pmap_icache_sync_range(
571 		    vm_map_pmap(&l->l_proc->p_vmspace->vm_map),
572 		    (vaddr_t)ua.addr, (vaddr_t)ua.addr + ua.len);
573 		cpu_unset_onfault();
574 	}
575 
576 	*retval = 0;
577 	return error;
578 }
579 
580 static int
arm32_drain_writebuf(struct lwp * l,const void * args,register_t * retval)581 arm32_drain_writebuf(struct lwp *l, const void *args, register_t *retval)
582 {
583 	aarch64_drain_writebuf();
584 
585 	*retval = 0;
586 	return 0;
587 }
588 
589 int
netbsd32_sysarch(struct lwp * l,const struct netbsd32_sysarch_args * uap,register_t * retval)590 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap,
591     register_t *retval)
592 {
593 	/* {
594 		syscallarg(int) op;
595 		syscallarg(netbsd32_voidp) parms;
596 	} */
597 	int error;
598 
599 	switch (SCARG(uap, op)) {
600 	case ARM_SYNC_ICACHE:
601 		error = arm32_sync_icache(l,
602 		    NETBSD32PTR64(SCARG(uap, parms)), retval);
603 		break;
604 	case ARM_DRAIN_WRITEBUF:
605 		error = arm32_drain_writebuf(l,
606 		    NETBSD32PTR64(SCARG(uap, parms)), retval);
607 		break;
608 	case ARM_VFP_FPSCR:
609 		printf("%s: ARM_VFP_FPSCR not implemented\n", __func__);
610 		error = EINVAL;
611 		break;
612 	case ARM_FPU_USED:
613 		printf("%s: ARM_FPU_USED not implemented\n", __func__);
614 		error = EINVAL;
615 		break;
616 	default:
617 		printf("%s: op=%d: not implemented\n", __func__,
618 		    SCARG(uap, op));
619 		error = EINVAL;
620 		break;
621 	}
622 	return error;
623 }
624 
625 vaddr_t
netbsd32_vm_default_addr(struct proc * p,vaddr_t base,vsize_t sz,int topdown)626 netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t sz,
627     int topdown)
628 {
629 	if (topdown)
630 		return VM_DEFAULT_ADDRESS32_TOPDOWN(base, sz);
631 	else
632 		return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, sz);
633 }
634 
635 void
netbsd32_machdep_md_init(void)636 netbsd32_machdep_md_init(void)
637 {
638 
639 	/* nothing to do */
640 }
641 
642 void
netbsd32_machdep_md_fini(void)643 netbsd32_machdep_md_fini(void)
644 {
645 
646 	/* nothing to do */
647 }
648