]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/exec_machdep.c
aarch64: Fix get_fpcontext32() to work on non-curthread.
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / exec_machdep.c
1 /*-
2  * Copyright (c) 2014 Andrew Turner
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  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/exec.h>
34 #include <sys/imgact.h>
35 #include <sys/kdb.h>
36 #include <sys/kernel.h>
37 #include <sys/ktr.h>
38 #include <sys/limits.h>
39 #include <sys/lock.h>
40 #include <sys/mutex.h>
41 #include <sys/proc.h>
42 #include <sys/ptrace.h>
43 #include <sys/reg.h>
44 #include <sys/rwlock.h>
45 #include <sys/signalvar.h>
46 #include <sys/syscallsubr.h>
47 #include <sys/sysent.h>
48 #include <sys/sysproto.h>
49 #include <sys/ucontext.h>
50
51 #include <vm/vm.h>
52 #include <vm/vm_param.h>
53
54 #include <machine/armreg.h>
55 #include <machine/kdb.h>
56 #include <machine/md_var.h>
57 #include <machine/pcb.h>
58
59 #ifdef VFP
60 #include <machine/vfp.h>
61 #endif
62
63 static void get_fpcontext(struct thread *td, mcontext_t *mcp);
64 static void set_fpcontext(struct thread *td, mcontext_t *mcp);
65
66 int
67 fill_regs(struct thread *td, struct reg *regs)
68 {
69         struct trapframe *frame;
70
71         frame = td->td_frame;
72         regs->sp = frame->tf_sp;
73         regs->lr = frame->tf_lr;
74         regs->elr = frame->tf_elr;
75         regs->spsr = frame->tf_spsr;
76
77         memcpy(regs->x, frame->tf_x, sizeof(regs->x));
78
79 #ifdef COMPAT_FREEBSD32
80         /*
81          * We may be called here for a 32bits process, if we're using a
82          * 64bits debugger. If so, put PC and SPSR where it expects it.
83          */
84         if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
85                 regs->x[15] = frame->tf_elr;
86                 regs->x[16] = frame->tf_spsr;
87         }
88 #endif
89         return (0);
90 }
91
92 int
93 set_regs(struct thread *td, struct reg *regs)
94 {
95         struct trapframe *frame;
96
97         frame = td->td_frame;
98         frame->tf_sp = regs->sp;
99         frame->tf_lr = regs->lr;
100
101         memcpy(frame->tf_x, regs->x, sizeof(frame->tf_x));
102
103 #ifdef COMPAT_FREEBSD32
104         if (SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
105                 /*
106                  * We may be called for a 32bits process if we're using
107                  * a 64bits debugger. If so, get PC and SPSR from where
108                  * it put it.
109                  */
110                 frame->tf_elr = regs->x[15];
111                 frame->tf_spsr &= ~PSR_SETTABLE_32;
112                 frame->tf_spsr |= regs->x[16] & PSR_SETTABLE_32;
113                 /* Don't allow userspace to ask to continue single stepping.
114                  * The SPSR.SS field doesn't exist when the EL1 is AArch32.
115                  * As the SPSR.DIT field has moved in its place don't
116                  * allow userspace to set the SPSR.SS field.
117                  */
118         } else
119 #endif
120         {
121                 frame->tf_elr = regs->elr;
122                 frame->tf_spsr &= ~PSR_SETTABLE_64;
123                 frame->tf_spsr |= regs->spsr & PSR_SETTABLE_64;
124                 /* Enable single stepping if userspace asked fot it */
125                 if ((frame->tf_spsr & PSR_SS) != 0) {
126                         td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
127
128                         WRITE_SPECIALREG(mdscr_el1,
129                             READ_SPECIALREG(mdscr_el1) | MDSCR_SS);
130                         isb();
131                 }
132         }
133         return (0);
134 }
135
136 int
137 fill_fpregs(struct thread *td, struct fpreg *regs)
138 {
139 #ifdef VFP
140         struct pcb *pcb;
141
142         pcb = td->td_pcb;
143         if ((pcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
144                 /*
145                  * If we have just been running VFP instructions we will
146                  * need to save the state to memcpy it below.
147                  */
148                 if (td == curthread)
149                         vfp_save_state(td, pcb);
150
151                 KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
152                     ("Called fill_fpregs while the kernel is using the VFP"));
153                 memcpy(regs->fp_q, pcb->pcb_fpustate.vfp_regs,
154                     sizeof(regs->fp_q));
155                 regs->fp_cr = pcb->pcb_fpustate.vfp_fpcr;
156                 regs->fp_sr = pcb->pcb_fpustate.vfp_fpsr;
157         } else
158 #endif
159                 memset(regs, 0, sizeof(*regs));
160         return (0);
161 }
162
163 int
164 set_fpregs(struct thread *td, struct fpreg *regs)
165 {
166 #ifdef VFP
167         struct pcb *pcb;
168
169         pcb = td->td_pcb;
170         KASSERT(pcb->pcb_fpusaved == &pcb->pcb_fpustate,
171             ("Called set_fpregs while the kernel is using the VFP"));
172         memcpy(pcb->pcb_fpustate.vfp_regs, regs->fp_q, sizeof(regs->fp_q));
173         pcb->pcb_fpustate.vfp_fpcr = regs->fp_cr;
174         pcb->pcb_fpustate.vfp_fpsr = regs->fp_sr;
175 #endif
176         return (0);
177 }
178
179 int
180 fill_dbregs(struct thread *td, struct dbreg *regs)
181 {
182         struct debug_monitor_state *monitor;
183         int i;
184         uint8_t debug_ver, nbkpts, nwtpts;
185
186         memset(regs, 0, sizeof(*regs));
187
188         extract_user_id_field(ID_AA64DFR0_EL1, ID_AA64DFR0_DebugVer_SHIFT,
189             &debug_ver);
190         extract_user_id_field(ID_AA64DFR0_EL1, ID_AA64DFR0_BRPs_SHIFT,
191             &nbkpts);
192         extract_user_id_field(ID_AA64DFR0_EL1, ID_AA64DFR0_WRPs_SHIFT,
193             &nwtpts);
194
195         /*
196          * The BRPs field contains the number of breakpoints - 1. Armv8-A
197          * allows the hardware to provide 2-16 breakpoints so this won't
198          * overflow an 8 bit value. The same applies to the WRPs field.
199          */
200         nbkpts++;
201         nwtpts++;
202
203         regs->db_debug_ver = debug_ver;
204         regs->db_nbkpts = nbkpts;
205         regs->db_nwtpts = nwtpts;
206
207         monitor = &td->td_pcb->pcb_dbg_regs;
208         if ((monitor->dbg_flags & DBGMON_ENABLED) != 0) {
209                 for (i = 0; i < nbkpts; i++) {
210                         regs->db_breakregs[i].dbr_addr = monitor->dbg_bvr[i];
211                         regs->db_breakregs[i].dbr_ctrl = monitor->dbg_bcr[i];
212                 }
213                 for (i = 0; i < nwtpts; i++) {
214                         regs->db_watchregs[i].dbw_addr = monitor->dbg_wvr[i];
215                         regs->db_watchregs[i].dbw_ctrl = monitor->dbg_wcr[i];
216                 }
217         }
218
219         return (0);
220 }
221
222 int
223 set_dbregs(struct thread *td, struct dbreg *regs)
224 {
225         struct debug_monitor_state *monitor;
226         uint64_t addr;
227         uint32_t ctrl;
228         int count;
229         int i;
230
231         monitor = &td->td_pcb->pcb_dbg_regs;
232         count = 0;
233         monitor->dbg_enable_count = 0;
234
235         for (i = 0; i < DBG_BRP_MAX; i++) {
236                 addr = regs->db_breakregs[i].dbr_addr;
237                 ctrl = regs->db_breakregs[i].dbr_ctrl;
238
239                 /*
240                  * Don't let the user set a breakpoint on a kernel or
241                  * non-canonical user address.
242                  */
243                 if (addr >= VM_MAXUSER_ADDRESS)
244                         return (EINVAL);
245
246                 /*
247                  * The lowest 2 bits are ignored, so record the effective
248                  * address.
249                  */
250                 addr = rounddown2(addr, 4);
251
252                 /*
253                  * Some control fields are ignored, and other bits reserved.
254                  * Only unlinked, address-matching breakpoints are supported.
255                  *
256                  * XXX: fields that appear unvalidated, such as BAS, have
257                  * constrained undefined behaviour. If the user mis-programs
258                  * these, there is no risk to the system.
259                  */
260                 ctrl &= DBGBCR_EN | DBGBCR_PMC | DBGBCR_BAS;
261                 if ((ctrl & DBGBCR_EN) != 0) {
262                         /* Only target EL0. */
263                         if ((ctrl & DBGBCR_PMC) != DBGBCR_PMC_EL0)
264                                 return (EINVAL);
265
266                         monitor->dbg_enable_count++;
267                 }
268
269                 monitor->dbg_bvr[i] = addr;
270                 monitor->dbg_bcr[i] = ctrl;
271         }
272
273         for (i = 0; i < DBG_WRP_MAX; i++) {
274                 addr = regs->db_watchregs[i].dbw_addr;
275                 ctrl = regs->db_watchregs[i].dbw_ctrl;
276
277                 /*
278                  * Don't let the user set a watchpoint on a kernel or
279                  * non-canonical user address.
280                  */
281                 if (addr >= VM_MAXUSER_ADDRESS)
282                         return (EINVAL);
283
284                 /*
285                  * Some control fields are ignored, and other bits reserved.
286                  * Only unlinked watchpoints are supported.
287                  */
288                 ctrl &= DBGWCR_EN | DBGWCR_PAC | DBGWCR_LSC | DBGWCR_BAS |
289                     DBGWCR_MASK;
290
291                 if ((ctrl & DBGWCR_EN) != 0) {
292                         /* Only target EL0. */
293                         if ((ctrl & DBGWCR_PAC) != DBGWCR_PAC_EL0)
294                                 return (EINVAL);
295
296                         /* Must set at least one of the load/store bits. */
297                         if ((ctrl & DBGWCR_LSC) == 0)
298                                 return (EINVAL);
299
300                         /*
301                          * When specifying the address range with BAS, the MASK
302                          * field must be zero.
303                          */
304                         if ((ctrl & DBGWCR_BAS) != DBGWCR_BAS &&
305                             (ctrl & DBGWCR_MASK) != 0)
306                                 return (EINVAL);
307
308                         monitor->dbg_enable_count++;
309                 }
310                 monitor->dbg_wvr[i] = addr;
311                 monitor->dbg_wcr[i] = ctrl;
312         }
313
314         if (monitor->dbg_enable_count > 0)
315                 monitor->dbg_flags |= DBGMON_ENABLED;
316
317         return (0);
318 }
319
320 #ifdef COMPAT_FREEBSD32
321 int
322 fill_regs32(struct thread *td, struct reg32 *regs)
323 {
324         int i;
325         struct trapframe *tf;
326
327         tf = td->td_frame;
328         for (i = 0; i < 13; i++)
329                 regs->r[i] = tf->tf_x[i];
330         /* For arm32, SP is r13 and LR is r14 */
331         regs->r_sp = tf->tf_x[13];
332         regs->r_lr = tf->tf_x[14];
333         regs->r_pc = tf->tf_elr;
334         regs->r_cpsr = tf->tf_spsr;
335
336         return (0);
337 }
338
339 int
340 set_regs32(struct thread *td, struct reg32 *regs)
341 {
342         int i;
343         struct trapframe *tf;
344
345         tf = td->td_frame;
346         for (i = 0; i < 13; i++)
347                 tf->tf_x[i] = regs->r[i];
348         /* For arm 32, SP is r13 an LR is r14 */
349         tf->tf_x[13] = regs->r_sp;
350         tf->tf_x[14] = regs->r_lr;
351         tf->tf_elr = regs->r_pc;
352         tf->tf_spsr &= ~PSR_SETTABLE_32;
353         tf->tf_spsr |= regs->r_cpsr & PSR_SETTABLE_32;
354
355         return (0);
356 }
357
358 /* XXX fill/set dbregs/fpregs are stubbed on 32-bit arm. */
359 int
360 fill_fpregs32(struct thread *td, struct fpreg32 *regs)
361 {
362
363         memset(regs, 0, sizeof(*regs));
364         return (0);
365 }
366
367 int
368 set_fpregs32(struct thread *td, struct fpreg32 *regs)
369 {
370
371         return (0);
372 }
373
374 int
375 fill_dbregs32(struct thread *td, struct dbreg32 *regs)
376 {
377
378         memset(regs, 0, sizeof(*regs));
379         return (0);
380 }
381
382 int
383 set_dbregs32(struct thread *td, struct dbreg32 *regs)
384 {
385
386         return (0);
387 }
388 #endif
389
390 void
391 exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
392 {
393         struct trapframe *tf = td->td_frame;
394         struct pcb *pcb = td->td_pcb;
395
396         memset(tf, 0, sizeof(struct trapframe));
397
398         tf->tf_x[0] = stack;
399         tf->tf_sp = STACKALIGN(stack);
400         tf->tf_lr = imgp->entry_addr;
401         tf->tf_elr = imgp->entry_addr;
402
403         td->td_pcb->pcb_tpidr_el0 = 0;
404         td->td_pcb->pcb_tpidrro_el0 = 0;
405         WRITE_SPECIALREG(tpidrro_el0, 0);
406         WRITE_SPECIALREG(tpidr_el0, 0);
407
408 #ifdef VFP
409         vfp_reset_state(td, pcb);
410 #endif
411
412         /*
413          * Clear debug register state. It is not applicable to the new process.
414          */
415         bzero(&pcb->pcb_dbg_regs, sizeof(pcb->pcb_dbg_regs));
416 }
417
418 /* Sanity check these are the same size, they will be memcpy'd to and from */
419 CTASSERT(sizeof(((struct trapframe *)0)->tf_x) ==
420     sizeof((struct gpregs *)0)->gp_x);
421 CTASSERT(sizeof(((struct trapframe *)0)->tf_x) ==
422     sizeof((struct reg *)0)->x);
423
424 int
425 get_mcontext(struct thread *td, mcontext_t *mcp, int clear_ret)
426 {
427         struct trapframe *tf = td->td_frame;
428
429         if (clear_ret & GET_MC_CLEAR_RET) {
430                 mcp->mc_gpregs.gp_x[0] = 0;
431                 mcp->mc_gpregs.gp_spsr = tf->tf_spsr & ~PSR_C;
432         } else {
433                 mcp->mc_gpregs.gp_x[0] = tf->tf_x[0];
434                 mcp->mc_gpregs.gp_spsr = tf->tf_spsr;
435         }
436
437         memcpy(&mcp->mc_gpregs.gp_x[1], &tf->tf_x[1],
438             sizeof(mcp->mc_gpregs.gp_x[1]) * (nitems(mcp->mc_gpregs.gp_x) - 1));
439
440         mcp->mc_gpregs.gp_sp = tf->tf_sp;
441         mcp->mc_gpregs.gp_lr = tf->tf_lr;
442         mcp->mc_gpregs.gp_elr = tf->tf_elr;
443         get_fpcontext(td, mcp);
444
445         return (0);
446 }
447
448 int
449 set_mcontext(struct thread *td, mcontext_t *mcp)
450 {
451         struct trapframe *tf = td->td_frame;
452         uint32_t spsr;
453
454         spsr = mcp->mc_gpregs.gp_spsr;
455         if ((spsr & PSR_M_MASK) != PSR_M_EL0t ||
456             (spsr & PSR_AARCH32) != 0 ||
457             (spsr & PSR_DAIF) != (td->td_frame->tf_spsr & PSR_DAIF))
458                 return (EINVAL); 
459
460         memcpy(tf->tf_x, mcp->mc_gpregs.gp_x, sizeof(tf->tf_x));
461
462         tf->tf_sp = mcp->mc_gpregs.gp_sp;
463         tf->tf_lr = mcp->mc_gpregs.gp_lr;
464         tf->tf_elr = mcp->mc_gpregs.gp_elr;
465         tf->tf_spsr = mcp->mc_gpregs.gp_spsr;
466         if ((tf->tf_spsr & PSR_SS) != 0) {
467                 td->td_pcb->pcb_flags |= PCB_SINGLE_STEP;
468
469                 WRITE_SPECIALREG(mdscr_el1,
470                     READ_SPECIALREG(mdscr_el1) | MDSCR_SS);
471                 isb();
472         }
473         set_fpcontext(td, mcp);
474
475         return (0);
476 }
477
478 static void
479 get_fpcontext(struct thread *td, mcontext_t *mcp)
480 {
481 #ifdef VFP
482         struct pcb *curpcb;
483
484         critical_enter();
485
486         curpcb = curthread->td_pcb;
487
488         if ((curpcb->pcb_fpflags & PCB_FP_STARTED) != 0) {
489                 /*
490                  * If we have just been running VFP instructions we will
491                  * need to save the state to memcpy it below.
492                  */
493                 vfp_save_state(td, curpcb);
494
495                 KASSERT(curpcb->pcb_fpusaved == &curpcb->pcb_fpustate,
496                     ("Called get_fpcontext while the kernel is using the VFP"));
497                 KASSERT((curpcb->pcb_fpflags & ~PCB_FP_USERMASK) == 0,
498                     ("Non-userspace FPU flags set in get_fpcontext"));
499                 memcpy(mcp->mc_fpregs.fp_q, curpcb->pcb_fpustate.vfp_regs,
500                     sizeof(mcp->mc_fpregs.fp_q));
501                 mcp->mc_fpregs.fp_cr = curpcb->pcb_fpustate.vfp_fpcr;
502                 mcp->mc_fpregs.fp_sr = curpcb->pcb_fpustate.vfp_fpsr;
503                 mcp->mc_fpregs.fp_flags = curpcb->pcb_fpflags;
504                 mcp->mc_flags |= _MC_FP_VALID;
505         }
506
507         critical_exit();
508 #endif
509 }
510
511 static void
512 set_fpcontext(struct thread *td, mcontext_t *mcp)
513 {
514 #ifdef VFP
515         struct pcb *curpcb;
516
517         critical_enter();
518
519         if ((mcp->mc_flags & _MC_FP_VALID) != 0) {
520                 curpcb = curthread->td_pcb;
521
522                 /*
523                  * Discard any vfp state for the current thread, we
524                  * are about to override it.
525                  */
526                 vfp_discard(td);
527
528                 KASSERT(curpcb->pcb_fpusaved == &curpcb->pcb_fpustate,
529                     ("Called set_fpcontext while the kernel is using the VFP"));
530                 memcpy(curpcb->pcb_fpustate.vfp_regs, mcp->mc_fpregs.fp_q,
531                     sizeof(mcp->mc_fpregs.fp_q));
532                 curpcb->pcb_fpustate.vfp_fpcr = mcp->mc_fpregs.fp_cr;
533                 curpcb->pcb_fpustate.vfp_fpsr = mcp->mc_fpregs.fp_sr;
534                 curpcb->pcb_fpflags = mcp->mc_fpregs.fp_flags & PCB_FP_USERMASK;
535         }
536
537         critical_exit();
538 #endif
539 }
540
541 int
542 sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
543 {
544         ucontext_t uc;
545         int error;
546
547         if (copyin(uap->sigcntxp, &uc, sizeof(uc)))
548                 return (EFAULT);
549
550         error = set_mcontext(td, &uc.uc_mcontext);
551         if (error != 0)
552                 return (error);
553
554         /* Restore signal mask. */
555         kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
556
557         return (EJUSTRETURN);
558 }
559
560 void
561 sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
562 {
563         struct thread *td;
564         struct proc *p;
565         struct trapframe *tf;
566         struct sigframe *fp, frame;
567         struct sigacts *psp;
568         int onstack, sig;
569
570         td = curthread;
571         p = td->td_proc;
572         PROC_LOCK_ASSERT(p, MA_OWNED);
573
574         sig = ksi->ksi_signo;
575         psp = p->p_sigacts;
576         mtx_assert(&psp->ps_mtx, MA_OWNED);
577
578         tf = td->td_frame;
579         onstack = sigonstack(tf->tf_sp);
580
581         CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
582             catcher, sig);
583
584         /* Allocate and validate space for the signal handler context. */
585         if ((td->td_pflags & TDP_ALTSTACK) != 0 && !onstack &&
586             SIGISMEMBER(psp->ps_sigonstack, sig)) {
587                 fp = (struct sigframe *)((uintptr_t)td->td_sigstk.ss_sp +
588                     td->td_sigstk.ss_size);
589 #if defined(COMPAT_43)
590                 td->td_sigstk.ss_flags |= SS_ONSTACK;
591 #endif
592         } else {
593                 fp = (struct sigframe *)td->td_frame->tf_sp;
594         }
595
596         /* Make room, keeping the stack aligned */
597         fp--;
598         fp = (struct sigframe *)STACKALIGN(fp);
599
600         /* Fill in the frame to copy out */
601         bzero(&frame, sizeof(frame));
602         get_mcontext(td, &frame.sf_uc.uc_mcontext, 0);
603         frame.sf_si = ksi->ksi_info;
604         frame.sf_uc.uc_sigmask = *mask;
605         frame.sf_uc.uc_stack = td->td_sigstk;
606         frame.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK) != 0 ?
607             (onstack ? SS_ONSTACK : 0) : SS_DISABLE;
608         mtx_unlock(&psp->ps_mtx);
609         PROC_UNLOCK(td->td_proc);
610
611         /* Copy the sigframe out to the user's stack. */
612         if (copyout(&frame, fp, sizeof(*fp)) != 0) {
613                 /* Process has trashed its stack. Kill it. */
614                 CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td, fp);
615                 PROC_LOCK(p);
616                 sigexit(td, SIGILL);
617         }
618
619         tf->tf_x[0] = sig;
620         tf->tf_x[1] = (register_t)&fp->sf_si;
621         tf->tf_x[2] = (register_t)&fp->sf_uc;
622
623         tf->tf_elr = (register_t)catcher;
624         tf->tf_sp = (register_t)fp;
625         tf->tf_lr = (register_t)p->p_sysent->sv_sigcode_base;
626
627         /* Clear the single step flag while in the signal handler */
628         if ((td->td_pcb->pcb_flags & PCB_SINGLE_STEP) != 0) {
629                 td->td_pcb->pcb_flags &= ~PCB_SINGLE_STEP;
630                 WRITE_SPECIALREG(mdscr_el1,
631                     READ_SPECIALREG(mdscr_el1) & ~MDSCR_SS);
632                 isb();
633         }
634
635         CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td, tf->tf_elr,
636             tf->tf_sp);
637
638         PROC_LOCK(p);
639         mtx_lock(&psp->ps_mtx);
640 }