Home | History | Annotate | Line # | Download | only in m68k
linux_machdep.c revision 1.1
      1 /*	$NetBSD: linux_machdep.c,v 1.1 1998/12/15 19:25:40 itohy Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by ITOH Yasufumi.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     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.
     18  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *	This product includes software developed by the NetBSD
     21  *	Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/param.h>
     40 #include <sys/systm.h>
     41 #include <sys/kernel.h>
     42 #include <sys/proc.h>
     43 #include <sys/exec.h>
     44 #include <sys/ioctl.h>
     45 #include <sys/mount.h>
     46 #include <sys/signal.h>
     47 #include <sys/signalvar.h>
     48 #include <sys/syscallargs.h>
     49 
     50 #include <machine/cpu.h>
     51 #include <machine/reg.h>
     52 
     53 #include <compat/linux/common/linux_types.h>
     54 #include <compat/linux/common/linux_signal.h>
     55 #include <compat/linux/common/linux_ioctl.h>
     56 #include <compat/linux/common/linux_exec.h>
     57 #include <compat/linux/common/linux_machdep.h>
     58 
     59 #include <compat/linux/linux_syscall.h>
     60 #include <compat/linux/linux_syscallargs.h>
     61 
     62 /* XXX should be in an include file somewhere */
     63 #define CC_PURGE	1
     64 #define CC_FLUSH	2
     65 #define CC_IPURGE	4
     66 #define CC_EXTPURGE	0x80000000
     67 /* XXX end should be */
     68 
     69 extern short exframesize[];
     70 
     71 #ifdef DEBUG
     72 extern int sigdebug;
     73 extern int sigpid;
     74 #define SDB_FOLLOW	0x01
     75 #define SDB_KSTACK	0x02
     76 #define SDB_FPSTATE	0x04
     77 #endif
     78 
     79 void setup_linux_sigframe __P((struct frame *frame, int sig, sigset_t *mask,
     80 				caddr_t usp));
     81 void setup_linux_rt_sigframe __P((struct frame *frame, int sig, sigset_t *mask,
     82 				caddr_t usp, struct sigacts *psp));
     83 
     84 /*
     85  * Deal with some m68k-specific things in the Linux emulation code.
     86  */
     87 
     88 /*
     89  * Setup registers on program execution.
     90  */
     91 void
     92 linux_setregs(p, epp, stack)
     93 	struct proc *p;
     94 	struct exec_package *epp;
     95 	u_long stack;
     96 {
     97 
     98 	setregs(p, epp, stack);
     99 }
    100 
    101 /*
    102  * Setup signal frame for old signal interface.
    103  */
    104 void
    105 setup_linux_sigframe(frame, sig, mask, usp)
    106 	struct frame *frame;
    107 	int sig;
    108 	sigset_t *mask;
    109 	caddr_t usp;
    110 {
    111 	struct proc *p = curproc;
    112 	struct linux_sigframe *fp, kf;
    113 	short ft;
    114 
    115 	ft = frame->f_format;
    116 
    117 	/* Allocate space for the signal handler context on the user stack. */
    118 	fp = (struct linux_sigframe *) usp;
    119 	fp--;
    120 
    121 #ifdef DEBUG
    122 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
    123 		printf("setup_linux_sigframe(%d): sig %d ssp %p usp %p scp %p ft %d\n",
    124 		       p->p_pid, sig, &ft, fp, &fp->sf_c.c_sc, ft);
    125 #endif
    126 
    127 	/* Build stack frame. */
    128 	kf.sf_psigtramp = fp->sf_sigtramp;	/* return addr for handler */
    129 	kf.sf_signum = native_to_linux_sig[sig];
    130 	kf.sf_code = frame->f_vector;		/* Does anyone use it? */
    131 	kf.sf_scp = &fp->sf_c.c_sc;
    132 
    133 	/* The sigtramp code is on the stack frame on Linux/m68k. */
    134 	kf.sf_sigtramp[0] = LINUX_SF_SIGTRAMP0;
    135 	kf.sf_sigtramp[1] = LINUX_SF_SIGTRAMP1;
    136 
    137 	/*
    138 	 * Save necessary hardware state.  Currently this includes:
    139 	 *	- scratch registers
    140 	 *	- original exception frame (if not a "normal" frame)
    141 	 *	- FP coprocessor state
    142 	 */
    143 	kf.sf_c.c_sc.sc_d0 = frame->f_regs[D0];
    144 	kf.sf_c.c_sc.sc_d1 = frame->f_regs[D1];
    145 	kf.sf_c.c_sc.sc_a0 = frame->f_regs[A0];
    146 	kf.sf_c.c_sc.sc_a1 = frame->f_regs[A1];
    147 
    148 	/* Clear for security (and initialize ss_format). */
    149 	bzero(&kf.sf_c.c_sc.sc_ss, sizeof kf.sf_c.c_sc.sc_ss);
    150 
    151 	if (ft >= FMT4) {
    152 #ifdef DEBUG
    153 		if (ft > 15 || exframesize[ft] < 0)
    154 			panic("setup_linux_sigframe: bogus frame type");
    155 #endif
    156 		kf.sf_c.c_sc.sc_ss.ss_format = ft;
    157 		kf.sf_c.c_sc.sc_ss.ss_vector = frame->f_vector;
    158 		bcopy(&frame->F_u, &kf.sf_c.c_sc.sc_ss.ss_frame,
    159 			(size_t) exframesize[ft]);
    160 		/*
    161 		 * Leave an indicator that we need to clean up the kernel
    162 		 * stack.  We do this by setting the "pad word" above the
    163 		 * hardware stack frame to the amount the stack must be
    164 		 * adjusted by.
    165 		 *
    166 		 * N.B. we increment rather than just set f_stackadj in
    167 		 * case we are called from syscall when processing a
    168 		 * sigreturn.  In that case, f_stackadj may be non-zero.
    169 		 */
    170 		frame->f_stackadj += exframesize[ft];
    171 		frame->f_format = frame->f_vector = 0;
    172 #ifdef DEBUG
    173 		if (sigdebug & SDB_FOLLOW)
    174 			printf("setup_linux_sigframe(%d): copy out %d of frame %d\n",
    175 			       p->p_pid, exframesize[ft], ft);
    176 #endif
    177 	}
    178 
    179 	switch (fputype) {
    180 	case FPU_NONE:
    181 		break;
    182 #ifdef M68060
    183 	case FPU_68060:
    184 		asm("fsave %0" : "=m" (kf.sf_c.c_sc.sc_ss.ss_fpstate.FPF_u1)
    185 			: : "memory");
    186 		if (((struct fpframe060 *)&kf.sf_c.c_sc.sc_ss.ss_fpstate.FPF_u1)
    187 					->fpf6_frmfmt != FPF6_FMT_NULL) {
    188 			asm("fmovem fp0-fp1,%0" :
    189 				"=m" (*kf.sf_c.c_sc.sc_ss.ss_fpstate.fpf_regs));
    190 			/*
    191 			 * On 060,  "fmovem fpcr/fpsr/fpi,<ea>"  is
    192 			 * emulated by software and slow.
    193 			 */
    194 			asm("fmovem fpcr,%0; fmovem fpsr,%1; fmovem fpi,%2" :
    195 				"=m" (kf.sf_c.c_sc.sc_ss.ss_fpstate.fpf_fpcr),
    196 				"=m" (kf.sf_c.c_sc.sc_ss.ss_fpstate.fpf_fpsr),
    197 				"=m" (kf.sf_c.c_sc.sc_ss.ss_fpstate.fpf_fpiar));
    198 		}
    199 		break;
    200 #endif
    201 	default:
    202 		asm("fsave %0" : "=m" (kf.sf_c.c_sc.sc_ss.ss_fpstate.FPF_u1)
    203 			: : "memory");
    204 		if (kf.sf_c.c_sc.sc_ss.ss_fpstate.fpf_version) {
    205 			asm("fmovem fp0-fp1,%0; fmovem fpcr/fpsr/fpi,%1" :
    206 				"=m" (*kf.sf_c.c_sc.sc_ss.ss_fpstate.fpf_regs),
    207 				"=m" (kf.sf_c.c_sc.sc_ss.ss_fpstate.fpf_fpcr)
    208 				: : "memory");
    209 		}
    210 		break;
    211 	}
    212 #ifdef DEBUG
    213 	if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_c.c_sc.sc_ss.ss_fpstate)
    214 		printf("setup_linux_sigframe(%d): copy out FP state (%x) to %p\n",
    215 		       p->p_pid, *(u_int *)&kf.sf_c.c_sc.sc_ss.ss_fpstate,
    216 		       &kf.sf_c.c_sc.sc_ss.ss_fpstate);
    217 #endif
    218 
    219 	/* Build the signal context to be used by sigreturn. */
    220 #if LINUX__NSIG_WORDS > 1
    221 	native_to_linux_old_extra_sigset(mask,
    222 			&kf.sf_c.c_sc.sc_mask, kf.sf_c.c_extrasigmask);
    223 #else
    224 	native_to_linux_old_sigset(mask, &kf.sf_c.c_sc.sc_mask);
    225 #endif
    226 	kf.sf_c.c_sc.sc_sp = frame->f_regs[SP];
    227 	kf.sf_c.c_sc.sc_pc = frame->f_pc;
    228 	kf.sf_c.c_sc.sc_ps = frame->f_sr;
    229 
    230 	if (copyout(&kf, fp, sizeof(struct linux_sigframe))) {
    231 #ifdef DEBUG
    232 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
    233 			printf("setup_linux_sigframe(%d): copyout failed on sig %d\n",
    234 			       p->p_pid, sig);
    235 #endif
    236 		/*
    237 		 * Process has trashed its stack; give it a segmentation
    238 		 * violation to halt it in its tracks.
    239 		 */
    240 		sigexit(p, SIGSEGV);
    241 		/* NOTREACHED */
    242 	}
    243 
    244 	/*
    245 	 * The signal trampoline is on the signal frame.
    246 	 * Clear the instruction cache in case of cached.
    247 	 */
    248 	cachectl(CC_EXTPURGE | CC_IPURGE,
    249 			(caddr_t) fp->sf_sigtramp, sizeof fp->sf_sigtramp);
    250 
    251 	/* Set up the user stack pointer. */
    252 	frame->f_regs[SP] = (int)fp;
    253 
    254 #ifdef DEBUG
    255 	if (sigdebug & SDB_FOLLOW)
    256 		printf("setup_linux_sigframe(%d): sig %d scp %p fp %p sc_sp %x\n",
    257 		       p->p_pid, sig, kf.sf_scp, fp, kf.sf_c.c_sc.sc_sp);
    258 #endif
    259 }
    260 
    261 /*
    262  * Setup signal frame for new RT signal interface.
    263  */
    264 void
    265 setup_linux_rt_sigframe(frame, sig, mask, usp, psp)
    266 	struct frame *frame;
    267 	int sig;
    268 	sigset_t *mask;
    269 	caddr_t usp;
    270 	struct sigacts *psp;
    271 {
    272 	struct proc *p = curproc;
    273 	struct linux_rt_sigframe *fp, kf;
    274 	short ft;
    275 
    276 	ft = frame->f_format;
    277 
    278 	/* Allocate space for the signal handler context on the user stack. */
    279 	fp = (struct linux_rt_sigframe *) usp;
    280 	fp--;
    281 
    282 #ifdef DEBUG
    283 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
    284 		printf("setup_linux_rt_sigframe(%d): sig %d ssp %p usp %p ucp %p ft %d\n",
    285 		       p->p_pid, sig, &ft, fp, &fp->sf_uc, ft);
    286 #endif
    287 
    288 	/* Build stack frame. */
    289 	kf.sf_psigtramp = fp->sf_sigtramp;	/* return addr for handler */
    290 	kf.sf_signum = native_to_linux_sig[sig];
    291 	kf.sf_pinfo = &fp->sf_info;
    292 	kf.sf_puc = &fp->sf_uc;
    293 
    294 	/* The sigtramp code is on the stack frame on Linux/m68k. */
    295 	kf.sf_sigtramp[0] = LINUX_RT_SF_SIGTRAMP0;
    296 	kf.sf_sigtramp[1] = LINUX_RT_SF_SIGTRAMP1;
    297 
    298 	/* clear for security (and initialize uc_flags, ss_format, etc.). */
    299 	bzero(&kf.sf_uc, sizeof(struct linux_ucontext));
    300 
    301 	/*
    302 	 * Save necessary hardware state.  Currently this includes:
    303 	 *	- general registers
    304 	 *	- original exception frame (if not a "normal" frame)
    305 	 *	- FP coprocessor state
    306 	 */
    307 	/* version of mcontext */
    308 	kf.sf_uc.uc_mc.mc_version = LINUX_MCONTEXT_VERSION;
    309 
    310 	/* general registers and pc/sr */
    311 	bcopy(frame->f_regs, kf.sf_uc.uc_mc.mc_gregs.gr_regs, sizeof(u_int)*16);
    312 	kf.sf_uc.uc_mc.mc_gregs.gr_pc = frame->f_pc;
    313 	kf.sf_uc.uc_mc.mc_gregs.gr_sr = frame->f_sr;
    314 
    315 	if (ft >= FMT4) {
    316 #ifdef DEBUG
    317 		if (ft > 15 || exframesize[ft] < 0)
    318 			panic("setup_linux_rt_sigframe: bogus frame type");
    319 #endif
    320 		kf.sf_uc.uc_ss.ss_format = ft;
    321 		kf.sf_uc.uc_ss.ss_vector = frame->f_vector;
    322 		bcopy(&frame->F_u, &kf.sf_uc.uc_ss.ss_frame,
    323 			(size_t) exframesize[ft]);
    324 		/*
    325 		 * Leave an indicator that we need to clean up the kernel
    326 		 * stack.  We do this by setting the "pad word" above the
    327 		 * hardware stack frame to the amount the stack must be
    328 		 * adjusted by.
    329 		 *
    330 		 * N.B. we increment rather than just set f_stackadj in
    331 		 * case we are called from syscall when processing a
    332 		 * sigreturn.  In that case, f_stackadj may be non-zero.
    333 		 */
    334 		frame->f_stackadj += exframesize[ft];
    335 		frame->f_format = frame->f_vector = 0;
    336 #ifdef DEBUG
    337 		if (sigdebug & SDB_FOLLOW)
    338 			printf("setup_linux_rt_sigframe(%d): copy out %d of frame %d\n",
    339 			       p->p_pid, exframesize[ft], ft);
    340 #endif
    341 	}
    342 
    343 	switch (fputype) {
    344 	case FPU_NONE:
    345 		break;
    346 #ifdef M68060
    347 	case FPU_68060:
    348 		asm("fsave %0" : "=m" (kf.sf_uc.uc_ss.ss_fpstate));
    349 				/* See note below. */
    350 		if (((struct fpframe060 *) &kf.sf_uc.uc_ss.ss_fpstate.FPF_u1)
    351 					->fpf6_frmfmt != FPF6_FMT_NULL) {
    352 			asm("fmovem fp0-fp7,%0" :
    353 				"=m" (*kf.sf_uc.uc_mc.mc_fpregs.fpr_regs));
    354 			/*
    355 			 * On 060,  "fmovem fpcr/fpsr/fpi,<ea>"  is
    356 			 * emulated by software and slow.
    357 			 */
    358 			asm("fmovem fpcr,%0; fmovem fpsr,%1; fmovem fpi,%2" :
    359 				"=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpcr),
    360 				"=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpsr),
    361 				"=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpiar));
    362 		}
    363 		break;
    364 #endif
    365 	default:
    366 		/*
    367 		 * NOTE:  We give whole of the  "struct linux_rt_fpframe"
    368 		 * to the asm("fsave") argument; not the FPF_u1 element only.
    369 		 * Unlike the non-RT version of this structure,
    370 		 * this contains only the FPU state used by "fsave"
    371 		 * (and whole of the information is in the structure).
    372 		 * This gives the correct dependency information to the asm(),
    373 		 * and no "memory" is required to the ``clobberd'' list.
    374 		 */
    375 		asm("fsave %0" : "=m" (kf.sf_uc.uc_ss.ss_fpstate));
    376 		if (kf.sf_uc.uc_ss.ss_fpstate.fpf_version) {
    377 			asm("fmovem fp0-fp7,%0; fmovem fpcr/fpsr/fpi,%1" :
    378 				"=m" (*kf.sf_uc.uc_mc.mc_fpregs.fpr_regs),
    379 				"=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpcr)
    380 				: : "memory");
    381 		}
    382 		break;
    383 	}
    384 #ifdef DEBUG
    385 	if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_uc.uc_ss.ss_fpstate)
    386 		printf("setup_linux_rt_sigframe(%d): copy out FP state (%x) to %p\n",
    387 		       p->p_pid, *(u_int *)&kf.sf_uc.uc_ss.ss_fpstate,
    388 		       &kf.sf_uc.uc_ss.ss_fpstate);
    389 #endif
    390 
    391 	/*
    392 	 * XXX XAX Create bogus siginfo data.  This can't really
    393 	 * XXX be fixed until NetBSD has realtime signals.
    394 	 * XXX Or we do the emuldata thing.
    395 	 * XXX -erh
    396 	 */
    397 	bzero(&kf.sf_info, sizeof(struct linux_siginfo));
    398 	kf.sf_info.si_signo = sig;
    399 	kf.sf_info.si_code = LINUX_SI_USER;
    400 	kf.sf_info.si_pid = p->p_pid;
    401 	kf.sf_info.si_uid = p->p_ucred->cr_uid;	/* Use real uid here? */
    402 
    403 	/* Build the signal context to be used by sigreturn. */
    404 	native_to_linux_sigset(mask, &kf.sf_uc.uc_sigmask);
    405 	kf.sf_uc.uc_stack.ss_sp = psp->ps_sigstk.ss_sp;
    406 	kf.sf_uc.uc_stack.ss_flags =
    407 		(psp->ps_sigstk.ss_flags & SS_ONSTACK ? LINUX_SS_ONSTACK : 0) |
    408 		(psp->ps_sigstk.ss_flags & SS_DISABLE ? LINUX_SS_DISABLE : 0);
    409 	kf.sf_uc.uc_stack.ss_size = psp->ps_sigstk.ss_size;
    410 
    411 	if (copyout(&kf, fp, sizeof(struct linux_rt_sigframe))) {
    412 #ifdef DEBUG
    413 		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
    414 			printf("setup_linux_rt_sigframe(%d): copyout failed on sig %d\n",
    415 			       p->p_pid, sig);
    416 #endif
    417 		/*
    418 		 * Process has trashed its stack; give it a segmentation
    419 		 * violation to halt it in its tracks.
    420 		 */
    421 		sigexit(p, SIGSEGV);
    422 		/* NOTREACHED */
    423 	}
    424 
    425 	/*
    426 	 * The signal trampoline is on the signal frame.
    427 	 * Clear the instruction cache in case of cached.
    428 	 */
    429 	cachectl(CC_EXTPURGE | CC_IPURGE,
    430 			(caddr_t) fp->sf_sigtramp, sizeof fp->sf_sigtramp);
    431 
    432 	/* Set up the user stack pointer. */
    433 	frame->f_regs[SP] = (int)fp;
    434 
    435 #ifdef DEBUG
    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]);
    440 #endif
    441 }
    442 
    443 /*
    444  * Send an interrupt to Linux process.
    445  */
    446 void
    447 linux_sendsig(catcher, sig, mask, code)
    448 	sig_t catcher;
    449 	int sig;
    450 	sigset_t *mask;
    451 	u_long code;
    452 {
    453 	struct proc *p = curproc;
    454 	struct frame *frame;
    455 	struct sigacts *psp = p->p_sigacts;
    456 	caddr_t usp;		/* user stack for signal context */
    457 	int onstack;
    458 
    459 	frame = (struct frame *)p->p_md.md_regs;
    460 
    461 	/* Do we need to jump onto the signal stack? */
    462 	onstack = (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
    463 		  (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0;
    464 
    465 	/* Determine user stack for the signal handler context. */
    466 	if (onstack)
    467 		usp = (caddr_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size;
    468 	else
    469 		usp = (caddr_t)frame->f_regs[SP];
    470 
    471 	/* Setup the signal frame (and part of the trapframe). */
    472 	if (p->p_sigacts->ps_sigact[sig].sa_flags & SA_SIGINFO)
    473 		setup_linux_rt_sigframe(frame, sig, mask, usp, psp);
    474 	else
    475 		setup_linux_sigframe(frame, sig, mask, usp);
    476 
    477 	/* Call the signal handler. */
    478 	frame->f_pc = (u_int) catcher;
    479 
    480 	/* Remember that we're now on the signal stack. */
    481 	if (onstack)
    482 		psp->ps_sigstk.ss_flags |= SS_ONSTACK;
    483 
    484 #ifdef DEBUG
    485 	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
    486 		printf("linux_sendsig(%d): sig %d returns\n",
    487 		       p->p_pid, sig);
    488 #endif
    489 }
    490 
    491 /*
    492  * The linux_sys_sigreturn and linux_sys_rt_sigreturn
    493  * system calls cleanup state after a signal
    494  * has been taken.  Reset signal mask and stack
    495  * state from context left by linux_sendsig (above).
    496  * Return to previous pc and psl as specified by
    497  * context left by linux_sendsig. Check carefully to
    498  * make sure that the user has not modified the
    499  * psl to gain improper privileges or to cause
    500  * a machine fault.
    501  *
    502  * Note that the sigreturn system calls of Linux/m68k
    503  * do not return on errors, but issue segmentation
    504  * violation and terminate the process.
    505  */
    506 /* ARGSUSED */
    507 int
    508 linux_sys_sigreturn(p, v, retval)
    509 	struct proc *p;
    510 	void *v;
    511 	register_t *retval;
    512 {
    513 	struct frame *frame;
    514 	struct linux_sigc2 tsigc2;	/* extra mask and sigcontext */
    515 	struct linux_sigcontext *scp;	/* pointer to sigcontext */
    516 	sigset_t mask;
    517 	int sz = 0;			/* extra frame size */
    518 	int usp;
    519 
    520 	/*
    521 	 * sigreturn of Linux/m68k takes no arguments.
    522 	 * The user stack points at struct linux_sigc2.
    523 	 */
    524 	frame = (struct frame *) p->p_md.md_regs;
    525 	usp = frame->f_regs[SP];
    526 	if (usp & 1)
    527 		goto bad;
    528 
    529 #ifdef DEBUG
    530 	if (sigdebug & SDB_FOLLOW)
    531 		printf("linux_sys_sigreturn: pid %d, usp %p\n",
    532 			p->p_pid, (caddr_t) usp);
    533 #endif
    534 
    535 	/* Grab whole of the sigcontext. */
    536 	if (copyin((caddr_t) usp, &tsigc2, sizeof tsigc2))
    537 bad:		sigexit(p, SIGSEGV);
    538 
    539 	scp = &tsigc2.c_sc;
    540 
    541 	/*
    542 	 * Check kernel stack and re-enter to syscall() if needed.
    543 	 */
    544 	if ((sz = scp->sc_ss.ss_format) != 0) {
    545 		if ((sz = exframesize[sz]) < 0)
    546 			goto bad;
    547 		if (sz && frame->f_stackadj == 0) {
    548 			/*
    549 			 * Extra stack space is required but not allocated.
    550 			 * Allocate and re-enter syscall().
    551 			 */
    552 			linux_reenter_syscall(frame, sz);
    553 			/* NOTREACHED */
    554 		}
    555 	}
    556 #ifdef DEBUG
    557 	/* linux_reenter_syscall() doesn't adjust stack. */
    558 	if (sz != frame->f_stackadj)
    559 		panic("linux_sys_sigreturn: adj: %d != %d",
    560 			sz, frame->f_stackadj);
    561 #endif
    562 
    563 	/* Restore signal stack. */
    564 	p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
    565 
    566 	/* Restore signal mask. */
    567 #if LINUX__NSIG_WORDS > 1
    568 	linux_old_extra_to_native_sigset(&scp->sc_mask, tsigc2.c_extrasigmask,
    569 					 &mask);
    570 #else
    571 	linux_old_to_native_sigset(&scp->sc_mask, &mask);
    572 #endif
    573 	(void) sigprocmask1(p, SIG_SETMASK, &mask, 0);
    574 
    575 	/*
    576 	 * Restore the user supplied information.
    577 	 */
    578 	frame->f_regs[SP] = scp->sc_sp;
    579 	frame->f_regs[D0] = scp->sc_d0;
    580 	frame->f_regs[D1] = scp->sc_d1;
    581 	frame->f_regs[A0] = scp->sc_a0;
    582 	frame->f_regs[A1] = scp->sc_a1;
    583 	frame->f_pc = scp->sc_pc;
    584 	/* Privileged bits of  sr  are silently ignored on Linux/m68k. */
    585 	frame->f_sr = scp->sc_ps & ~(PSL_MBZ|PSL_IPL|PSL_S);
    586 	/*
    587 	 * Other registers are assumed to be unchanged,
    588 	 * and not restored.
    589 	 */
    590 
    591 	/*
    592 	 * Restore long stack frames.  Note that we do not copy
    593 	 * back the saved SR or PC, they were picked up above from
    594 	 * the sigcontext structure.
    595 	 */
    596 	if (scp->sc_ss.ss_format) {
    597 		frame->f_format = scp->sc_ss.ss_format;
    598 		frame->f_vector = scp->sc_ss.ss_vector;
    599 		if (frame->f_stackadj < sz)	/* just in case... */
    600 			goto bad;
    601 		frame->f_stackadj -= sz;
    602 		bcopy(&scp->sc_ss.ss_frame, &frame->F_u, sz);
    603 #ifdef DEBUG
    604 		if (sigdebug & SDB_FOLLOW)
    605 			printf("linux_sys_sigreturn(%d): copy in %d of frame type %d\n",
    606 			       p->p_pid, sz, scp->sc_ss.ss_format);
    607 #endif
    608 	}
    609 
    610 	/*
    611 	 * Finally we restore the original FP context.
    612 	 */
    613 	switch (fputype) {
    614 	case FPU_NONE:
    615 		break;
    616 #ifdef M68060
    617 	case FPU_68060:
    618 		if (((struct fpframe060*)&scp->sc_ss.ss_fpstate.FPF_u1)
    619 					->fpf6_frmfmt != FPF6_FMT_NULL) {
    620 			/*
    621 			 * On 060,  "fmovem <ea>,fpcr/fpsr/fpi"  is
    622 			 * emulated by software and slow.
    623 			 */
    624 			asm("fmovem %0,fpcr; fmovem %1,fpsr; fmovem %2,fpi" : :
    625 				"m" (scp->sc_ss.ss_fpstate.fpf_fpcr),
    626 				"m" (scp->sc_ss.ss_fpstate.fpf_fpsr),
    627 				"m" (scp->sc_ss.ss_fpstate.fpf_fpiar));
    628 			asm("fmovem %0,fp0-fp1" : :
    629 				"m" (*scp->sc_ss.ss_fpstate.fpf_regs));
    630 		}
    631 		asm("frestore %0" : : "m" (scp->sc_ss.ss_fpstate.FPF_u1));
    632 		break;
    633 #endif
    634 	default:
    635 		if (scp->sc_ss.ss_fpstate.fpf_version) {
    636 			asm("fmovem %0,fpcr/fpsr/fpi; fmovem %1,fp0-fp1" : :
    637 				"m" (scp->sc_ss.ss_fpstate.fpf_fpcr),
    638 				"m" (*scp->sc_ss.ss_fpstate.fpf_regs));
    639 		}
    640 		asm("frestore %0" : : "m" (scp->sc_ss.ss_fpstate.FPF_u1));
    641 		break;
    642 	}
    643 
    644 #ifdef DEBUG
    645 	if ((sigdebug & SDB_FPSTATE) && *(char *)&scp->sc_ss.ss_fpstate)
    646 		printf("linux_sys_sigreturn(%d): copied in FP state (%x) at %p\n",
    647 		       p->p_pid, *(u_int *)&scp->sc_ss.ss_fpstate,
    648 		       &scp->sc_ss.ss_fpstate);
    649 	if ((sigdebug & SDB_FOLLOW) ||
    650 	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
    651 		printf("linux_sys_sigreturn(%d): returns\n", p->p_pid);
    652 #endif
    653 
    654 	return EJUSTRETURN;
    655 }
    656 
    657 /* ARGSUSED */
    658 int
    659 linux_sys_rt_sigreturn(p, v, retval)
    660 	struct proc *p;
    661 	void *v;
    662 	register_t *retval;
    663 {
    664 	struct frame *frame;
    665 	struct linux_ucontext *ucp;	/* ucontext in user space */
    666 	struct linux_ucontext tuc;	/* copy of *ucp */
    667 	sigset_t mask;
    668 	struct sigacts *psp;
    669 	int sz = 0;			/* extra frame size */
    670 
    671 	/*
    672 	 * rt_sigreturn of Linux/m68k takes no arguments.
    673 	 * usp + 4 is a pointer to siginfo structure,
    674 	 * usp + 8 is a pointer to ucontext structure.
    675 	 */
    676 	frame = (struct frame *) p->p_md.md_regs;
    677 	ucp = (struct linux_ucontext *) fuword((caddr_t)frame->f_regs[SP] + 8);
    678 	if ((int) ucp & 1)
    679 		goto bad;		/* error (-1) or odd address */
    680 
    681 #ifdef DEBUG
    682 	if (sigdebug & SDB_FOLLOW)
    683 		printf("linux_rt_sigreturn: pid %d, ucp %p\n", p->p_pid, ucp);
    684 #endif
    685 
    686 	/* Grab whole of the ucontext. */
    687 	if (copyin(ucp, &tuc, sizeof tuc))
    688 bad:		sigexit(p, SIGSEGV);
    689 
    690 	/*
    691 	 * Check kernel stack and re-enter to syscall() if needed.
    692 	 */
    693 	if ((sz = tuc.uc_ss.ss_format) != 0) {
    694 		if ((sz = exframesize[sz]) < 0)
    695 			goto bad;
    696 		if (sz && frame->f_stackadj == 0) {
    697 			/*
    698 			 * Extra stack space is required but not allocated.
    699 			 * Allocate and re-enter syscall().
    700 			 */
    701 			linux_reenter_syscall(frame, sz);
    702 			/* NOTREACHED */
    703 		}
    704 	}
    705 #ifdef DEBUG
    706 	/* linux_reenter_syscall() doesn't adjust stack. */
    707 	if (sz != frame->f_stackadj)
    708 		panic("linux_sys_rt_sigreturn: adj: %d != %d",
    709 			sz, frame->f_stackadj);
    710 #endif
    711 
    712 	if (tuc.uc_mc.mc_version != LINUX_MCONTEXT_VERSION)
    713 		goto bad;
    714 
    715 	/* Restore signal stack. */
    716 	psp = p->p_sigacts;
    717 	psp->ps_sigstk.ss_flags =
    718 		(psp->ps_sigstk.ss_flags & ~SS_ONSTACK) |
    719 		(tuc.uc_stack.ss_flags & LINUX_SS_ONSTACK ? SS_ONSTACK : 0);
    720 
    721 	/* Restore signal mask. */
    722 	linux_to_native_sigset(&tuc.uc_sigmask, &mask);
    723 	(void) sigprocmask1(p, SIG_SETMASK, &mask, 0);
    724 
    725 	/*
    726 	 * Restore the user supplied information.
    727 	 */
    728 	bcopy(tuc.uc_mc.mc_gregs.gr_regs, frame->f_regs, sizeof(u_int)*16);
    729 	frame->f_pc = tuc.uc_mc.mc_gregs.gr_pc;
    730 	/* Privileged bits of  sr  are silently ignored on Linux/m68k. */
    731 	frame->f_sr = tuc.uc_mc.mc_gregs.gr_sr & ~(PSL_MBZ|PSL_IPL|PSL_S);
    732 
    733 	/*
    734 	 * Restore long stack frames.  Note that we do not copy
    735 	 * back the saved SR or PC, they were picked up above from
    736 	 * the ucontext structure.
    737 	 */
    738 	if (tuc.uc_ss.ss_format) {
    739 		frame->f_format = tuc.uc_ss.ss_format;
    740 		frame->f_vector = tuc.uc_ss.ss_vector;
    741 		if (frame->f_stackadj < sz)	/* just in case... */
    742 			goto bad;
    743 		frame->f_stackadj -= sz;
    744 		bcopy(&tuc.uc_ss.ss_frame, &frame->F_u, sz);
    745 #ifdef DEBUG
    746 		if (sigdebug & SDB_FOLLOW)
    747 			printf("linux_sys_rt_sigreturn(%d): copy in %d of frame type %d\n",
    748 			       p->p_pid, sz, tuc.uc_ss.ss_format);
    749 #endif
    750 	}
    751 
    752 	/*
    753 	 * Finally we restore the original FP context.
    754 	 */
    755 	switch (fputype) {
    756 	case FPU_NONE:
    757 		break;
    758 #ifdef M68060
    759 	case FPU_68060:
    760 		if (((struct fpframe060*)&tuc.uc_ss.ss_fpstate.FPF_u1)
    761 					->fpf6_frmfmt != FPF6_FMT_NULL) {
    762 			/*
    763 			 * On 060,  "fmovem <ea>,fpcr/fpsr/fpi"  is
    764 			 * emulated by software and slow.
    765 			 */
    766 			asm("fmovem %0,fpcr; fmovem %1,fpsr; fmovem %2,fpi" : :
    767 				"m" (tuc.uc_mc.mc_fpregs.fpr_fpcr),
    768 				"m" (tuc.uc_mc.mc_fpregs.fpr_fpsr),
    769 				"m" (tuc.uc_mc.mc_fpregs.fpr_fpiar));
    770 			asm("fmovem %0,fp0-fp1" : :
    771 				"m" (*tuc.uc_mc.mc_fpregs.fpr_regs));
    772 		}
    773 		asm("frestore %0" : : "m" (tuc.uc_ss.ss_fpstate.FPF_u1));
    774 		break;
    775 #endif
    776 	default:
    777 		if (tuc.uc_ss.ss_fpstate.fpf_version) {
    778 			asm("fmovem %0,fpcr/fpsr/fpi; fmovem %1,fp0-fp1" : :
    779 				"m" (tuc.uc_mc.mc_fpregs.fpr_fpcr),
    780 				"m" (*tuc.uc_mc.mc_fpregs.fpr_regs));
    781 		}
    782 		asm("frestore %0" : : "m" (tuc.uc_ss.ss_fpstate.FPF_u1));
    783 		break;
    784 	}
    785 
    786 #ifdef DEBUG
    787 	if ((sigdebug & SDB_FPSTATE) && *(char *)&tuc.uc_ss.ss_fpstate)
    788 		printf("linux_rt_sigreturn(%d): copied in FP state (%x) at %p\n",
    789 		       p->p_pid, *(u_int *)&tuc.uc_ss.ss_fpstate,
    790 		       &tuc.uc_ss.ss_fpstate);
    791 	if ((sigdebug & SDB_FOLLOW) ||
    792 	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
    793 		printf("linux_rt_sigreturn(%d): returns\n", p->p_pid);
    794 #endif
    795 
    796 	return EJUSTRETURN;
    797 }
    798 
    799 /*
    800  * MPU cache operation of Linux/m68k,
    801  * mainly used for dynamic linking.
    802  */
    803 
    804 /* scope */
    805 #define LINUX_FLUSH_SCOPE_LINE	1	/* a cache line */
    806 #define LINUX_FLUSH_SCOPE_PAGE	2	/* a page */
    807 #define LINUX_FLUSH_SCOPE_ALL	3	/* the whole cache */
    808 /* cache */
    809 #define LINUX_FLUSH_CACHE_DATA	1	/* flush and purge data cache */
    810 #define LINUX_FLUSH_CACHE_INSN	2	/* purge instruction cache */
    811 #define LINUX_FLUSH_CACHE_BOTH	3	/* both */
    812 
    813 /* ARGSUSED */
    814 int
    815 linux_sys_cacheflush(p, v, retval)
    816 	struct proc *p;
    817 	void *v;
    818 	register_t *retval;
    819 {
    820 	struct linux_sys_cacheflush_args /* {
    821 		syscallarg(unsigned long)	addr;
    822 		syscallarg(int)			scope;
    823 		syscallarg(int)			cache;
    824 		syscallarg(unsigned long)	len;
    825 	} */ *uap = v;
    826 	int scope, cache;
    827 	caddr_t addr;
    828 	int len;
    829 	int error;
    830 
    831 	scope = SCARG(uap, scope);
    832 	cache = SCARG(uap, cache);
    833 
    834 	if (scope < LINUX_FLUSH_SCOPE_LINE || scope > LINUX_FLUSH_SCOPE_ALL
    835 				|| cache & ~LINUX_FLUSH_CACHE_BOTH)
    836 		return EINVAL;
    837 
    838 #if defined(M68040) || defined(M68060)
    839 	addr = (caddr_t) SCARG(uap, addr);
    840 	len = (int) SCARG(uap, len);
    841 #else
    842 	/*
    843 	 * We always flush entire cache on 68020/030
    844 	 * and these values are not used afterwards.
    845 	 */
    846 	addr = (caddr_t) 0;
    847 	len = 0;
    848 #endif
    849 
    850 	/*
    851 	 * LINUX_FLUSH_SCOPE_ALL (flush whole cache) is limited to super users.
    852 	 */
    853 	if (scope == LINUX_FLUSH_SCOPE_ALL) {
    854 		if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    855 			return error;
    856 #if defined(M68040) || defined(M68060)
    857 		/* entire cache */
    858 		len = INT_MAX;
    859 #endif
    860 	}
    861 
    862 	error = 0;
    863 	if (cache & LINUX_FLUSH_CACHE_DATA)
    864 		if ((error = cachectl(CC_EXTPURGE|CC_PURGE, addr, len)) != 0)
    865 			return error;
    866 	if (cache & LINUX_FLUSH_CACHE_INSN)
    867 		error = cachectl(CC_EXTPURGE|CC_IPURGE, addr, len);
    868 
    869 	return error;
    870 }
    871 
    872 /*
    873  * Convert NetBSD's devices to Linux's.
    874  */
    875 dev_t
    876 linux_fakedev(dev)
    877 	dev_t dev;
    878 {
    879 
    880 	/* do nothing for now */
    881 	return dev;
    882 }
    883 
    884 /*
    885  * We come here in a last attempt to satisfy a Linux ioctl() call.
    886  */
    887 int
    888 linux_machdepioctl(p, v, retval)
    889 	struct proc *p;
    890 	void *v;
    891 	register_t *retval;
    892 {
    893 	struct linux_sys_ioctl_args /* {
    894 		syscallarg(int) fd;
    895 		syscallarg(u_long) com;
    896 		syscallarg(caddr_t) data;
    897 	} */ *uap = v;
    898 	struct sys_ioctl_args bia;
    899 	u_long com;
    900 
    901 	SCARG(&bia, fd) = SCARG(uap, fd);
    902 	SCARG(&bia, data) = SCARG(uap, data);
    903 	com = SCARG(uap, com);
    904 
    905 	switch (com) {
    906 
    907 	/* do nothing for now */
    908 
    909 	default:
    910 		printf("linux_machdepioctl: invalid ioctl %08lx\n", com);
    911 		return EINVAL;
    912 	}
    913 	SCARG(&bia, com) = com;
    914 	return sys_ioctl(p, &bia, retval);
    915 }
    916