2 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
3 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by TooLs GmbH.
17 * 4. The name of TooLs GmbH may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * Copyright (C) 2001 Benno Rice
33 * All rights reserved.
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 * notice, this list of conditions and the following disclaimer in the
42 * documentation and/or other materials provided with the distribution.
44 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
45 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
47 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
49 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
50 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
51 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
52 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
53 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 * $NetBSD: machdep.c,v 1.74.2.1 2000/11/01 16:13:48 tv Exp $
57 #include <sys/cdefs.h>
58 __FBSDID("$FreeBSD$");
60 #include "opt_compat.h"
62 #include <sys/param.h>
64 #include <sys/systm.h>
71 #include <sys/imgact.h>
72 #include <sys/kernel.h>
75 #include <sys/malloc.h>
76 #include <sys/mutex.h>
77 #include <sys/signalvar.h>
78 #include <sys/syscallsubr.h>
79 #include <sys/syscall.h>
80 #include <sys/sysent.h>
81 #include <sys/sysproto.h>
82 #include <sys/ucontext.h>
85 #include <machine/altivec.h>
86 #include <machine/cpu.h>
87 #include <machine/elf.h>
88 #include <machine/fpu.h>
89 #include <machine/pcb.h>
90 #include <machine/reg.h>
91 #include <machine/sigframe.h>
92 #include <machine/trap.h>
93 #include <machine/vmparam.h>
95 static int grab_mcontext(struct thread *, mcontext_t *, int);
98 sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
100 struct trapframe *tf;
107 int oonstack, rndfsize;
113 PROC_LOCK_ASSERT(p, MA_OWNED);
116 mtx_assert(&psp->ps_mtx, MA_OWNED);
118 oonstack = sigonstack(tf->fixreg[1]);
121 * Fill siginfo structure.
123 ksi->ksi_info.si_signo = ksi->ksi_signo;
125 ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ?
126 tf->cpu.aim.dar : tf->srr0);
128 ksi->ksi_info.si_addr = (void *)((tf->exc == EXC_DSI) ?
129 tf->cpu.booke.dear : tf->srr0);
132 sig = ksi->ksi_signo;
133 code = ksi->ksi_code;
135 sfpsize = sizeof(sf);
136 rndfsize = ((sizeof(sf) + 15) / 16) * 16;
142 memset(&sf, 0, sizeof(sf));
143 grab_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
145 sf.sf_uc.uc_sigmask = *mask;
146 sf.sf_uc.uc_stack = td->td_sigstk;
147 sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
148 ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
150 sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
152 CTR4(KTR_SIG, "sendsig: td=%p (%s) catcher=%p sig=%d", td, p->p_comm,
156 * Allocate and validate space for the signal handler context.
158 if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
159 SIGISMEMBER(psp->ps_sigonstack, sig)) {
160 usfp = (void *)(td->td_sigstk.ss_sp +
161 td->td_sigstk.ss_size - rndfsize);
163 usfp = (void *)(tf->fixreg[1] - rndfsize);
167 * Translate the signal if appropriate (Linux emu ?)
169 if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize)
170 sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)];
173 * Save the floating-point state, if necessary, then copy it.
178 * Set up the registers to return to sigcode.
180 * r1/sp - sigframe ptr
181 * lr - sig function, dispatched to by blrl in trampoline
183 * r4 - SIGINFO ? &siginfo : exception code
185 * srr0 - trampoline function addr
187 tf->lr = (register_t)catcher;
188 tf->fixreg[1] = (register_t)usfp;
189 tf->fixreg[FIRSTARG] = sig;
190 tf->fixreg[FIRSTARG+2] = (register_t)usfp +
191 offsetof(struct sigframe, sf_uc);
192 if (SIGISMEMBER(psp->ps_siginfo, sig)) {
194 * Signal handler installed with SA_SIGINFO.
196 tf->fixreg[FIRSTARG+1] = (register_t)usfp +
197 offsetof(struct sigframe, sf_si);
198 sf.sf_si = ksi->ksi_info;
200 /* Old FreeBSD-style arguments. */
201 tf->fixreg[FIRSTARG+1] = code;
203 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ?
204 tf->cpu.aim.dar : tf->srr0;
206 tf->fixreg[FIRSTARG+3] = (tf->exc == EXC_DSI) ?
207 tf->cpu.booke.dear : tf->srr0;
210 mtx_unlock(&psp->ps_mtx);
213 tf->srr0 = (register_t)(p->p_sysent->sv_psstrings -
214 *(p->p_sysent->sv_szsigcode));
217 * copy the frame out to userland.
219 if (copyout(sfp, usfp, sfpsize) != 0) {
221 * Process has trashed its stack. Kill it.
223 CTR2(KTR_SIG, "sendsig: sigexit td=%p sfp=%p", td, sfp);
228 CTR3(KTR_SIG, "sendsig: return td=%p pc=%#x sp=%#x", td,
229 tf->srr0, tf->fixreg[1]);
232 mtx_lock(&psp->ps_mtx);
236 sigreturn(struct thread *td, struct sigreturn_args *uap)
241 CTR2(KTR_SIG, "sigreturn: td=%p ucp=%p", td, uap->sigcntxp);
243 if (copyin(uap->sigcntxp, &uc, sizeof(uc)) != 0) {
244 CTR1(KTR_SIG, "sigreturn: efault td=%p", td);
248 error = set_mcontext(td, &uc.uc_mcontext);
252 kern_sigprocmask(td, SIG_SETMASK, &uc.uc_sigmask, NULL, 0);
254 CTR3(KTR_SIG, "sigreturn: return td=%p pc=%#x sp=%#x",
255 td, uc.uc_mcontext.mc_srr0, uc.uc_mcontext.mc_gpr[1]);
257 return (EJUSTRETURN);
260 #ifdef COMPAT_FREEBSD4
262 freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
265 return sigreturn(td, (struct sigreturn_args *)uap);
270 * Construct a PCB from a trapframe. This is called from kdb_trap() where
271 * we want to start a backtrace from the function that caused us to enter
272 * the debugger. We have the context in the trapframe, but base the trace
273 * on the PCB. The PCB doesn't have to be perfect, as long as it contains
274 * enough for a backtrace.
277 makectx(struct trapframe *tf, struct pcb *pcb)
280 pcb->pcb_lr = tf->srr0;
281 pcb->pcb_sp = tf->fixreg[1];
285 * get_mcontext/sendsig helper routine that doesn't touch the
289 grab_mcontext(struct thread *td, mcontext_t *mcp, int flags)
295 memset(mcp, 0, sizeof(mcontext_t));
297 mcp->mc_vers = _MC_VERSION;
299 memcpy(&mcp->mc_frame, td->td_frame, sizeof(struct trapframe));
300 if (flags & GET_MC_CLEAR_RET) {
307 * This assumes that floating-point context is *not* lazy,
308 * so if the thread has used FP there would have been a
309 * FP-unavailable exception that would have set things up
312 if (pcb->pcb_flags & PCB_FPU) {
313 KASSERT(td == curthread,
314 ("get_mcontext: fp save not curthread"));
318 mcp->mc_flags |= _MC_FP_VALID;
319 memcpy(&mcp->mc_fpscr, &pcb->pcb_fpu.fpscr, sizeof(double));
320 memcpy(mcp->mc_fpreg, pcb->pcb_fpu.fpr, 32*sizeof(double));
324 * Repeat for Altivec context
327 if (pcb->pcb_flags & PCB_VEC) {
328 KASSERT(td == curthread,
329 ("get_mcontext: fp save not curthread"));
333 mcp->mc_flags |= _MC_AV_VALID;
334 mcp->mc_vscr = pcb->pcb_vec.vscr;
335 mcp->mc_vrsave = pcb->pcb_vec.vrsave;
336 memcpy(mcp->mc_avec, pcb->pcb_vec.vr, sizeof(mcp->mc_avec));
340 mcp->mc_len = sizeof(*mcp);
346 get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
350 error = grab_mcontext(td, mcp, flags);
352 PROC_LOCK(curthread->td_proc);
353 mcp->mc_onstack = sigonstack(td->td_frame->fixreg[1]);
354 PROC_UNLOCK(curthread->td_proc);
361 set_mcontext(struct thread *td, const mcontext_t *mcp)
364 struct trapframe *tf;
369 if (mcp->mc_vers != _MC_VERSION || mcp->mc_len != sizeof(*mcp))
374 * Don't let the user set privileged MSR bits
376 if ((mcp->mc_srr1 & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) {
381 memcpy(tf, mcp->mc_frame, sizeof(mcp->mc_frame));
384 if (mcp->mc_flags & _MC_FP_VALID) {
385 if ((pcb->pcb_flags & PCB_FPU) != PCB_FPU) {
390 memcpy(&pcb->pcb_fpu.fpscr, &mcp->mc_fpscr, sizeof(double));
391 memcpy(pcb->pcb_fpu.fpr, mcp->mc_fpreg, 32*sizeof(double));
394 if (mcp->mc_flags & _MC_AV_VALID) {
395 if ((pcb->pcb_flags & PCB_VEC) != PCB_VEC) {
400 pcb->pcb_vec.vscr = mcp->mc_vscr;
401 pcb->pcb_vec.vrsave = mcp->mc_vrsave;
402 memcpy(pcb->pcb_vec.vr, mcp->mc_avec, sizeof(mcp->mc_avec));
410 * Set set up registers on exec.
413 exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
415 struct trapframe *tf;
419 bzero(tf, sizeof *tf);
420 tf->fixreg[1] = -roundup(-stack + 8, 16);
423 * Set up arguments for _start():
424 * _start(argc, argv, envp, obj, cleanup, ps_strings);
427 * - obj and cleanup are the auxilliary and termination
428 * vectors. They are fixed up by ld.elf_so.
429 * - ps_strings is a NetBSD extention, and will be
430 * ignored by executables which are strictly
431 * compliant with the SVR4 ABI.
433 * XXX We have to set both regs and retval here due to different
434 * XXX calling convention in trap.c and init_main.c.
437 /* Collect argc from the user stack */
438 argc = fuword((void *)stack);
441 * XXX PG: these get overwritten in the syscall return code.
442 * execve() should return EJUSTRETURN, like it does on NetBSD.
443 * Emulate by setting the syscall return value cells. The
444 * registers still have to be set for init's fork trampoline.
446 td->td_retval[0] = argc;
447 td->td_retval[1] = stack + sizeof(register_t);
448 tf->fixreg[3] = argc;
449 tf->fixreg[4] = stack + sizeof(register_t);
450 tf->fixreg[5] = stack + (2 + argc)*sizeof(register_t);
451 tf->fixreg[6] = 0; /* auxillary vector */
452 tf->fixreg[7] = 0; /* termination vector */
453 tf->fixreg[8] = (register_t)ps_strings; /* NetBSD extension */
456 tf->srr1 = PSL_USERSET | PSL_FE_DFLT;
457 td->td_pcb->pcb_flags = 0;
462 fill_regs(struct thread *td, struct reg *regs)
464 struct trapframe *tf;
467 memcpy(regs, tf, sizeof(struct reg));
473 fill_dbregs(struct thread *td, struct dbreg *dbregs)
475 /* No debug registers on PowerPC */
480 fill_fpregs(struct thread *td, struct fpreg *fpregs)
486 if ((pcb->pcb_flags & PCB_FPU) == 0)
487 memset(fpregs, 0, sizeof(struct fpreg));
489 memcpy(fpregs, &pcb->pcb_fpu, sizeof(struct fpreg));
495 set_regs(struct thread *td, struct reg *regs)
497 struct trapframe *tf;
500 memcpy(tf, regs, sizeof(struct reg));
506 set_dbregs(struct thread *td, struct dbreg *dbregs)
508 /* No debug registers on PowerPC */
513 set_fpregs(struct thread *td, struct fpreg *fpregs)
519 if ((pcb->pcb_flags & PCB_FPU) == 0)
521 memcpy(&pcb->pcb_fpu, fpregs, sizeof(struct fpreg));
530 cpu_set_syscall_retval(struct thread *td, int error)
533 struct trapframe *tf;
536 if (error == EJUSTRETURN)
542 if (tf->fixreg[0] == SYS___syscall) {
543 int code = tf->fixreg[FIRSTARG + 1];
544 if (p->p_sysent->sv_mask)
545 code &= p->p_sysent->sv_mask;
546 fixup = (code != SYS_freebsd6_lseek && code != SYS_lseek) ?
555 * 64-bit return, 32-bit syscall. Fixup byte order
557 tf->fixreg[FIRSTARG] = 0;
558 tf->fixreg[FIRSTARG + 1] = td->td_retval[0];
560 tf->fixreg[FIRSTARG] = td->td_retval[0];
561 tf->fixreg[FIRSTARG + 1] = td->td_retval[1];
563 tf->cr &= ~0x10000000; /* Unset summary overflow */
567 * Set user's pc back to redo the system call.
572 if (p->p_sysent->sv_errsize) {
573 error = (error < p->p_sysent->sv_errsize) ?
574 p->p_sysent->sv_errtbl[error] : -1;
576 tf->fixreg[FIRSTARG] = error;
577 tf->cr |= 0x10000000; /* Set summary overflow */
583 * Threading functions
586 cpu_thread_exit(struct thread *td)
591 cpu_thread_clean(struct thread *td)
596 cpu_thread_alloc(struct thread *td)
600 pcb = (struct pcb *)((td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
601 sizeof(struct pcb)) & ~0x2fUL);
603 td->td_frame = (struct trapframe *)pcb - 1;
607 cpu_thread_free(struct thread *td)
612 cpu_set_user_tls(struct thread *td, void *tls_base)
615 td->td_frame->fixreg[2] = (register_t)tls_base + 0x7008;
620 cpu_set_upcall(struct thread *td, struct thread *td0)
623 struct trapframe *tf;
624 struct callframe *cf;
628 /* Copy the upcall pcb */
629 bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
631 /* Create a stack for the new thread */
633 bcopy(td0->td_frame, tf, sizeof(struct trapframe));
634 tf->fixreg[FIRSTARG] = 0;
635 tf->fixreg[FIRSTARG + 1] = 0;
636 tf->cr &= ~0x10000000;
638 /* Set registers for trampoline to user mode. */
639 cf = (struct callframe *)tf - 1;
640 memset(cf, 0, sizeof(struct callframe));
641 cf->cf_func = (register_t)fork_return;
642 cf->cf_arg0 = (register_t)td;
643 cf->cf_arg1 = (register_t)tf;
645 pcb2->pcb_sp = (register_t)cf;
646 pcb2->pcb_lr = (register_t)fork_trampoline;
647 pcb2->pcb_cpu.aim.usr = 0;
649 /* Setup to release spin count in fork_exit(). */
650 td->td_md.md_spinlock_count = 1;
651 td->td_md.md_saved_msr = PSL_KERNSET;
655 cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
658 struct trapframe *tf;
662 /* align stack and alloc space for frame ptr and saved LR */
663 sp = ((uintptr_t)stack->ss_sp + stack->ss_size - 8) &
665 bzero(tf, sizeof(struct trapframe));
667 tf->fixreg[1] = (register_t)sp;
668 tf->fixreg[3] = (register_t)arg;
669 tf->srr0 = (register_t)entry;
671 tf->srr1 = PSL_MBO | PSL_USERSET | PSL_FE_DFLT;
673 tf->srr1 = PSL_USERSET;
676 td->td_pcb->pcb_flags = 0;
678 td->td_retval[0] = (register_t)entry;
679 td->td_retval[1] = 0;