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