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