1 /* $NetBSD: linux_machdep.c,v 1.22 2003/09/28 00:15:13 cl 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.22 2003/09/28 00:15:13 cl 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, 86 const sigset_t *mask, caddr_t usp)); 87 void setup_linux_rt_sigframe __P((struct frame *frame, int sig, 88 const sigset_t *mask, 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 const 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[0][0])); 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[0][0]), 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 const 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[0][0])); 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[0][0]), 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(const ksiginfo_t *ksi, const sigset_t *mask) 455 { 456 /* u_long code = ksi->ksi_trap; */ 457 int sig = ksi->ksi_signo; 458 struct lwp *l = curlwp; 459 struct proc *p = l->l_proc; 460 struct frame *frame = (struct frame *)l->l_md.md_regs; 461 int onstack; 462 /* user stack for signal context */ 463 caddr_t usp = getframe(l, sig, &onstack); 464 sig_t catcher = SIGACTION(p, sig).sa_handler; 465 466 /* Setup the signal frame (and part of the trapframe). */ 467 if (SIGACTION(p, sig).sa_flags & SA_SIGINFO) 468 setup_linux_rt_sigframe(frame, sig, mask, usp, l); 469 else 470 setup_linux_sigframe(frame, sig, mask, usp); 471 472 /* Call the signal handler. */ 473 frame->f_pc = (u_int) catcher; 474 475 /* Remember that we're now on the signal stack. */ 476 if (onstack) 477 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 478 479 #ifdef DEBUG 480 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 481 printf("linux_sendsig(%d): sig %d returns\n", 482 p->p_pid, sig); 483 #endif 484 } 485 486 /* 487 * The linux_sys_sigreturn and linux_sys_rt_sigreturn 488 * system calls cleanup state after a signal 489 * has been taken. Reset signal mask and stack 490 * state from context left by linux_sendsig (above). 491 * Return to previous pc and psl as specified by 492 * context left by linux_sendsig. Check carefully to 493 * make sure that the user has not modified the 494 * psl to gain improper privileges or to cause 495 * a machine fault. 496 * 497 * Note that the sigreturn system calls of Linux/m68k 498 * do not return on errors, but issue segmentation 499 * violation and terminate the process. 500 */ 501 /* ARGSUSED */ 502 int 503 linux_sys_sigreturn(l, v, retval) 504 struct lwp *l; 505 void *v; 506 register_t *retval; 507 { 508 struct proc *p = l->l_proc; 509 struct frame *frame; 510 struct linux_sigc2 tsigc2; /* extra mask and sigcontext */ 511 struct linux_sigcontext *scp; /* pointer to sigcontext */ 512 sigset_t mask; 513 int sz = 0; /* extra frame size */ 514 int usp; 515 516 /* 517 * sigreturn of Linux/m68k takes no arguments. 518 * The user stack points at struct linux_sigc2. 519 */ 520 frame = (struct frame *) l->l_md.md_regs; 521 usp = frame->f_regs[SP]; 522 if (usp & 1) 523 goto bad; 524 525 #ifdef DEBUG 526 if (sigdebug & SDB_FOLLOW) 527 printf("linux_sys_sigreturn: pid %d, usp %p\n", 528 p->p_pid, (caddr_t) usp); 529 #endif 530 531 /* Grab whole of the sigcontext. */ 532 if (copyin((caddr_t) usp, &tsigc2, sizeof tsigc2)) 533 bad: sigexit(l, SIGSEGV); 534 535 scp = &tsigc2.c_sc; 536 537 /* 538 * Check kernel stack and re-enter to syscall() if needed. 539 */ 540 if ((sz = scp->sc_ss.ss_format) != 0) { 541 if ((sz = exframesize[sz]) < 0) 542 goto bad; 543 if (sz && frame->f_stackadj == 0) { 544 /* 545 * Extra stack space is required but not allocated. 546 * Allocate and re-enter syscall(). 547 */ 548 reenter_syscall(frame, sz); 549 /* NOTREACHED */ 550 } 551 } 552 #ifdef DEBUG 553 /* reenter_syscall() doesn't adjust stack. */ 554 if (sz != frame->f_stackadj) 555 panic("linux_sys_sigreturn: adj: %d != %d", 556 sz, frame->f_stackadj); 557 #endif 558 559 /* Restore signal stack. */ 560 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 561 562 /* Restore signal mask. */ 563 #if LINUX__NSIG_WORDS > 1 564 linux_old_extra_to_native_sigset(&mask, &scp->sc_mask, 565 tsigc2.c_extrasigmask); 566 #else 567 linux_old_to_native_sigset(&scp->sc_mask, &mask); 568 #endif 569 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 570 571 /* 572 * Restore the user supplied information. 573 */ 574 frame->f_regs[SP] = scp->sc_sp; 575 frame->f_regs[D0] = scp->sc_d0; 576 frame->f_regs[D1] = scp->sc_d1; 577 frame->f_regs[A0] = scp->sc_a0; 578 frame->f_regs[A1] = scp->sc_a1; 579 frame->f_pc = scp->sc_pc; 580 /* Privileged bits of sr are silently ignored on Linux/m68k. */ 581 frame->f_sr = scp->sc_ps & ~(PSL_MBZ|PSL_IPL|PSL_S); 582 /* 583 * Other registers are assumed to be unchanged, 584 * and not restored. 585 */ 586 587 /* 588 * Restore long stack frames. Note that we do not copy 589 * back the saved SR or PC, they were picked up above from 590 * the sigcontext structure. 591 */ 592 if (scp->sc_ss.ss_format) { 593 frame->f_format = scp->sc_ss.ss_format; 594 frame->f_vector = scp->sc_ss.ss_vector; 595 if (frame->f_stackadj < sz) /* just in case... */ 596 goto bad; 597 frame->f_stackadj -= sz; 598 bcopy(&scp->sc_ss.ss_frame, &frame->F_u, sz); 599 #ifdef DEBUG 600 if (sigdebug & SDB_FOLLOW) 601 printf("linux_sys_sigreturn(%d): copy in %d of frame type %d\n", 602 p->p_pid, sz, scp->sc_ss.ss_format); 603 #endif 604 } 605 606 /* 607 * Finally we restore the original FP context. 608 */ 609 switch (fputype) { 610 case FPU_NONE: 611 break; 612 #ifdef M68060 613 case FPU_68060: 614 if (((struct fpframe060*)&scp->sc_ss.ss_fpstate.FPF_u1) 615 ->fpf6_frmfmt != FPF6_FMT_NULL) { 616 /* 617 * On 060, "fmovem <ea>,fpcr/fpsr/fpi" is 618 * emulated by software and slow. 619 */ 620 asm("fmovem %0,%%fpcr; fmovem %1,%%fpsr; fmovem %2,%%fpi":: 621 "m" (scp->sc_ss.ss_fpstate.fpf_fpcr), 622 "m" (scp->sc_ss.ss_fpstate.fpf_fpsr), 623 "m" (scp->sc_ss.ss_fpstate.fpf_fpiar)); 624 asm("fmovem %0,%%fp0-%%fp1" : : 625 "m" (scp->sc_ss.ss_fpstate.fpf_regs[0][0])); 626 } 627 asm("frestore %0" : : "m" (scp->sc_ss.ss_fpstate.FPF_u1)); 628 break; 629 #endif 630 default: 631 if (scp->sc_ss.ss_fpstate.fpf_version) { 632 asm("fmovem %0,%%fpcr/%%fpsr/%%fpi; fmovem %1,%%fp0-%%fp1":: 633 "m" (scp->sc_ss.ss_fpstate.fpf_fpcr), 634 "m" (scp->sc_ss.ss_fpstate.fpf_regs[0][0])); 635 } 636 asm("frestore %0" : : "m" (scp->sc_ss.ss_fpstate.FPF_u1)); 637 break; 638 } 639 640 #ifdef DEBUG 641 if ((sigdebug & SDB_FPSTATE) && *(char *)&scp->sc_ss.ss_fpstate) 642 printf("linux_sys_sigreturn(%d): copied in FP state (%x) at %p\n", 643 p->p_pid, *(u_int *)&scp->sc_ss.ss_fpstate, 644 &scp->sc_ss.ss_fpstate); 645 if ((sigdebug & SDB_FOLLOW) || 646 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 647 printf("linux_sys_sigreturn(%d): returns\n", p->p_pid); 648 #endif 649 650 return EJUSTRETURN; 651 } 652 653 /* ARGSUSED */ 654 int 655 linux_sys_rt_sigreturn(l, v, retval) 656 struct lwp *l; 657 void *v; 658 register_t *retval; 659 { 660 struct proc *p = l->l_proc; 661 struct frame *frame; 662 struct linux_ucontext *ucp; /* ucontext in user space */ 663 struct linux_ucontext tuc; /* copy of *ucp */ 664 sigset_t mask; 665 int sz = 0, error; /* extra frame size */ 666 667 /* 668 * rt_sigreturn of Linux/m68k takes no arguments. 669 * usp + 4 is a pointer to siginfo structure, 670 * usp + 8 is a pointer to ucontext structure. 671 */ 672 frame = (struct frame *) l->l_md.md_regs; 673 error = copyin((caddr_t) frame->f_regs[SP] + 8, (void *) &ucp, sizeof(void *)); 674 if (error || (int) ucp & 1) 675 goto bad; /* error or odd address */ 676 677 #ifdef DEBUG 678 if (sigdebug & SDB_FOLLOW) 679 printf("linux_rt_sigreturn: pid %d, ucp %p\n", p->p_pid, ucp); 680 #endif 681 682 /* Grab whole of the ucontext. */ 683 if (copyin(ucp, &tuc, sizeof tuc)) 684 bad: sigexit(l, SIGSEGV); 685 686 /* 687 * Check kernel stack and re-enter to syscall() if needed. 688 */ 689 if ((sz = tuc.uc_ss.ss_format) != 0) { 690 if ((sz = exframesize[sz]) < 0) 691 goto bad; 692 if (sz && frame->f_stackadj == 0) { 693 /* 694 * Extra stack space is required but not allocated. 695 * Allocate and re-enter syscall(). 696 */ 697 reenter_syscall(frame, sz); 698 /* NOTREACHED */ 699 } 700 } 701 #ifdef DEBUG 702 /* reenter_syscall() doesn't adjust stack. */ 703 if (sz != frame->f_stackadj) 704 panic("linux_sys_rt_sigreturn: adj: %d != %d", 705 sz, frame->f_stackadj); 706 #endif 707 708 if (tuc.uc_mc.mc_version != LINUX_MCONTEXT_VERSION) 709 goto bad; 710 711 /* Restore signal stack. */ 712 p->p_sigctx.ps_sigstk.ss_flags = 713 (p->p_sigctx.ps_sigstk.ss_flags & ~SS_ONSTACK) | 714 (tuc.uc_stack.ss_flags & LINUX_SS_ONSTACK ? SS_ONSTACK : 0); 715 716 /* Restore signal mask. */ 717 linux_to_native_sigset(&mask, &tuc.uc_sigmask); 718 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 719 720 /* 721 * Restore the user supplied information. 722 */ 723 bcopy(tuc.uc_mc.mc_gregs.gr_regs, frame->f_regs, sizeof(u_int)*16); 724 frame->f_pc = tuc.uc_mc.mc_gregs.gr_pc; 725 /* Privileged bits of sr are silently ignored on Linux/m68k. */ 726 frame->f_sr = tuc.uc_mc.mc_gregs.gr_sr & ~(PSL_MBZ|PSL_IPL|PSL_S); 727 728 /* 729 * Restore long stack frames. Note that we do not copy 730 * back the saved SR or PC, they were picked up above from 731 * the ucontext structure. 732 */ 733 if (tuc.uc_ss.ss_format) { 734 frame->f_format = tuc.uc_ss.ss_format; 735 frame->f_vector = tuc.uc_ss.ss_vector; 736 if (frame->f_stackadj < sz) /* just in case... */ 737 goto bad; 738 frame->f_stackadj -= sz; 739 bcopy(&tuc.uc_ss.ss_frame, &frame->F_u, sz); 740 #ifdef DEBUG 741 if (sigdebug & SDB_FOLLOW) 742 printf("linux_sys_rt_sigreturn(%d): copy in %d of frame type %d\n", 743 p->p_pid, sz, tuc.uc_ss.ss_format); 744 #endif 745 } 746 747 /* 748 * Finally we restore the original FP context. 749 */ 750 switch (fputype) { 751 case FPU_NONE: 752 break; 753 #ifdef M68060 754 case FPU_68060: 755 if (((struct fpframe060*)&tuc.uc_ss.ss_fpstate.FPF_u1) 756 ->fpf6_frmfmt != FPF6_FMT_NULL) { 757 /* 758 * On 060, "fmovem <ea>,fpcr/fpsr/fpi" is 759 * emulated by software and slow. 760 */ 761 asm("fmovem %0,%%fpcr; fmovem %1,%%fpsr; fmovem %2,%%fpi":: 762 "m" (tuc.uc_mc.mc_fpregs.fpr_fpcr), 763 "m" (tuc.uc_mc.mc_fpregs.fpr_fpsr), 764 "m" (tuc.uc_mc.mc_fpregs.fpr_fpiar)); 765 asm("fmovem %0,%%fp0-%%fp1" : : 766 "m" (tuc.uc_mc.mc_fpregs.fpr_regs[0][0])); 767 } 768 asm("frestore %0" : : "m" (tuc.uc_ss.ss_fpstate.FPF_u1)); 769 break; 770 #endif 771 default: 772 if (tuc.uc_ss.ss_fpstate.fpf_version) { 773 asm("fmovem %0,%%fpcr/%%fpsr/%%fpi; fmovem %1,%%fp0-%%fp1":: 774 "m" (tuc.uc_mc.mc_fpregs.fpr_fpcr), 775 "m" (tuc.uc_mc.mc_fpregs.fpr_regs[0][0])); 776 } 777 asm("frestore %0" : : "m" (tuc.uc_ss.ss_fpstate.FPF_u1)); 778 break; 779 } 780 781 #ifdef DEBUG 782 if ((sigdebug & SDB_FPSTATE) && *(char *)&tuc.uc_ss.ss_fpstate) 783 printf("linux_rt_sigreturn(%d): copied in FP state (%x) at %p\n", 784 p->p_pid, *(u_int *)&tuc.uc_ss.ss_fpstate, 785 &tuc.uc_ss.ss_fpstate); 786 if ((sigdebug & SDB_FOLLOW) || 787 ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)) 788 printf("linux_rt_sigreturn(%d): returns\n", p->p_pid); 789 #endif 790 791 return EJUSTRETURN; 792 } 793 794 /* 795 * MPU cache operation of Linux/m68k, 796 * mainly used for dynamic linking. 797 */ 798 799 /* scope */ 800 #define LINUX_FLUSH_SCOPE_LINE 1 /* a cache line */ 801 #define LINUX_FLUSH_SCOPE_PAGE 2 /* a page */ 802 #define LINUX_FLUSH_SCOPE_ALL 3 /* the whole cache */ 803 /* cache */ 804 #define LINUX_FLUSH_CACHE_DATA 1 /* flush and purge data cache */ 805 #define LINUX_FLUSH_CACHE_INSN 2 /* purge instruction cache */ 806 #define LINUX_FLUSH_CACHE_BOTH 3 /* both */ 807 808 /* ARGSUSED */ 809 int 810 linux_sys_cacheflush(l, v, retval) 811 struct lwp *l; 812 void *v; 813 register_t *retval; 814 { 815 struct linux_sys_cacheflush_args /* { 816 syscallarg(unsigned long) addr; 817 syscallarg(int) scope; 818 syscallarg(int) cache; 819 syscallarg(unsigned long) len; 820 } */ *uap = v; 821 struct proc *p = l->l_proc; 822 int scope, cache; 823 vaddr_t addr; 824 int len; 825 int error; 826 827 scope = SCARG(uap, scope); 828 cache = SCARG(uap, cache); 829 830 if (scope < LINUX_FLUSH_SCOPE_LINE || scope > LINUX_FLUSH_SCOPE_ALL 831 || cache & ~LINUX_FLUSH_CACHE_BOTH) 832 return EINVAL; 833 834 #if defined(M68040) || defined(M68060) 835 addr = (vaddr_t) SCARG(uap, addr); 836 len = (int) SCARG(uap, len); 837 #else 838 /* 839 * We always flush entire cache on 68020/030 840 * and these values are not used afterwards. 841 */ 842 addr = 0; 843 len = 0; 844 #endif 845 846 /* 847 * LINUX_FLUSH_SCOPE_ALL (flush whole cache) is limited to super users. 848 */ 849 if (scope == LINUX_FLUSH_SCOPE_ALL) { 850 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 851 return error; 852 #if defined(M68040) || defined(M68060) 853 /* entire cache */ 854 len = INT_MAX; 855 #endif 856 } 857 858 error = 0; 859 if (cache & LINUX_FLUSH_CACHE_DATA) 860 if ((error = cachectl1(CC_EXTPURGE|CC_PURGE, addr, len, p)) !=0) 861 return error; 862 if (cache & LINUX_FLUSH_CACHE_INSN) 863 error = cachectl1(CC_EXTPURGE|CC_IPURGE, addr, len, p); 864 865 return error; 866 } 867 868 /* 869 * Convert NetBSD's devices to Linux's. 870 */ 871 dev_t 872 linux_fakedev(dev, raw) 873 dev_t dev; 874 int raw; 875 { 876 877 /* do nothing for now */ 878 return dev; 879 } 880 881 /* 882 * We come here in a last attempt to satisfy a Linux ioctl() call. 883 */ 884 int 885 linux_machdepioctl(p, v, retval) 886 struct proc *p; 887 void *v; 888 register_t *retval; 889 { 890 struct linux_sys_ioctl_args /* { 891 syscallarg(int) fd; 892 syscallarg(u_long) com; 893 syscallarg(caddr_t) data; 894 } */ *uap = v; 895 struct sys_ioctl_args bia; 896 u_long com; 897 898 SCARG(&bia, fd) = SCARG(uap, fd); 899 SCARG(&bia, data) = SCARG(uap, data); 900 com = SCARG(uap, com); 901 902 switch (com) { 903 904 /* do nothing for now */ 905 906 default: 907 printf("linux_machdepioctl: invalid ioctl %08lx\n", com); 908 return EINVAL; 909 } 910 SCARG(&bia, com) = com; 911 return sys_ioctl(curlwp, &bia, retval); 912 } 913