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