1 /* $NetBSD: linux_machdep.c,v 1.18 2002/07/28 07:38:34 chs 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.18 2002/07/28 07:38:34 chs 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(sig, mask, code) /* XXX Check me */ 121 int sig; 122 sigset_t *mask; 123 u_long code; 124 { 125 struct proc *p = curproc; 126 struct trapframe *tf; 127 sig_t catcher = SIGACTION(p, sig).sa_handler; 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 save_fpu_proc(curproc); 200 memcpy(&frame.lfp_regs, curpcb->pcb_fpu.fpr, sizeof(frame.lfp_regs)); 201 202 /* 203 * Copy Linux's signal trampoline on the user stack It should not 204 * be used, but Linux binaries might expect it to be there. 205 */ 206 frame.ltramp[0] = 0x38997777; /* li r0, 0x7777 */ 207 frame.ltramp[1] = 0x44000002; /* sc */ 208 209 /* 210 * Move it to the user stack 211 * There is a little trick here, about the LINUX_ABIGAP: the 212 * linux_sigreg structure has a 56 int gap to support rs6000/xcoff 213 * binaries. But the Linux kernel seems to do without it, and it 214 * just skip it when building the stack frame. Hence the LINUX_ABIGAP. 215 */ 216 if (copyout(&frame, (caddr_t)fp, sizeof (frame) - LINUX_ABIGAP) != 0) { 217 /* 218 * Process has trashed its stack; give it an illegal 219 * instruction to halt it in its tracks. 220 */ 221 sigexit(p, SIGILL); 222 /* NOTREACHED */ 223 } 224 225 /* 226 * Add a sigcontext on the stack 227 */ 228 fp -= sizeof(struct linux_sigcontext); 229 if (copyout(&sc, (caddr_t)fp, sizeof (struct linux_sigcontext)) != 0) { 230 /* 231 * Process has trashed its stack; give it an illegal 232 * instruction to halt it in its tracks. 233 */ 234 sigexit(p, SIGILL); 235 /* NOTREACHED */ 236 } 237 238 /* 239 * Set the registers according to how the Linux process expects them. 240 * "Mind the gap" Linux expects a gap here. 241 */ 242 tf->fixreg[1] = fp - LINUX__SIGNAL_FRAMESIZE; 243 tf->lr = (int)catcher; 244 tf->fixreg[3] = (int)native_to_linux_signo[sig]; 245 tf->fixreg[4] = fp; 246 tf->srr0 = (int)p->p_sigctx.ps_sigcode; 247 248 #ifdef DEBUG_LINUX 249 printf("fp at end of linux_sendsig = %x\n", fp); 250 #endif 251 /* 252 * Remember that we're now on the signal stack. 253 */ 254 if (onstack) 255 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 256 #ifdef DEBUG_LINUX 257 printf("linux_sendsig: exitting. fp=0x%lx\n",(long)fp); 258 #endif 259 } 260 261 /* 262 * System call to cleanup state after a signal 263 * has been taken. Reset signal mask and 264 * stack state from context left by sendsig (above). 265 * Return to previous pc and psl as specified by 266 * context left by sendsig. Check carefully to 267 * make sure that the user has not modified the 268 * psl to gain improper privileges or to cause 269 * a machine fault. 270 * 271 * XXX not tested 272 */ 273 int 274 linux_sys_rt_sigreturn(p, v, retval) 275 struct proc *p; 276 void *v; 277 register_t *retval; 278 { 279 struct linux_sys_rt_sigreturn_args /* { 280 syscallarg(struct linux_rt_sigframe *) sfp; 281 } */ *uap = v; 282 struct linux_rt_sigframe *scp, sigframe; 283 struct linux_sigregs sregs; 284 struct linux_pt_regs *lregs; 285 struct trapframe *tf; 286 sigset_t mask; 287 int i; 288 289 /* 290 * The trampoline code hands us the context. 291 * It is unsafe to keep track of it ourselves, in the event that a 292 * program jumps out of a signal handler. 293 */ 294 scp = SCARG(uap, sfp); 295 296 /* 297 * Get the context from user stack 298 */ 299 if (copyin((caddr_t)scp, &sigframe, sizeof(*scp))) 300 return (EFAULT); 301 302 /* 303 * Make sure, fpu is sync'ed 304 */ 305 save_fpu_proc(curproc); 306 307 /* 308 * Restore register context. 309 */ 310 if (copyin((caddr_t)sigframe.luc.luc_context.lregs, 311 &sregs, sizeof(sregs))) 312 return (EFAULT); 313 lregs = (struct linux_pt_regs *)&sregs.lgp_regs; 314 315 tf = trapframe(p); 316 #ifdef DEBUG_LINUX 317 printf("linux_sys_sigreturn: trapframe=0x%lx scp=0x%lx\n", 318 (unsigned long)tf, (unsigned long)scp); 319 #endif 320 321 if ((lregs->lmsr & PSL_USERSTATIC) != (tf->srr1 & PSL_USERSTATIC)) 322 return (EINVAL); 323 324 for (i = 0; i < 32; i++) 325 tf->fixreg[i] = lregs->lgpr[i]; 326 tf->lr = lregs->llink; 327 tf->cr = lregs->lccr; 328 tf->xer = lregs->lxer; 329 tf->ctr = lregs->lctr; 330 tf->srr0 = lregs->lnip; 331 tf->srr1 = lregs->lmsr; 332 333 memcpy(curpcb->pcb_fpu.fpr, (caddr_t)&sregs.lfp_regs, 334 sizeof(curpcb->pcb_fpu.fpr)); 335 336 /* 337 * Restore signal stack. 338 * 339 * XXX cannot find the onstack information in Linux sig context. 340 * Is signal stack really supported on Linux? 341 * 342 * It seems to be supported in libc6... 343 */ 344 /* if (sc.sc_onstack & SS_ONSTACK) 345 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 346 else */ 347 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 348 349 /* 350 * Grab the signal mask 351 */ 352 linux_to_native_sigset(&mask, &sigframe.luc.luc_sigmask); 353 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 354 355 return (EJUSTRETURN); 356 } 357 358 359 /* 360 * The following needs code review for potential security issues 361 */ 362 int 363 linux_sys_sigreturn(p, v, retval) 364 struct proc *p; 365 void *v; 366 register_t *retval; 367 { 368 struct linux_sys_sigreturn_args /* { 369 syscallarg(struct linux_sigcontext *) scp; 370 } */ *uap = v; 371 struct linux_sigcontext *scp, context; 372 struct linux_sigregs sregs; 373 struct linux_pt_regs *lregs; 374 struct trapframe *tf; 375 sigset_t mask; 376 int i; 377 378 /* 379 * The trampoline code hands us the context. 380 * It is unsafe to keep track of it ourselves, in the event that a 381 * program jumps out of a signal handler. 382 */ 383 scp = SCARG(uap, scp); 384 385 /* 386 * Get the context from user stack 387 */ 388 if (copyin(scp, &context, sizeof(*scp))) 389 return (EFAULT); 390 391 /* 392 * Make sure, fpu is in sync 393 */ 394 save_fpu_proc(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(&mask, &context.lmask, 439 &context._unused[3]); 440 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 441 442 return (EJUSTRETURN); 443 } 444 445 446 #if 0 447 int 448 linux_sys_modify_ldt(p, v, retval) 449 struct proc *p; 450 void *v; 451 register_t *retval; 452 { 453 /* 454 * This syscall is not implemented in Linux/PowerPC: we should not 455 * be here 456 */ 457 #ifdef DEBUG_LINUX 458 printf("linux_sys_modify_ldt: should not be here.\n"); 459 #endif 460 return 0; 461 } 462 #endif 463 464 /* 465 * major device numbers remapping 466 */ 467 dev_t 468 linux_fakedev(dev, raw) 469 dev_t dev; 470 int raw; 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