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