1 /* $NetBSD: linux_machdep.c,v 1.40 2009/03/18 17:06:48 cegger Exp $ */
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.40 2009/03/18 17:06:48 cegger Exp $");
35 #define COMPAT_LINUX 1
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
42 #include <sys/ioctl.h>
43 #include <sys/mount.h>
44 #include <sys/signal.h>
45 #include <sys/signalvar.h>
46 #include <sys/syscallargs.h>
47 #include <sys/kauth.h>
50 #include <machine/reg.h>
52 #include <compat/linux/common/linux_types.h>
53 #include <compat/linux/common/linux_signal.h>
54 #include <compat/linux/common/linux_ioctl.h>
55 #include <compat/linux/common/linux_exec.h>
56 #include <compat/linux/common/linux_machdep.h>
58 #include <compat/linux/linux_syscall.h>
59 #include <compat/linux/linux_syscallargs.h>
61 /* XXX should be in an include file somewhere */
65 #define CC_EXTPURGE 0x80000000
66 /* XXX end should be */
68 extern short exframesize
[];
73 #define SDB_FOLLOW 0x01
74 #define SDB_KSTACK 0x02
75 #define SDB_FPSTATE 0x04
78 void setup_linux_sigframe(struct frame
*frame
, int sig
,
79 const sigset_t
*mask
, void *usp
);
80 void setup_linux_rt_sigframe(struct frame
*frame
, int sig
,
81 const sigset_t
*mask
, void *usp
, struct lwp
*l
);
84 * Deal with some m68k-specific things in the Linux emulation code.
88 * Setup registers on program execution.
91 linux_setregs(struct lwp
*l
, struct exec_package
*epp
, u_long stack
)
94 setregs(l
, epp
, stack
);
98 * Setup signal frame for old signal interface.
101 setup_linux_sigframe(struct frame
*frame
, int sig
, const sigset_t
*mask
, void *usp
)
103 struct lwp
*l
= curlwp
;
104 struct proc
*p
= l
->l_proc
;
105 struct linux_sigframe
*fp
, kf
;
109 ft
= frame
->f_format
;
111 /* Allocate space for the signal handler context on the user stack. */
112 fp
= (struct linux_sigframe
*) usp
;
116 if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
117 printf("setup_linux_sigframe(%d): sig %d ssp %p usp %p scp %p ft %d\n",
118 p
->p_pid
, sig
, &ft
, fp
, &fp
->sf_c
.c_sc
, ft
);
121 /* Build stack frame. */
122 kf
.sf_psigtramp
= fp
->sf_sigtramp
; /* return addr for handler */
123 kf
.sf_signum
= native_to_linux_signo
[sig
];
124 kf
.sf_code
= frame
->f_vector
; /* Does anyone use it? */
125 kf
.sf_scp
= &fp
->sf_c
.c_sc
;
127 /* The sigtramp code is on the stack frame on Linux/m68k. */
128 kf
.sf_sigtramp
[0] = LINUX_SF_SIGTRAMP0
;
129 kf
.sf_sigtramp
[1] = LINUX_SF_SIGTRAMP1
;
132 * Save necessary hardware state. Currently this includes:
133 * - scratch registers
134 * - original exception frame (if not a "normal" frame)
135 * - FP coprocessor state
137 kf
.sf_c
.c_sc
.sc_d0
= frame
->f_regs
[D0
];
138 kf
.sf_c
.c_sc
.sc_d1
= frame
->f_regs
[D1
];
139 kf
.sf_c
.c_sc
.sc_a0
= frame
->f_regs
[A0
];
140 kf
.sf_c
.c_sc
.sc_a1
= frame
->f_regs
[A1
];
142 /* Clear for security (and initialize ss_format). */
143 memset(&kf
.sf_c
.c_sc
.sc_ss
, 0, sizeof kf
.sf_c
.c_sc
.sc_ss
);
147 if (ft
> 15 || exframesize
[ft
] < 0)
148 panic("setup_linux_sigframe: bogus frame type");
150 kf
.sf_c
.c_sc
.sc_ss
.ss_format
= ft
;
151 kf
.sf_c
.c_sc
.sc_ss
.ss_vector
= frame
->f_vector
;
152 memcpy( &kf
.sf_c
.c_sc
.sc_ss
.ss_frame
, &frame
->F_u
,
153 (size_t) exframesize
[ft
]);
155 * Leave an indicator that we need to clean up the kernel
156 * stack. We do this by setting the "pad word" above the
157 * hardware stack frame to the amount the stack must be
160 * N.B. we increment rather than just set f_stackadj in
161 * case we are called from syscall when processing a
162 * sigreturn. In that case, f_stackadj may be non-zero.
164 frame
->f_stackadj
+= exframesize
[ft
];
165 frame
->f_format
= frame
->f_vector
= 0;
167 if (sigdebug
& SDB_FOLLOW
)
168 printf("setup_linux_sigframe(%d): copy out %d of frame %d\n",
169 p
->p_pid
, exframesize
[ft
], ft
);
178 __asm("fsave %0" : "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.FPF_u1
)
180 if (((struct fpframe060
*)&kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.FPF_u1
)
181 ->fpf6_frmfmt
!= FPF6_FMT_NULL
) {
182 __asm("fmovem %%fp0-%%fp1,%0" :
183 "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.fpf_regs
[0][0]));
185 * On 060, "fmovem fpcr/fpsr/fpi,<ea>" is
186 * emulated by software and slow.
188 __asm("fmovem %%fpcr,%0; fmovem %%fpsr,%1; fmovem %%fpi,%2" :
189 "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.fpf_fpcr
),
190 "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.fpf_fpsr
),
191 "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.fpf_fpiar
));
196 __asm("fsave %0" : "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.FPF_u1
)
198 if (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.fpf_version
) {
199 __asm("fmovem %%fp0-%%fp1,%0; fmovem %%fpcr/%%fpsr/%%fpi,%1" :
200 "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.fpf_regs
[0][0]),
201 "=m" (kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
.fpf_fpcr
)
207 if ((sigdebug
& SDB_FPSTATE
) && *(char *)&kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
)
208 printf("setup_linux_sigframe(%d): copy out FP state (%x) to %p\n",
209 p
->p_pid
, *(u_int
*)&kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
,
210 &kf
.sf_c
.c_sc
.sc_ss
.ss_fpstate
);
213 /* Build the signal context to be used by sigreturn. */
214 #if LINUX__NSIG_WORDS > 1
215 native_to_linux_old_extra_sigset(&kf
.sf_c
.c_sc
.sc_mask
,
216 kf
.sf_c
.c_extrasigmask
, mask
);
218 native_to_linux_old_sigset(&kf
.sf_c
.c_sc
.sc_mask
, mask
);
220 kf
.sf_c
.c_sc
.sc_sp
= frame
->f_regs
[SP
];
221 kf
.sf_c
.c_sc
.sc_pc
= frame
->f_pc
;
222 kf
.sf_c
.c_sc
.sc_ps
= frame
->f_sr
;
223 sendsig_reset(l
, sig
);
225 mutex_exit(p
->p_lock
);
226 error
= copyout(&kf
, fp
, sizeof(struct linux_sigframe
));
227 mutex_enter(p
->p_lock
);
231 if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
232 printf("setup_linux_sigframe(%d): copyout failed on sig %d\n",
236 * Process has trashed its stack; give it a segmentation
237 * violation to halt it in its tracks.
244 * The signal trampoline is on the signal frame.
245 * Clear the instruction cache in case of cached.
247 cachectl1(CC_EXTPURGE
| CC_IPURGE
,
248 (vaddr_t
) fp
->sf_sigtramp
, sizeof fp
->sf_sigtramp
, p
);
250 /* Set up the user stack pointer. */
251 frame
->f_regs
[SP
] = (int)fp
;
254 if (sigdebug
& SDB_FOLLOW
)
255 printf("setup_linux_sigframe(%d): sig %d scp %p fp %p sc_sp %x\n",
256 p
->p_pid
, sig
, kf
.sf_scp
, fp
, kf
.sf_c
.c_sc
.sc_sp
);
261 * Setup signal frame for new RT signal interface.
264 setup_linux_rt_sigframe(struct frame
*frame
, int sig
, const sigset_t
*mask
, void *usp
, struct lwp
*l
)
266 struct proc
*p
= l
->l_proc
;
267 struct linux_rt_sigframe
*fp
, kf
;
271 ft
= frame
->f_format
;
273 /* Allocate space for the signal handler context on the user stack. */
274 fp
= (struct linux_rt_sigframe
*) usp
;
278 if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
279 printf("setup_linux_rt_sigframe(%d): sig %d ssp %p usp %p ucp %p ft %d\n",
280 p
->p_pid
, sig
, &ft
, fp
, &fp
->sf_uc
, ft
);
283 /* Build stack frame. */
284 kf
.sf_psigtramp
= fp
->sf_sigtramp
; /* return addr for handler */
285 kf
.sf_signum
= native_to_linux_signo
[sig
];
286 kf
.sf_pinfo
= &fp
->sf_info
;
287 kf
.sf_puc
= &fp
->sf_uc
;
289 /* The sigtramp code is on the stack frame on Linux/m68k. */
290 kf
.sf_sigtramp
[0] = LINUX_RT_SF_SIGTRAMP0
;
291 kf
.sf_sigtramp
[1] = LINUX_RT_SF_SIGTRAMP1
;
293 /* clear for security (and initialize uc_flags, ss_format, etc.). */
294 memset(&kf
.sf_uc
, 0, sizeof(struct linux_ucontext
));
297 * Save necessary hardware state. Currently this includes:
298 * - general registers
299 * - original exception frame (if not a "normal" frame)
300 * - FP coprocessor state
302 /* version of mcontext */
303 kf
.sf_uc
.uc_mc
.mc_version
= LINUX_MCONTEXT_VERSION
;
305 /* general registers and pc/sr */
306 memcpy( kf
.sf_uc
.uc_mc
.mc_gregs
.gr_regs
, frame
->f_regs
, sizeof(u_int
)*16);
307 kf
.sf_uc
.uc_mc
.mc_gregs
.gr_pc
= frame
->f_pc
;
308 kf
.sf_uc
.uc_mc
.mc_gregs
.gr_sr
= frame
->f_sr
;
312 if (ft
> 15 || exframesize
[ft
] < 0)
313 panic("setup_linux_rt_sigframe: bogus frame type");
315 kf
.sf_uc
.uc_ss
.ss_format
= ft
;
316 kf
.sf_uc
.uc_ss
.ss_vector
= frame
->f_vector
;
317 memcpy( &kf
.sf_uc
.uc_ss
.ss_frame
, &frame
->F_u
,
318 (size_t) exframesize
[ft
]);
320 * Leave an indicator that we need to clean up the kernel
321 * stack. We do this by setting the "pad word" above the
322 * hardware stack frame to the amount the stack must be
325 * N.B. we increment rather than just set f_stackadj in
326 * case we are called from syscall when processing a
327 * sigreturn. In that case, f_stackadj may be non-zero.
329 frame
->f_stackadj
+= exframesize
[ft
];
330 frame
->f_format
= frame
->f_vector
= 0;
332 if (sigdebug
& SDB_FOLLOW
)
333 printf("setup_linux_rt_sigframe(%d): copy out %d of frame %d\n",
334 p
->p_pid
, exframesize
[ft
], ft
);
343 __asm("fsave %0" : "=m" (kf
.sf_uc
.uc_ss
.ss_fpstate
));
344 /* See note below. */
345 if (((struct fpframe060
*) &kf
.sf_uc
.uc_ss
.ss_fpstate
.FPF_u1
)
346 ->fpf6_frmfmt
!= FPF6_FMT_NULL
) {
347 __asm("fmovem %%fp0-%%fp7,%0" :
348 "=m" (kf
.sf_uc
.uc_mc
.mc_fpregs
.fpr_regs
[0][0]));
350 * On 060, "fmovem fpcr/fpsr/fpi,<ea>" is
351 * emulated by software and slow.
353 __asm("fmovem %%fpcr,%0; fmovem %%fpsr,%1; fmovem %%fpi,%2" :
354 "=m" (kf
.sf_uc
.uc_mc
.mc_fpregs
.fpr_fpcr
),
355 "=m" (kf
.sf_uc
.uc_mc
.mc_fpregs
.fpr_fpsr
),
356 "=m" (kf
.sf_uc
.uc_mc
.mc_fpregs
.fpr_fpiar
));
362 * NOTE: We give whole of the "struct linux_rt_fpframe"
363 * to the __asm("fsave") argument; not the FPF_u1 element only.
364 * Unlike the non-RT version of this structure,
365 * this contains only the FPU state used by "fsave"
366 * (and whole of the information is in the structure).
367 * This gives the correct dependency information to the __asm(),
368 * and no "memory" is required to the ``clobberd'' list.
370 __asm("fsave %0" : "=m" (kf
.sf_uc
.uc_ss
.ss_fpstate
));
371 if (kf
.sf_uc
.uc_ss
.ss_fpstate
.fpf_version
) {
372 __asm("fmovem %%fp0-%%fp7,%0; fmovem %%fpcr/%%fpsr/%%fpi,%1" :
373 "=m" (kf
.sf_uc
.uc_mc
.mc_fpregs
.fpr_regs
[0][0]),
374 "=m" (kf
.sf_uc
.uc_mc
.mc_fpregs
.fpr_fpcr
)
380 if ((sigdebug
& SDB_FPSTATE
) && *(char *)&kf
.sf_uc
.uc_ss
.ss_fpstate
)
381 printf("setup_linux_rt_sigframe(%d): copy out FP state (%x) to %p\n",
382 p
->p_pid
, *(u_int
*)&kf
.sf_uc
.uc_ss
.ss_fpstate
,
383 &kf
.sf_uc
.uc_ss
.ss_fpstate
);
387 * XXX XAX Create bogus siginfo data. This can't really
388 * XXX be fixed until NetBSD has realtime signals.
389 * XXX Or we do the emuldata thing.
392 memset(&kf
.sf_info
, 0, sizeof(struct linux_siginfo
));
393 kf
.sf_info
.lsi_signo
= sig
;
394 kf
.sf_info
.lsi_code
= LINUX_SI_USER
;
395 kf
.sf_info
.lsi_pid
= p
->p_pid
;
396 kf
.sf_info
.lsi_uid
= kauth_cred_geteuid(l
->l_cred
); /* Use real uid here? */
398 /* Build the signal context to be used by sigreturn. */
399 native_to_linux_sigset(&kf
.sf_uc
.uc_sigmask
, mask
);
400 kf
.sf_uc
.uc_stack
.ss_sp
= l
->l_sigstk
.ss_sp
;
401 kf
.sf_uc
.uc_stack
.ss_flags
=
402 (l
->l_sigstk
.ss_flags
& SS_ONSTACK
? LINUX_SS_ONSTACK
: 0) |
403 (l
->l_sigstk
.ss_flags
& SS_DISABLE
? LINUX_SS_DISABLE
: 0);
404 kf
.sf_uc
.uc_stack
.ss_size
= l
->l_sigstk
.ss_size
;
405 sendsig_reset(l
, sig
);
407 mutex_exit(p
->p_lock
);
408 error
= copyout(&kf
, fp
, sizeof(struct linux_rt_sigframe
));
409 mutex_enter(p
->p_lock
);
413 if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
414 printf("setup_linux_rt_sigframe(%d): copyout failed on sig %d\n",
418 * Process has trashed its stack; give it a segmentation
419 * violation to halt it in its tracks.
426 * The signal trampoline is on the signal frame.
427 * Clear the instruction cache in case of cached.
429 cachectl1(CC_EXTPURGE
| CC_IPURGE
,
430 (vaddr_t
) fp
->sf_sigtramp
, sizeof fp
->sf_sigtramp
, p
);
432 /* Set up the user stack pointer. */
433 frame
->f_regs
[SP
] = (int)fp
;
436 if (sigdebug
& SDB_FOLLOW
)
437 printf("setup_linux_rt_sigframe(%d): sig %d puc %p fp %p sc_sp %x\n",
438 p
->p_pid
, sig
, kf
.sf_puc
, fp
,
439 kf
.sf_uc
.uc_mc
.mc_gregs
.gr_regs
[SP
]);
444 * Send an interrupt to Linux process.
447 linux_sendsig(const ksiginfo_t
*ksi
, const sigset_t
*mask
)
449 /* u_long code = ksi->ksi_trap; */
450 int sig
= ksi
->ksi_signo
;
451 struct lwp
*l
= curlwp
;
452 struct proc
*p
= l
->l_proc
;
453 struct frame
*frame
= (struct frame
*)l
->l_md
.md_regs
;
455 /* user stack for signal context */
456 void *usp
= getframe(l
, sig
, &onstack
);
457 sig_t catcher
= SIGACTION(p
, sig
).sa_handler
;
459 /* Setup the signal frame (and part of the trapframe). */
460 if (SIGACTION(p
, sig
).sa_flags
& SA_SIGINFO
)
461 setup_linux_rt_sigframe(frame
, sig
, mask
, usp
, l
);
463 setup_linux_sigframe(frame
, sig
, mask
, usp
);
465 /* Call the signal handler. */
466 frame
->f_pc
= (u_int
) catcher
;
468 /* Remember that we're now on the signal stack. */
470 l
->l_sigstk
.ss_flags
|= SS_ONSTACK
;
473 if ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
)
474 printf("linux_sendsig(%d): sig %d returns\n",
480 * The linux_sys_sigreturn and linux_sys_rt_sigreturn
481 * system calls cleanup state after a signal
482 * has been taken. Reset signal mask and stack
483 * state from context left by linux_sendsig (above).
484 * Return to previous pc and psl as specified by
485 * context left by linux_sendsig. Check carefully to
486 * make sure that the user has not modified the
487 * psl to gain improper privileges or to cause
490 * Note that the sigreturn system calls of Linux/m68k
491 * do not return on errors, but issue segmentation
492 * violation and terminate the process.
496 linux_sys_sigreturn(struct lwp
*l
, const void *v
, register_t
*retval
)
498 struct proc
*p
= l
->l_proc
;
500 struct linux_sigc2 tsigc2
; /* extra mask and sigcontext */
501 struct linux_sigcontext
*scp
; /* pointer to sigcontext */
503 int sz
= 0; /* extra frame size */
507 * sigreturn of Linux/m68k takes no arguments.
508 * The user stack points at struct linux_sigc2.
510 frame
= (struct frame
*) l
->l_md
.md_regs
;
511 usp
= frame
->f_regs
[SP
];
516 if (sigdebug
& SDB_FOLLOW
)
517 printf("linux_sys_sigreturn: pid %d, usp %p\n",
518 p
->p_pid
, (void *) usp
);
521 /* Grab whole of the sigcontext. */
522 if (copyin((void *) usp
, &tsigc2
, sizeof tsigc2
)) {
524 mutex_enter(p
->p_lock
);
531 * Check kernel stack and re-enter to syscall() if needed.
533 if ((sz
= scp
->sc_ss
.ss_format
) != 0) {
534 if ((sz
= exframesize
[sz
]) < 0)
536 if (sz
&& frame
->f_stackadj
== 0) {
538 * Extra stack space is required but not allocated.
539 * Allocate and re-enter syscall().
541 reenter_syscall(frame
, sz
);
546 /* reenter_syscall() doesn't adjust stack. */
547 if (sz
!= frame
->f_stackadj
)
548 panic("linux_sys_sigreturn: adj: %d != %d",
549 sz
, frame
->f_stackadj
);
552 mutex_enter(p
->p_lock
);
554 /* Restore signal stack. */
555 l
->l_sigstk
.ss_flags
&= ~SS_ONSTACK
;
557 /* Restore signal mask. */
558 #if LINUX__NSIG_WORDS > 1
559 linux_old_extra_to_native_sigset(&mask
, &scp
->sc_mask
,
560 tsigc2
.c_extrasigmask
);
562 linux_old_to_native_sigset(&scp
->sc_mask
, &mask
);
564 (void) sigprocmask1(l
, SIG_SETMASK
, &mask
, 0);
566 mutex_exit(p
->p_lock
);
569 * Restore the user supplied information.
571 frame
->f_regs
[SP
] = scp
->sc_sp
;
572 frame
->f_regs
[D0
] = scp
->sc_d0
;
573 frame
->f_regs
[D1
] = scp
->sc_d1
;
574 frame
->f_regs
[A0
] = scp
->sc_a0
;
575 frame
->f_regs
[A1
] = scp
->sc_a1
;
576 frame
->f_pc
= scp
->sc_pc
;
577 /* Privileged bits of sr are silently ignored on Linux/m68k. */
578 frame
->f_sr
= scp
->sc_ps
& ~(PSL_MBZ
|PSL_IPL
|PSL_S
);
580 * Other registers are assumed to be unchanged,
585 * Restore long stack frames. Note that we do not copy
586 * back the saved SR or PC, they were picked up above from
587 * the sigcontext structure.
589 if (scp
->sc_ss
.ss_format
) {
590 frame
->f_format
= scp
->sc_ss
.ss_format
;
591 frame
->f_vector
= scp
->sc_ss
.ss_vector
;
592 if (frame
->f_stackadj
< sz
) /* just in case... */
594 frame
->f_stackadj
-= sz
;
595 memcpy( &frame
->F_u
, &scp
->sc_ss
.ss_frame
, sz
);
597 if (sigdebug
& SDB_FOLLOW
)
598 printf("linux_sys_sigreturn(%d): copy in %d of frame type %d\n",
599 p
->p_pid
, sz
, scp
->sc_ss
.ss_format
);
604 * Finally we restore the original FP context.
611 if (((struct fpframe060
*)&scp
->sc_ss
.ss_fpstate
.FPF_u1
)
612 ->fpf6_frmfmt
!= FPF6_FMT_NULL
) {
614 * On 060, "fmovem <ea>,fpcr/fpsr/fpi" is
615 * emulated by software and slow.
617 __asm("fmovem %0,%%fpcr; fmovem %1,%%fpsr; fmovem %2,%%fpi"::
618 "m" (scp
->sc_ss
.ss_fpstate
.fpf_fpcr
),
619 "m" (scp
->sc_ss
.ss_fpstate
.fpf_fpsr
),
620 "m" (scp
->sc_ss
.ss_fpstate
.fpf_fpiar
));
621 __asm("fmovem %0,%%fp0-%%fp1" : :
622 "m" (scp
->sc_ss
.ss_fpstate
.fpf_regs
[0][0]));
624 __asm("frestore %0" : : "m" (scp
->sc_ss
.ss_fpstate
.FPF_u1
));
628 if (scp
->sc_ss
.ss_fpstate
.fpf_version
) {
629 __asm("fmovem %0,%%fpcr/%%fpsr/%%fpi; fmovem %1,%%fp0-%%fp1"::
630 "m" (scp
->sc_ss
.ss_fpstate
.fpf_fpcr
),
631 "m" (scp
->sc_ss
.ss_fpstate
.fpf_regs
[0][0]));
633 __asm("frestore %0" : : "m" (scp
->sc_ss
.ss_fpstate
.FPF_u1
));
638 if ((sigdebug
& SDB_FPSTATE
) && *(char *)&scp
->sc_ss
.ss_fpstate
)
639 printf("linux_sys_sigreturn(%d): copied in FP state (%x) at %p\n",
640 p
->p_pid
, *(u_int
*)&scp
->sc_ss
.ss_fpstate
,
641 &scp
->sc_ss
.ss_fpstate
);
642 if ((sigdebug
& SDB_FOLLOW
) ||
643 ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
))
644 printf("linux_sys_sigreturn(%d): returns\n", p
->p_pid
);
652 linux_sys_rt_sigreturn(struct lwp
*l
, const void *v
, register_t
*retval
)
654 struct proc
*p
= l
->l_proc
;
656 struct linux_ucontext
*ucp
; /* ucontext in user space */
657 struct linux_ucontext tuc
; /* copy of *ucp */
659 int sz
= 0, error
; /* extra frame size */
662 * rt_sigreturn of Linux/m68k takes no arguments.
663 * usp + 4 is a pointer to siginfo structure,
664 * usp + 8 is a pointer to ucontext structure.
666 frame
= (struct frame
*) l
->l_md
.md_regs
;
667 error
= copyin((char *)frame
->f_regs
[SP
] + 8, (void *)&ucp
,
669 if (error
|| (int) ucp
& 1)
670 goto bad
; /* error or odd address */
673 if (sigdebug
& SDB_FOLLOW
)
674 printf("linux_rt_sigreturn: pid %d, ucp %p\n", p
->p_pid
, ucp
);
677 /* Grab whole of the ucontext. */
678 if (copyin(ucp
, &tuc
, sizeof tuc
)) {
680 mutex_enter(p
->p_lock
);
685 * Check kernel stack and re-enter to syscall() if needed.
687 if ((sz
= tuc
.uc_ss
.ss_format
) != 0) {
688 if ((sz
= exframesize
[sz
]) < 0)
690 if (sz
&& frame
->f_stackadj
== 0) {
692 * Extra stack space is required but not allocated.
693 * Allocate and re-enter syscall().
695 reenter_syscall(frame
, sz
);
700 /* reenter_syscall() doesn't adjust stack. */
701 if (sz
!= frame
->f_stackadj
)
702 panic("linux_sys_rt_sigreturn: adj: %d != %d",
703 sz
, frame
->f_stackadj
);
706 if (tuc
.uc_mc
.mc_version
!= LINUX_MCONTEXT_VERSION
)
709 mutex_enter(p
->p_lock
);
711 /* Restore signal stack. */
712 l
->l_sigstk
.ss_flags
=
713 (l
->l_sigstk
.ss_flags
& ~SS_ONSTACK
) |
714 (tuc
.uc_stack
.ss_flags
& LINUX_SS_ONSTACK
? SS_ONSTACK
: 0);
716 /* Restore signal mask. */
717 linux_to_native_sigset(&mask
, &tuc
.uc_sigmask
);
718 (void) sigprocmask1(l
, SIG_SETMASK
, &mask
, 0);
720 mutex_exit(p
->p_lock
);
723 * Restore the user supplied information.
725 memcpy( frame
->f_regs
, tuc
.uc_mc
.mc_gregs
.gr_regs
, sizeof(u_int
)*16);
726 frame
->f_pc
= tuc
.uc_mc
.mc_gregs
.gr_pc
;
727 /* Privileged bits of sr are silently ignored on Linux/m68k. */
728 frame
->f_sr
= tuc
.uc_mc
.mc_gregs
.gr_sr
& ~(PSL_MBZ
|PSL_IPL
|PSL_S
);
731 * Restore long stack frames. Note that we do not copy
732 * back the saved SR or PC, they were picked up above from
733 * the ucontext structure.
735 if (tuc
.uc_ss
.ss_format
) {
736 frame
->f_format
= tuc
.uc_ss
.ss_format
;
737 frame
->f_vector
= tuc
.uc_ss
.ss_vector
;
738 if (frame
->f_stackadj
< sz
) /* just in case... */
740 frame
->f_stackadj
-= sz
;
741 memcpy( &frame
->F_u
, &tuc
.uc_ss
.ss_frame
, sz
);
743 if (sigdebug
& SDB_FOLLOW
)
744 printf("linux_sys_rt_sigreturn(%d): copy in %d of frame type %d\n",
745 p
->p_pid
, sz
, tuc
.uc_ss
.ss_format
);
750 * Finally we restore the original FP context.
757 if (((struct fpframe060
*)&tuc
.uc_ss
.ss_fpstate
.FPF_u1
)
758 ->fpf6_frmfmt
!= FPF6_FMT_NULL
) {
760 * On 060, "fmovem <ea>,fpcr/fpsr/fpi" is
761 * emulated by software and slow.
763 __asm("fmovem %0,%%fpcr; fmovem %1,%%fpsr; fmovem %2,%%fpi"::
764 "m" (tuc
.uc_mc
.mc_fpregs
.fpr_fpcr
),
765 "m" (tuc
.uc_mc
.mc_fpregs
.fpr_fpsr
),
766 "m" (tuc
.uc_mc
.mc_fpregs
.fpr_fpiar
));
767 __asm("fmovem %0,%%fp0-%%fp1" : :
768 "m" (tuc
.uc_mc
.mc_fpregs
.fpr_regs
[0][0]));
770 __asm("frestore %0" : : "m" (tuc
.uc_ss
.ss_fpstate
.FPF_u1
));
774 if (tuc
.uc_ss
.ss_fpstate
.fpf_version
) {
775 __asm("fmovem %0,%%fpcr/%%fpsr/%%fpi; fmovem %1,%%fp0-%%fp1"::
776 "m" (tuc
.uc_mc
.mc_fpregs
.fpr_fpcr
),
777 "m" (tuc
.uc_mc
.mc_fpregs
.fpr_regs
[0][0]));
779 __asm("frestore %0" : : "m" (tuc
.uc_ss
.ss_fpstate
.FPF_u1
));
784 if ((sigdebug
& SDB_FPSTATE
) && *(char *)&tuc
.uc_ss
.ss_fpstate
)
785 printf("linux_rt_sigreturn(%d): copied in FP state (%x) at %p\n",
786 p
->p_pid
, *(u_int
*)&tuc
.uc_ss
.ss_fpstate
,
787 &tuc
.uc_ss
.ss_fpstate
);
788 if ((sigdebug
& SDB_FOLLOW
) ||
789 ((sigdebug
& SDB_KSTACK
) && p
->p_pid
== sigpid
))
790 printf("linux_rt_sigreturn(%d): returns\n", p
->p_pid
);
797 * MPU cache operation of Linux/m68k,
798 * mainly used for dynamic linking.
802 #define LINUX_FLUSH_SCOPE_LINE 1 /* a cache line */
803 #define LINUX_FLUSH_SCOPE_PAGE 2 /* a page */
804 #define LINUX_FLUSH_SCOPE_ALL 3 /* the whole cache */
806 #define LINUX_FLUSH_CACHE_DATA 1 /* flush and purge data cache */
807 #define LINUX_FLUSH_CACHE_INSN 2 /* purge instruction cache */
808 #define LINUX_FLUSH_CACHE_BOTH 3 /* both */
812 linux_sys_cacheflush(struct lwp
*l
, const struct linux_sys_cacheflush_args
*uap
, register_t
*retval
)
815 syscallarg(unsigned long) addr;
816 syscallarg(int) scope;
817 syscallarg(int) cache;
818 syscallarg(unsigned long) len;
820 struct proc
*p
= l
->l_proc
;
826 scope
= SCARG(uap
, scope
);
827 cache
= SCARG(uap
, cache
);
829 if (scope
< LINUX_FLUSH_SCOPE_LINE
|| scope
> LINUX_FLUSH_SCOPE_ALL
830 || cache
& ~LINUX_FLUSH_CACHE_BOTH
)
833 #if defined(M68040) || defined(M68060)
834 addr
= (vaddr_t
) SCARG(uap
, addr
);
835 len
= (int) SCARG(uap
, len
);
838 * We always flush entire cache on 68020/030
839 * and these values are not used afterwards.
846 * LINUX_FLUSH_SCOPE_ALL (flush whole cache) is limited to super users.
848 if (scope
== LINUX_FLUSH_SCOPE_ALL
) {
849 if ((error
= kauth_authorize_machdep(l
->l_cred
,
850 KAUTH_MACHDEP_CACHEFLUSH
, NULL
, NULL
, NULL
, NULL
)) != 0)
852 #if defined(M68040) || defined(M68060)
859 if (cache
& LINUX_FLUSH_CACHE_DATA
)
860 if ((error
= cachectl1(CC_EXTPURGE
|CC_PURGE
, addr
, len
, p
)) !=0)
862 if (cache
& LINUX_FLUSH_CACHE_INSN
)
863 error
= cachectl1(CC_EXTPURGE
|CC_IPURGE
, addr
, len
, p
);
869 * Convert NetBSD's devices to Linux's.
872 linux_fakedev(dev_t dev
, int raw
)
875 /* do nothing for now */
880 * We come here in a last attempt to satisfy a Linux ioctl() call.
883 linux_machdepioctl(struct lwp
*l
, const struct linux_sys_ioctl_args
*uap
, register_t
*retval
)
887 syscallarg(u_long) com;
888 syscallarg(void *) data;
890 struct sys_ioctl_args bia
;
893 SCARG(&bia
, fd
) = SCARG(uap
, fd
);
894 SCARG(&bia
, data
) = SCARG(uap
, data
);
895 com
= SCARG(uap
, com
);
899 /* do nothing for now */
902 printf("linux_machdepioctl: invalid ioctl %08lx\n", com
);
905 SCARG(&bia
, com
) = com
;
906 return sys_ioctl(l
, &bia
, retval
);
910 linux_usertrap(struct lwp
*l
, vaddr_t trapaddr
, void *arg
)