1 /* $NetBSD: linux_machdep.c,v 1.11 2001/06/13 23:09:01 wiz Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Emmanuel Dreyfus. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/signalvar.h> 42 #include <sys/kernel.h> 43 #include <sys/map.h> 44 #include <sys/proc.h> 45 #include <sys/user.h> 46 #include <sys/buf.h> 47 #include <sys/reboot.h> 48 #include <sys/conf.h> 49 #include <sys/exec.h> 50 #include <sys/file.h> 51 #include <sys/callout.h> 52 #include <sys/malloc.h> 53 #include <sys/mbuf.h> 54 #include <sys/msgbuf.h> 55 #include <sys/mount.h> 56 #include <sys/vnode.h> 57 #include <sys/device.h> 58 #include <sys/syscallargs.h> 59 #include <sys/filedesc.h> 60 #include <sys/exec_elf.h> 61 #include <sys/disklabel.h> 62 #include <sys/ioctl.h> 63 #include <miscfs/specfs/specdev.h> 64 65 #include <compat/linux/common/linux_types.h> 66 #include <compat/linux/common/linux_signal.h> 67 #include <compat/linux/common/linux_util.h> 68 #include <compat/linux/common/linux_ioctl.h> 69 #include <compat/linux/common/linux_hdio.h> 70 #include <compat/linux/common/linux_exec.h> 71 #include <compat/linux/common/linux_machdep.h> 72 73 #include <compat/linux/linux_syscallargs.h> 74 75 #include <machine/cpu.h> 76 #include <machine/fpu.h> 77 #include <machine/psl.h> 78 #include <machine/reg.h> 79 #include <machine/vmparam.h> 80 81 /* 82 * To see whether wscons is configured (for virtual console ioctl calls). 83 */ 84 #if defined(_KERNEL_OPT) 85 #include "wsdisplay.h" 86 #endif 87 #if (NWSDISPLAY > 0) 88 #include <dev/wscons/wsconsio.h> 89 #include <dev/wscons/wsdisplay_usl_io.h> 90 #endif 91 92 /* 93 * Set set up registers on exec. 94 * XXX not used at the moment since in sys/kern/exec_conf, LINUX_COMPAT 95 * entry uses NetBSD's native setregs instead of linux_setregs 96 */ 97 void 98 linux_setregs(p, pack, stack) 99 struct proc *p; 100 struct exec_package *pack; 101 u_long stack; 102 { 103 setregs(p, pack, stack); 104 } 105 106 /* 107 * Send an interrupt to process. 108 * 109 * Adapted from arch/powerpc/powerpc/sig_machdep.c:sendsig and 110 * compat/linux/arch/i386/linux_machdep.c:linux_sendsig 111 * 112 * XXX Does not work well yet with RT signals 113 * 114 */ 115 116 void 117 linux_sendsig(catcher, sig, mask, code) /* XXX Check me */ 118 sig_t catcher; 119 int sig; 120 sigset_t *mask; 121 u_long code; 122 { 123 struct proc *p = curproc; 124 struct trapframe *tf; 125 struct linux_sigregs frame; 126 struct linux_pt_regs linux_regs; 127 struct linux_sigcontext sc; 128 register_t fp; 129 int onstack; 130 int i; 131 132 tf = trapframe(p); 133 134 /* 135 * Do we need to jump onto the signal stack? 136 */ 137 onstack = 138 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 139 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 140 141 /* 142 * Signal stack is broken (see at the end of linux_sigreturn), so we do 143 * not use it yet. XXX fix this. 144 */ 145 onstack=0; 146 147 /* 148 * Allocate space for the signal handler context. 149 */ 150 if (onstack) { 151 fp = (register_t) 152 ((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + 153 p->p_sigctx.ps_sigstk.ss_size); 154 } else { 155 fp = tf->fixreg[1]; 156 } 157 #ifdef DEBUG_LINUX 158 printf("fp at start of linux_sendsig = %x\n", fp); 159 #endif 160 fp -= sizeof(struct linux_sigregs); 161 fp &= ~0xf; 162 163 /* 164 * Prepare a sigcontext for later. 165 */ 166 memset(&sc, 0, sizeof sc); 167 sc.lsignal = (int)native_to_linux_sig[sig]; 168 sc.lhandler = (unsigned long)catcher; 169 native_to_linux_old_extra_sigset(mask, &sc.lmask, &sc._unused[3]); 170 sc.lregs = (struct linux_pt_regs*)fp; 171 172 /* 173 * Setup the signal stack frame as Linux does it in 174 * arch/ppc/kernel/signal.c:setup_frame() 175 * 176 * Save register context. 177 */ 178 for (i = 0; i < 32; i++) 179 linux_regs.lgpr[i] = tf->fixreg[i]; 180 linux_regs.lnip = tf->srr0; 181 linux_regs.lmsr = tf->srr1; 182 linux_regs.lorig_gpr3 = tf->fixreg[3]; /* XXX Is that right? */ 183 linux_regs.lctr = tf->ctr; 184 linux_regs.llink = tf->lr; 185 linux_regs.lxer = tf->xer; 186 linux_regs.lccr = tf->cr; 187 linux_regs.lmq = 0; /* Unused, 601 only */ 188 linux_regs.ltrap = tf->exc; 189 linux_regs.ldar = tf->dar; 190 linux_regs.ldsisr = tf->dsisr; 191 linux_regs.lresult = 0; 192 193 memset(&frame, 0, sizeof(frame)); 194 memcpy(&frame.lgp_regs, &linux_regs, sizeof(linux_regs)); 195 196 if (curproc == fpuproc) 197 save_fpu(curproc); 198 memcpy(&frame.lfp_regs, curpcb->pcb_fpu.fpr, sizeof(frame.lfp_regs)); 199 200 /* 201 * Copy Linux's signal trampoline on the user stack It should not 202 * be used, but Linux binaries might expect it to be there. 203 */ 204 frame.ltramp[0] = 0x38997777; /* li r0, 0x7777 */ 205 frame.ltramp[1] = 0x44000002; /* sc */ 206 207 /* 208 * Move it to the user stack 209 * There is a little trick here, about the LINUX_ABIGAP: the 210 * linux_sigreg structure has a 56 int gap to support rs6000/xcoff 211 * binaries. But the Linux kernel seems to do without it, and it 212 * just skip it when building the stack frame. Hence the LINUX_ABIGAP. 213 */ 214 if (copyout(&frame, (caddr_t)fp, sizeof (frame) - LINUX_ABIGAP) != 0) { 215 /* 216 * Process has trashed its stack; give it an illegal 217 * instruction to halt it in its tracks. 218 */ 219 sigexit(p, SIGILL); 220 /* NOTREACHED */ 221 } 222 223 /* 224 * Add a sigcontext on the stack 225 */ 226 fp -= sizeof(struct linux_sigcontext); 227 if (copyout(&sc, (caddr_t)fp, sizeof (struct linux_sigcontext)) != 0) { 228 /* 229 * Process has trashed its stack; give it an illegal 230 * instruction to halt it in its tracks. 231 */ 232 sigexit(p, SIGILL); 233 /* NOTREACHED */ 234 } 235 236 /* 237 * Set the registers according to how the Linux process expects them. 238 * "Mind the gap" Linux expects a gap here. 239 */ 240 tf->fixreg[1] = fp - LINUX__SIGNAL_FRAMESIZE; 241 tf->lr = (int)catcher; 242 tf->fixreg[3] = (int)native_to_linux_sig[sig]; 243 tf->fixreg[4] = fp; 244 tf->srr0 = (int)p->p_sigctx.ps_sigcode; 245 246 #ifdef DEBUG_LINUX 247 printf("fp at end of linux_sendsig = %x\n", fp); 248 #endif 249 /* 250 * Remember that we're now on the signal stack. 251 */ 252 if (onstack) 253 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 254 #ifdef DEBUG_LINUX 255 printf("linux_sendsig: exitting. fp=0x%lx\n",(long)fp); 256 #endif 257 } 258 259 /* 260 * System call to cleanup state after a signal 261 * has been taken. Reset signal mask and 262 * stack state from context left by sendsig (above). 263 * Return to previous pc and psl as specified by 264 * context left by sendsig. Check carefully to 265 * make sure that the user has not modified the 266 * psl to gain improper privileges or to cause 267 * a machine fault. 268 * 269 * XXX not tested 270 */ 271 int 272 linux_sys_rt_sigreturn(p, v, retval) 273 struct proc *p; 274 void *v; 275 register_t *retval; 276 { 277 struct linux_sys_rt_sigreturn_args /* { 278 syscallarg(struct linux_rt_sigframe *) sfp; 279 } */ *uap = v; 280 struct linux_rt_sigframe *scp, sigframe; 281 struct linux_sigregs sregs; 282 struct linux_pt_regs *lregs; 283 struct trapframe *tf; 284 sigset_t mask; 285 int i; 286 287 /* 288 * The trampoline code hands us the context. 289 * It is unsafe to keep track of it ourselves, in the event that a 290 * program jumps out of a signal handler. 291 */ 292 scp = SCARG(uap, sfp); 293 294 /* 295 * Get the context from user stack 296 */ 297 if (copyin((caddr_t)scp, &sigframe, sizeof(*scp))) 298 return (EFAULT); 299 300 /* 301 * Make sure, fpu is sync'ed 302 */ 303 if (curproc == fpuproc) 304 save_fpu(curproc); 305 306 /* 307 * Restore register context. 308 */ 309 if (copyin((caddr_t)sigframe.luc.luc_context.lregs, 310 &sregs, sizeof(sregs))) 311 return (EFAULT); 312 lregs = (struct linux_pt_regs *)&sregs.lgp_regs; 313 314 tf = trapframe(p); 315 #ifdef DEBUG_LINUX 316 printf("linux_sys_sigreturn: trapframe=0x%lx scp=0x%lx\n", 317 (unsigned long)tf, (unsigned long)scp); 318 #endif 319 320 if ((lregs->lmsr & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) 321 return (EINVAL); 322 323 for (i = 0; i < 32; i++) 324 tf->fixreg[i] = lregs->lgpr[i]; 325 tf->lr = lregs->llink; 326 tf->cr = lregs->lccr; 327 tf->xer = lregs->lxer; 328 tf->ctr = lregs->lctr; 329 tf->srr0 = lregs->lnip; 330 tf->srr1 = lregs->lmsr; 331 332 memcpy(curpcb->pcb_fpu.fpr, (caddr_t)&sregs.lfp_regs, 333 sizeof(curpcb->pcb_fpu.fpr)); 334 335 /* 336 * Restore signal stack. 337 * 338 * XXX cannot find the onstack information in Linux sig context. 339 * Is signal stack really supported on Linux? 340 * 341 * It seems to be supported in libc6... 342 */ 343 /* if (sc.sc_onstack & SS_ONSTACK) 344 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 345 else */ 346 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 347 348 /* 349 * Grab the signal mask 350 */ 351 linux_to_native_sigset(&sigframe.luc.luc_sigmask, &mask); 352 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 353 354 return (EJUSTRETURN); 355 } 356 357 358 /* 359 * The following needs code review for potential security issues 360 */ 361 int 362 linux_sys_sigreturn(p, v, retval) 363 struct proc *p; 364 void *v; 365 register_t *retval; 366 { 367 struct linux_sys_sigreturn_args /* { 368 syscallarg(struct linux_sigcontext *) scp; 369 } */ *uap = v; 370 struct linux_sigcontext *scp, context; 371 struct linux_sigregs sregs; 372 struct linux_pt_regs *lregs; 373 struct trapframe *tf; 374 sigset_t mask; 375 int i; 376 377 /* 378 * The trampoline code hands us the context. 379 * It is unsafe to keep track of it ourselves, in the event that a 380 * program jumps out of a signal handler. 381 */ 382 scp = SCARG(uap, scp); 383 384 /* 385 * Get the context from user stack 386 */ 387 if (copyin(scp, &context, sizeof(*scp))) 388 return (EFAULT); 389 390 /* 391 * Make sure, fpu is in sync 392 */ 393 if (curproc == fpuproc) 394 save_fpu(curproc); 395 396 /* 397 * Restore register context. 398 */ 399 if (copyin((caddr_t)context.lregs, &sregs, sizeof(sregs))) 400 return (EFAULT); 401 lregs = (struct linux_pt_regs *)&sregs.lgp_regs; 402 403 tf = trapframe(p); 404 #ifdef DEBUG_LINUX 405 printf("linux_sys_sigreturn: trapframe=0x%lx scp=0x%lx\n", 406 (unsigned long)tf, (unsigned long)scp); 407 #endif 408 409 if ((lregs->lmsr & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) 410 return (EINVAL); 411 412 for (i = 0; i < 32; i++) 413 tf->fixreg[i] = lregs->lgpr[i]; 414 tf->lr = lregs->llink; 415 tf->cr = lregs->lccr; 416 tf->xer = lregs->lxer; 417 tf->ctr = lregs->lctr; 418 tf->srr0 = lregs->lnip; 419 tf->srr1 = lregs->lmsr; 420 421 memcpy(curpcb->pcb_fpu.fpr, (caddr_t)&sregs.lfp_regs, 422 sizeof(curpcb->pcb_fpu.fpr)); 423 424 /* 425 * Restore signal stack. 426 * 427 * XXX cannot find the onstack information in Linux sig context. 428 * Is signal stack really supported on Linux? 429 */ 430 #if 0 431 if (sc.sc_onstack & SS_ONSTACK) 432 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 433 else 434 #endif 435 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 436 437 /* Restore signal mask. */ 438 linux_old_extra_to_native_sigset(&context.lmask, 439 &context._unused[3], 440 &mask); 441 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 442 443 return (EJUSTRETURN); 444 } 445 446 447 #if 0 448 int 449 linux_sys_modify_ldt(p, v, retval) 450 struct proc *p; 451 void *v; 452 register_t *retval; 453 { 454 /* 455 * This syscall is not implemented in Linux/PowerPC: we should not 456 * be here 457 */ 458 #ifdef DEBUG_LINUX 459 printf("linux_sys_modify_ldt: should not be here.\n"); 460 #endif 461 return 0; 462 } 463 #endif 464 465 /* 466 * major device numbers remapping 467 */ 468 dev_t 469 linux_fakedev(dev) 470 dev_t dev; 471 { 472 /* XXX write me */ 473 return dev; 474 } 475 476 /* 477 * We come here in a last attempt to satisfy a Linux ioctl() call 478 */ 479 int 480 linux_machdepioctl(p, v, retval) 481 struct proc *p; 482 void *v; 483 register_t *retval; 484 { 485 struct linux_sys_ioctl_args /* { 486 syscallarg(int) fd; 487 syscallarg(u_long) com; 488 syscallarg(caddr_t) data; 489 } */ *uap = v; 490 struct sys_ioctl_args bia; 491 u_long com; 492 493 SCARG(&bia, fd) = SCARG(uap, fd); 494 SCARG(&bia, data) = SCARG(uap, data); 495 com = SCARG(uap, com); 496 497 switch (com) { 498 default: 499 printf("linux_machdepioctl: invalid ioctl %08lx\n", com); 500 return EINVAL; 501 } 502 SCARG(&bia, com) = com; 503 return sys_ioctl(p, &bia, retval); 504 } 505 #if 0 506 /* 507 * Set I/O permissions for a process. Just set the maximum level 508 * right away (ignoring the argument), otherwise we would have 509 * to rely on I/O permission maps, which are not implemented. 510 */ 511 int 512 linux_sys_iopl(p, v, retval) 513 struct proc *p; 514 void *v; 515 register_t *retval; 516 { 517 /* 518 * This syscall is not implemented in Linux/PowerPC: we should not be here 519 */ 520 #ifdef DEBUG_LINUX 521 printf("linux_sys_iopl: should not be here.\n"); 522 #endif 523 return 0; 524 } 525 #endif 526 527 /* 528 * See above. If a root process tries to set access to an I/O port, 529 * just let it have the whole range. 530 */ 531 int 532 linux_sys_ioperm(p, v, retval) 533 struct proc *p; 534 void *v; 535 register_t *retval; 536 { 537 /* 538 * This syscall is not implemented in Linux/PowerPC: we should not be here 539 */ 540 #ifdef DEBUG_LINUX 541 printf("linux_sys_ioperm: should not be here.\n"); 542 #endif 543 return 0; 544 } 545 546 /* 547 * wrapper linux_sys_new_uname() -> linux_sys_uname() 548 */ 549 int 550 linux_sys_new_uname(p, v, retval) 551 struct proc *p; 552 void *v; 553 register_t *retval; 554 { 555 return linux_sys_uname(p, v, retval); 556 } 557 558 /* 559 * wrapper linux_sys_new_select() -> linux_sys_select() 560 */ 561 int 562 linux_sys_new_select(p, v, retval) 563 struct proc *p; 564 void *v; 565 register_t *retval; 566 { 567 return linux_sys_select(p, v, retval); 568 } 569