1 /* $NetBSD: linux_machdep.c,v 1.2 1998/12/19 16:27:10 drochner 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 sigacts *psp)); 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 cachectl(CC_EXTPURGE | CC_IPURGE, 251 (caddr_t) fp->sf_sigtramp, sizeof fp->sf_sigtramp); 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, psp) 268 struct frame *frame; 269 int sig; 270 sigset_t *mask; 271 caddr_t usp; 272 struct sigacts *psp; 273 { 274 struct proc *p = curproc; 275 struct linux_rt_sigframe *fp, kf; 276 short ft; 277 278 ft = frame->f_format; 279 280 /* Allocate space for the signal handler context on the user stack. */ 281 fp = (struct linux_rt_sigframe *) usp; 282 fp--; 283 284 #ifdef DEBUG 285 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 286 printf("setup_linux_rt_sigframe(%d): sig %d ssp %p usp %p ucp %p ft %d\n", 287 p->p_pid, sig, &ft, fp, &fp->sf_uc, ft); 288 #endif 289 290 /* Build stack frame. */ 291 kf.sf_psigtramp = fp->sf_sigtramp; /* return addr for handler */ 292 kf.sf_signum = native_to_linux_sig[sig]; 293 kf.sf_pinfo = &fp->sf_info; 294 kf.sf_puc = &fp->sf_uc; 295 296 /* The sigtramp code is on the stack frame on Linux/m68k. */ 297 kf.sf_sigtramp[0] = LINUX_RT_SF_SIGTRAMP0; 298 kf.sf_sigtramp[1] = LINUX_RT_SF_SIGTRAMP1; 299 300 /* clear for security (and initialize uc_flags, ss_format, etc.). */ 301 bzero(&kf.sf_uc, sizeof(struct linux_ucontext)); 302 303 /* 304 * Save necessary hardware state. Currently this includes: 305 * - general registers 306 * - original exception frame (if not a "normal" frame) 307 * - FP coprocessor state 308 */ 309 /* version of mcontext */ 310 kf.sf_uc.uc_mc.mc_version = LINUX_MCONTEXT_VERSION; 311 312 /* general registers and pc/sr */ 313 bcopy(frame->f_regs, kf.sf_uc.uc_mc.mc_gregs.gr_regs, sizeof(u_int)*16); 314 kf.sf_uc.uc_mc.mc_gregs.gr_pc = frame->f_pc; 315 kf.sf_uc.uc_mc.mc_gregs.gr_sr = frame->f_sr; 316 317 if (ft >= FMT4) { 318 #ifdef DEBUG 319 if (ft > 15 || exframesize[ft] < 0) 320 panic("setup_linux_rt_sigframe: bogus frame type"); 321 #endif 322 kf.sf_uc.uc_ss.ss_format = ft; 323 kf.sf_uc.uc_ss.ss_vector = frame->f_vector; 324 bcopy(&frame->F_u, &kf.sf_uc.uc_ss.ss_frame, 325 (size_t) exframesize[ft]); 326 /* 327 * Leave an indicator that we need to clean up the kernel 328 * stack. We do this by setting the "pad word" above the 329 * hardware stack frame to the amount the stack must be 330 * adjusted by. 331 * 332 * N.B. we increment rather than just set f_stackadj in 333 * case we are called from syscall when processing a 334 * sigreturn. In that case, f_stackadj may be non-zero. 335 */ 336 frame->f_stackadj += exframesize[ft]; 337 frame->f_format = frame->f_vector = 0; 338 #ifdef DEBUG 339 if (sigdebug & SDB_FOLLOW) 340 printf("setup_linux_rt_sigframe(%d): copy out %d of frame %d\n", 341 p->p_pid, exframesize[ft], ft); 342 #endif 343 } 344 345 switch (fputype) { 346 case FPU_NONE: 347 break; 348 #ifdef M68060 349 case FPU_68060: 350 asm("fsave %0" : "=m" (kf.sf_uc.uc_ss.ss_fpstate)); 351 /* See note below. */ 352 if (((struct fpframe060 *) &kf.sf_uc.uc_ss.ss_fpstate.FPF_u1) 353 ->fpf6_frmfmt != FPF6_FMT_NULL) { 354 asm("fmovem fp0-fp7,%0" : 355 "=m" (*kf.sf_uc.uc_mc.mc_fpregs.fpr_regs)); 356 /* 357 * On 060, "fmovem fpcr/fpsr/fpi,<ea>" is 358 * emulated by software and slow. 359 */ 360 asm("fmovem fpcr,%0; fmovem fpsr,%1; fmovem fpi,%2" : 361 "=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpcr), 362 "=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpsr), 363 "=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpiar)); 364 } 365 break; 366 #endif 367 default: 368 /* 369 * NOTE: We give whole of the "struct linux_rt_fpframe" 370 * to the asm("fsave") argument; not the FPF_u1 element only. 371 * Unlike the non-RT version of this structure, 372 * this contains only the FPU state used by "fsave" 373 * (and whole of the information is in the structure). 374 * This gives the correct dependency information to the asm(), 375 * and no "memory" is required to the ``clobberd'' list. 376 */ 377 asm("fsave %0" : "=m" (kf.sf_uc.uc_ss.ss_fpstate)); 378 if (kf.sf_uc.uc_ss.ss_fpstate.fpf_version) { 379 asm("fmovem fp0-fp7,%0; fmovem fpcr/fpsr/fpi,%1" : 380 "=m" (*kf.sf_uc.uc_mc.mc_fpregs.fpr_regs), 381 "=m" (kf.sf_uc.uc_mc.mc_fpregs.fpr_fpcr) 382 : : "memory"); 383 } 384 break; 385 } 386 #ifdef DEBUG 387 if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_uc.uc_ss.ss_fpstate) 388 printf("setup_linux_rt_sigframe(%d): copy out FP state (%x) to %p\n", 389 p->p_pid, *(u_int *)&kf.sf_uc.uc_ss.ss_fpstate, 390 &kf.sf_uc.uc_ss.ss_fpstate); 391 #endif 392 393 /* 394 * XXX XAX Create bogus siginfo data. This can't really 395 * XXX be fixed until NetBSD has realtime signals. 396 * XXX Or we do the emuldata thing. 397 * XXX -erh 398 */ 399 bzero(&kf.sf_info, sizeof(struct linux_siginfo)); 400 kf.sf_info.si_signo = sig; 401 kf.sf_info.si_code = LINUX_SI_USER; 402 kf.sf_info.si_pid = p->p_pid; 403 kf.sf_info.si_uid = p->p_ucred->cr_uid; /* Use real uid here? */ 404 405 /* Build the signal context to be used by sigreturn. */ 406 native_to_linux_sigset(mask, &kf.sf_uc.uc_sigmask); 407 kf.sf_uc.uc_stack.ss_sp = psp->ps_sigstk.ss_sp; 408 kf.sf_uc.uc_stack.ss_flags = 409 (psp->ps_sigstk.ss_flags & SS_ONSTACK ? LINUX_SS_ONSTACK : 0) | 410 (psp->ps_sigstk.ss_flags & SS_DISABLE ? LINUX_SS_DISABLE : 0); 411 kf.sf_uc.uc_stack.ss_size = psp->ps_sigstk.ss_size; 412 413 if (copyout(&kf, fp, sizeof(struct linux_rt_sigframe))) { 414 #ifdef DEBUG 415 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 416 printf("setup_linux_rt_sigframe(%d): copyout failed on sig %d\n", 417 p->p_pid, sig); 418 #endif 419 /* 420 * Process has trashed its stack; give it a segmentation 421 * violation to halt it in its tracks. 422 */ 423 sigexit(p, SIGSEGV); 424 /* NOTREACHED */ 425 } 426 427 /* 428 * The signal trampoline is on the signal frame. 429 * Clear the instruction cache in case of cached. 430 */ 431 cachectl(CC_EXTPURGE | CC_IPURGE, 432 (caddr_t) fp->sf_sigtramp, sizeof fp->sf_sigtramp); 433 434 /* Set up the user stack pointer. */ 435 frame->f_regs[SP] = (int)fp; 436 437 #ifdef DEBUG 438 if (sigdebug & SDB_FOLLOW) 439 printf("setup_linux_rt_sigframe(%d): sig %d puc %p fp %p sc_sp %x\n", 440 p->p_pid, sig, kf.sf_puc, fp, 441 kf.sf_uc.uc_mc.mc_gregs.gr_regs[SP]); 442 #endif 443 } 444 445 /* 446 * Send an interrupt to Linux process. 447 */ 448 void 449 linux_sendsig(catcher, sig, mask, code) 450 sig_t catcher; 451 int sig; 452 sigset_t *mask; 453 u_long code; 454 { 455 struct proc *p = curproc; 456 struct frame *frame; 457 struct sigacts *psp = p->p_sigacts; 458 caddr_t usp; /* user stack for signal context */ 459 int onstack; 460 461 frame = (struct frame *)p->p_md.md_regs; 462 463 /* Do we need to jump onto the signal stack? */ 464 onstack = (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 465 (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0; 466 467 /* Determine user stack for the signal handler context. */ 468 if (onstack) 469 usp = (caddr_t)psp->ps_sigstk.ss_sp + psp->ps_sigstk.ss_size; 470 else 471 usp = (caddr_t)frame->f_regs[SP]; 472 473 /* Setup the signal frame (and part of the trapframe). */ 474 if (p->p_sigacts->ps_sigact[sig].sa_flags & SA_SIGINFO) 475 setup_linux_rt_sigframe(frame, sig, mask, usp, psp); 476 else 477 setup_linux_sigframe(frame, sig, mask, usp); 478 479 /* Call the signal handler. */ 480 frame->f_pc = (u_int) catcher; 481 482 /* Remember that we're now on the signal stack. */ 483 if (onstack) 484 psp->ps_sigstk.ss_flags |= SS_ONSTACK; 485 486 #ifdef DEBUG 487 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 488 printf("linux_sendsig(%d): sig %d returns\n", 489 p->p_pid, sig); 490 #endif 491 } 492 493 /* 494 * The linux_sys_sigreturn and linux_sys_rt_sigreturn 495 * system calls cleanup state after a signal 496 * has been taken. Reset signal mask and stack 497 * state from context left by linux_sendsig (above). 498 * Return to previous pc and psl as specified by 499 * context left by linux_sendsig. Check carefully to 500 * make sure that the user has not modified the 501 * psl to gain improper privileges or to cause 502 * a machine fault. 503 * 504 * Note that the sigreturn system calls of Linux/m68k 505 * do not return on errors, but issue segmentation 506 * violation and terminate the process. 507 */ 508 /* ARGSUSED */ 509 int 510 linux_sys_sigreturn(p, v, retval) 511 struct proc *p; 512 void *v; 513 register_t *retval; 514 { 515 struct frame *frame; 516 struct linux_sigc2 tsigc2; /* extra mask and sigcontext */ 517 struct linux_sigcontext *scp; /* pointer to sigcontext */ 518 sigset_t mask; 519 int sz = 0; /* extra frame size */ 520 int usp; 521 522 /* 523 * sigreturn of Linux/m68k takes no arguments. 524 * The user stack points at struct linux_sigc2. 525 */ 526 frame = (struct frame *) p->p_md.md_regs; 527 usp = frame->f_regs[SP]; 528 if (usp & 1) 529 goto bad; 530 531 #ifdef DEBUG 532 if (sigdebug & SDB_FOLLOW) 533 printf("linux_sys_sigreturn: pid %d, usp %p\n", 534 p->p_pid, (caddr_t) usp); 535 #endif 536 537 /* Grab whole of the sigcontext. */ 538 if (copyin((caddr_t) usp, &tsigc2, sizeof tsigc2)) 539 bad: sigexit(p, SIGSEGV); 540 541 scp = &tsigc2.c_sc; 542 543 /* 544 * Check kernel stack and re-enter to syscall() if needed. 545 */ 546 if ((sz = scp->sc_ss.ss_format) != 0) { 547 if ((sz = exframesize[sz]) < 0) 548 goto bad; 549 if (sz && frame->f_stackadj == 0) { 550 /* 551 * Extra stack space is required but not allocated. 552 * Allocate and re-enter syscall(). 553 */ 554 linux_reenter_syscall(frame, sz); 555 /* NOTREACHED */ 556 } 557 } 558 #ifdef DEBUG 559 /* linux_reenter_syscall() doesn't adjust stack. */ 560 if (sz != frame->f_stackadj) 561 panic("linux_sys_sigreturn: adj: %d != %d", 562 sz, frame->f_stackadj); 563 #endif 564 565 /* Restore signal stack. */ 566 p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; 567 568 /* Restore signal mask. */ 569 #if LINUX__NSIG_WORDS > 1 570 linux_old_extra_to_native_sigset(&scp->sc_mask, tsigc2.c_extrasigmask, 571 &mask); 572 #else 573 linux_old_to_native_sigset(&scp->sc_mask, &mask); 574 #endif 575 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 576 577 /* 578 * Restore the user supplied information. 579 */ 580 frame->f_regs[SP] = scp->sc_sp; 581 frame->f_regs[D0] = scp->sc_d0; 582 frame->f_regs[D1] = scp->sc_d1; 583 frame->f_regs[A0] = scp->sc_a0; 584 frame->f_regs[A1] = scp->sc_a1; 585 frame->f_pc = scp->sc_pc; 586 /* Privileged bits of sr are silently ignored on Linux/m68k. */ 587 frame->f_sr = scp->sc_ps & ~(PSL_MBZ|PSL_IPL|PSL_S); 588 /* 589 * Other registers are assumed to be unchanged, 590 * and not restored. 591 */ 592 593 /* 594 * Restore long stack frames. Note that we do not copy 595 * back the saved SR or PC, they were picked up above from 596 * the sigcontext structure. 597 */ 598 if (scp->sc_ss.ss_format) { 599 frame->f_format = scp->sc_ss.ss_format; 600 frame->f_vector = scp->sc_ss.ss_vector; 601 if (frame->f_stackadj < sz) /* just in case... */ 602 goto bad; 603 frame->f_stackadj -= sz; 604 bcopy(&scp->sc_ss.ss_frame, &frame->F_u, sz); 605 #ifdef DEBUG 606 if (sigdebug & SDB_FOLLOW) 607 printf("linux_sys_sigreturn(%d): copy in %d of frame type %d\n", 608 p->p_pid, sz, scp->sc_ss.ss_format); 609 #endif 610 } 611 612 /* 613 * Finally we restore the original FP context. 614 */ 615 switch (fputype) { 616 case FPU_NONE: 617 break; 618 #ifdef M68060 619 case FPU_68060: 620 if (((struct fpframe060*)&scp->sc_ss.ss_fpstate.FPF_u1) 621 ->fpf6_frmfmt != FPF6_FMT_NULL) { 622 /* 623 * On 060, "fmovem <ea>,fpcr/fpsr/fpi" is 624 * emulated by software and slow. 625 */ 626 asm("fmovem %0,fpcr; fmovem %1,fpsr; fmovem %2,fpi" : : 627 "m" (scp->sc_ss.ss_fpstate.fpf_fpcr), 628 "m" (scp->sc_ss.ss_fpstate.fpf_fpsr), 629 "m" (scp->sc_ss.ss_fpstate.fpf_fpiar)); 630 asm("fmovem %0,fp0-fp1" : : 631 "m" (*scp->sc_ss.ss_fpstate.fpf_regs)); 632 } 633 asm("frestore %0" : : "m" (scp->sc_ss.ss_fpstate.FPF_u1)); 634 break; 635 #endif 636 default: 637 if (scp->sc_ss.ss_fpstate.fpf_version) { 638 asm("fmovem %0,fpcr/fpsr/fpi; fmovem %1,fp0-fp1" : : 639 "m" (scp->sc_ss.ss_fpstate.fpf_fpcr), 640 "m" (*scp->sc_ss.ss_fpstate.fpf_regs)); 641 } 642 asm("frestore %0" : : "m" (scp->sc_ss.ss_fpstate.FPF_u1)); 643 break; 644 } 645 646 #ifdef DEBUG 647 if ((sigdebug & SDB_FPSTATE) && *(char *)&scp->sc_ss.ss_fpstate) 648 printf("linux_sys_sigreturn(%d): copied in FP state (%x) at %p\n", 649 p->p_pid, *(u_int *)&scp->sc_ss.ss_fpstate, 650 &scp->sc_ss.ss_fpstate); 651 if ((sigdebug & SDB_FOLLOW) || 652 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 653 printf("linux_sys_sigreturn(%d): returns\n", p->p_pid); 654 #endif 655 656 return EJUSTRETURN; 657 } 658 659 /* ARGSUSED */ 660 int 661 linux_sys_rt_sigreturn(p, v, retval) 662 struct proc *p; 663 void *v; 664 register_t *retval; 665 { 666 struct frame *frame; 667 struct linux_ucontext *ucp; /* ucontext in user space */ 668 struct linux_ucontext tuc; /* copy of *ucp */ 669 sigset_t mask; 670 struct sigacts *psp; 671 int sz = 0; /* extra frame size */ 672 673 /* 674 * rt_sigreturn of Linux/m68k takes no arguments. 675 * usp + 4 is a pointer to siginfo structure, 676 * usp + 8 is a pointer to ucontext structure. 677 */ 678 frame = (struct frame *) p->p_md.md_regs; 679 ucp = (struct linux_ucontext *) fuword((caddr_t)frame->f_regs[SP] + 8); 680 if ((int) ucp & 1) 681 goto bad; /* error (-1) or odd address */ 682 683 #ifdef DEBUG 684 if (sigdebug & SDB_FOLLOW) 685 printf("linux_rt_sigreturn: pid %d, ucp %p\n", p->p_pid, ucp); 686 #endif 687 688 /* Grab whole of the ucontext. */ 689 if (copyin(ucp, &tuc, sizeof tuc)) 690 bad: sigexit(p, SIGSEGV); 691 692 /* 693 * Check kernel stack and re-enter to syscall() if needed. 694 */ 695 if ((sz = tuc.uc_ss.ss_format) != 0) { 696 if ((sz = exframesize[sz]) < 0) 697 goto bad; 698 if (sz && frame->f_stackadj == 0) { 699 /* 700 * Extra stack space is required but not allocated. 701 * Allocate and re-enter syscall(). 702 */ 703 linux_reenter_syscall(frame, sz); 704 /* NOTREACHED */ 705 } 706 } 707 #ifdef DEBUG 708 /* linux_reenter_syscall() doesn't adjust stack. */ 709 if (sz != frame->f_stackadj) 710 panic("linux_sys_rt_sigreturn: adj: %d != %d", 711 sz, frame->f_stackadj); 712 #endif 713 714 if (tuc.uc_mc.mc_version != LINUX_MCONTEXT_VERSION) 715 goto bad; 716 717 /* Restore signal stack. */ 718 psp = p->p_sigacts; 719 psp->ps_sigstk.ss_flags = 720 (psp->ps_sigstk.ss_flags & ~SS_ONSTACK) | 721 (tuc.uc_stack.ss_flags & LINUX_SS_ONSTACK ? SS_ONSTACK : 0); 722 723 /* Restore signal mask. */ 724 linux_to_native_sigset(&tuc.uc_sigmask, &mask); 725 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 726 727 /* 728 * Restore the user supplied information. 729 */ 730 bcopy(tuc.uc_mc.mc_gregs.gr_regs, frame->f_regs, sizeof(u_int)*16); 731 frame->f_pc = tuc.uc_mc.mc_gregs.gr_pc; 732 /* Privileged bits of sr are silently ignored on Linux/m68k. */ 733 frame->f_sr = tuc.uc_mc.mc_gregs.gr_sr & ~(PSL_MBZ|PSL_IPL|PSL_S); 734 735 /* 736 * Restore long stack frames. Note that we do not copy 737 * back the saved SR or PC, they were picked up above from 738 * the ucontext structure. 739 */ 740 if (tuc.uc_ss.ss_format) { 741 frame->f_format = tuc.uc_ss.ss_format; 742 frame->f_vector = tuc.uc_ss.ss_vector; 743 if (frame->f_stackadj < sz) /* just in case... */ 744 goto bad; 745 frame->f_stackadj -= sz; 746 bcopy(&tuc.uc_ss.ss_frame, &frame->F_u, sz); 747 #ifdef DEBUG 748 if (sigdebug & SDB_FOLLOW) 749 printf("linux_sys_rt_sigreturn(%d): copy in %d of frame type %d\n", 750 p->p_pid, sz, tuc.uc_ss.ss_format); 751 #endif 752 } 753 754 /* 755 * Finally we restore the original FP context. 756 */ 757 switch (fputype) { 758 case FPU_NONE: 759 break; 760 #ifdef M68060 761 case FPU_68060: 762 if (((struct fpframe060*)&tuc.uc_ss.ss_fpstate.FPF_u1) 763 ->fpf6_frmfmt != FPF6_FMT_NULL) { 764 /* 765 * On 060, "fmovem <ea>,fpcr/fpsr/fpi" is 766 * emulated by software and slow. 767 */ 768 asm("fmovem %0,fpcr; fmovem %1,fpsr; fmovem %2,fpi" : : 769 "m" (tuc.uc_mc.mc_fpregs.fpr_fpcr), 770 "m" (tuc.uc_mc.mc_fpregs.fpr_fpsr), 771 "m" (tuc.uc_mc.mc_fpregs.fpr_fpiar)); 772 asm("fmovem %0,fp0-fp1" : : 773 "m" (*tuc.uc_mc.mc_fpregs.fpr_regs)); 774 } 775 asm("frestore %0" : : "m" (tuc.uc_ss.ss_fpstate.FPF_u1)); 776 break; 777 #endif 778 default: 779 if (tuc.uc_ss.ss_fpstate.fpf_version) { 780 asm("fmovem %0,fpcr/fpsr/fpi; fmovem %1,fp0-fp1" : : 781 "m" (tuc.uc_mc.mc_fpregs.fpr_fpcr), 782 "m" (*tuc.uc_mc.mc_fpregs.fpr_regs)); 783 } 784 asm("frestore %0" : : "m" (tuc.uc_ss.ss_fpstate.FPF_u1)); 785 break; 786 } 787 788 #ifdef DEBUG 789 if ((sigdebug & SDB_FPSTATE) && *(char *)&tuc.uc_ss.ss_fpstate) 790 printf("linux_rt_sigreturn(%d): copied in FP state (%x) at %p\n", 791 p->p_pid, *(u_int *)&tuc.uc_ss.ss_fpstate, 792 &tuc.uc_ss.ss_fpstate); 793 if ((sigdebug & SDB_FOLLOW) || 794 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 795 printf("linux_rt_sigreturn(%d): returns\n", p->p_pid); 796 #endif 797 798 return EJUSTRETURN; 799 } 800 801 /* 802 * MPU cache operation of Linux/m68k, 803 * mainly used for dynamic linking. 804 */ 805 806 /* scope */ 807 #define LINUX_FLUSH_SCOPE_LINE 1 /* a cache line */ 808 #define LINUX_FLUSH_SCOPE_PAGE 2 /* a page */ 809 #define LINUX_FLUSH_SCOPE_ALL 3 /* the whole cache */ 810 /* cache */ 811 #define LINUX_FLUSH_CACHE_DATA 1 /* flush and purge data cache */ 812 #define LINUX_FLUSH_CACHE_INSN 2 /* purge instruction cache */ 813 #define LINUX_FLUSH_CACHE_BOTH 3 /* both */ 814 815 /* ARGSUSED */ 816 int 817 linux_sys_cacheflush(p, v, retval) 818 struct proc *p; 819 void *v; 820 register_t *retval; 821 { 822 struct linux_sys_cacheflush_args /* { 823 syscallarg(unsigned long) addr; 824 syscallarg(int) scope; 825 syscallarg(int) cache; 826 syscallarg(unsigned long) len; 827 } */ *uap = v; 828 int scope, cache; 829 caddr_t addr; 830 int len; 831 int error; 832 833 scope = SCARG(uap, scope); 834 cache = SCARG(uap, cache); 835 836 if (scope < LINUX_FLUSH_SCOPE_LINE || scope > LINUX_FLUSH_SCOPE_ALL 837 || cache & ~LINUX_FLUSH_CACHE_BOTH) 838 return EINVAL; 839 840 #if defined(M68040) || defined(M68060) 841 addr = (caddr_t) SCARG(uap, addr); 842 len = (int) SCARG(uap, len); 843 #else 844 /* 845 * We always flush entire cache on 68020/030 846 * and these values are not used afterwards. 847 */ 848 addr = (caddr_t) 0; 849 len = 0; 850 #endif 851 852 /* 853 * LINUX_FLUSH_SCOPE_ALL (flush whole cache) is limited to super users. 854 */ 855 if (scope == LINUX_FLUSH_SCOPE_ALL) { 856 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 857 return error; 858 #if defined(M68040) || defined(M68060) 859 /* entire cache */ 860 len = INT_MAX; 861 #endif 862 } 863 864 error = 0; 865 if (cache & LINUX_FLUSH_CACHE_DATA) 866 if ((error = cachectl(CC_EXTPURGE|CC_PURGE, addr, len)) != 0) 867 return error; 868 if (cache & LINUX_FLUSH_CACHE_INSN) 869 error = cachectl(CC_EXTPURGE|CC_IPURGE, addr, len); 870 871 return error; 872 } 873 874 /* 875 * Convert NetBSD's devices to Linux's. 876 */ 877 dev_t 878 linux_fakedev(dev) 879 dev_t dev; 880 { 881 882 /* do nothing for now */ 883 return dev; 884 } 885 886 /* 887 * We come here in a last attempt to satisfy a Linux ioctl() call. 888 */ 889 int 890 linux_machdepioctl(p, v, retval) 891 struct proc *p; 892 void *v; 893 register_t *retval; 894 { 895 struct linux_sys_ioctl_args /* { 896 syscallarg(int) fd; 897 syscallarg(u_long) com; 898 syscallarg(caddr_t) data; 899 } */ *uap = v; 900 struct sys_ioctl_args bia; 901 u_long com; 902 903 SCARG(&bia, fd) = SCARG(uap, fd); 904 SCARG(&bia, data) = SCARG(uap, data); 905 com = SCARG(uap, com); 906 907 switch (com) { 908 909 /* do nothing for now */ 910 911 default: 912 printf("linux_machdepioctl: invalid ioctl %08lx\n", com); 913 return EINVAL; 914 } 915 SCARG(&bia, com) = com; 916 return sys_ioctl(p, &bia, retval); 917 } 918