1 /* $NetBSD: linux_machdep.c,v 1.7 1999/09/12 01:17:31 chs 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 Eric Haszlakiewicz. 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 * Based on sys/arch/i386/i386/linux_machdep.c: 39 * linux_machdep.c,v 1.42 1998/09/11 12:50:06 mycroft Exp 40 * written by Frank van der Linden 41 * 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/signalvar.h> 47 #include <sys/kernel.h> 48 #include <sys/map.h> 49 #include <sys/proc.h> 50 #include <sys/user.h> 51 #include <sys/buf.h> 52 #include <sys/reboot.h> 53 #include <sys/conf.h> 54 #include <sys/exec.h> 55 #include <sys/file.h> 56 #include <sys/callout.h> 57 #include <sys/malloc.h> 58 #include <sys/mbuf.h> 59 #include <sys/msgbuf.h> 60 #include <sys/mount.h> 61 #include <sys/vnode.h> 62 #include <sys/device.h> 63 #include <sys/syscallargs.h> 64 #include <sys/filedesc.h> 65 #include <sys/exec_elf.h> 66 67 #include <vm/vm.h> 68 69 #include <uvm/uvm_extern.h> 70 71 #include <compat/linux/common/linux_types.h> 72 #include <compat/linux/common/linux_signal.h> 73 #include <compat/linux/common/linux_siginfo.h> 74 #include <compat/linux/common/linux_util.h> 75 #include <compat/linux/common/linux_ioctl.h> 76 #include <compat/linux/common/linux_exec.h> 77 #include <compat/linux/common/linux_machdep.h> 78 #include <compat/linux/common/linux_emuldata.h> 79 80 #include <compat/linux/linux_syscallargs.h> 81 82 #include <machine/alpha.h> 83 #include <machine/reg.h> 84 85 #include "wsdisplay.h" 86 #if (NWSDISPLAY >0) 87 #include <sys/ioctl.h> 88 #include <dev/wscons/wsdisplay_usl_io.h> 89 #endif 90 91 /* 92 * Deal with some alpha-specific things in the Linux emulation code. 93 */ 94 95 void 96 linux_setregs(p, epp, stack) 97 struct proc *p; 98 struct exec_package *epp; 99 u_long stack; 100 { 101 /* XXX XAX I think this is ok. not sure though. */ 102 setregs(p, epp, stack); 103 } 104 105 void setup_linux_rt_sigframe(tf, sig, mask) 106 struct trapframe *tf; 107 int sig; 108 sigset_t *mask; 109 { 110 register struct proc *p = curproc; 111 struct linux_rt_sigframe *sfp, sigframe; 112 struct sigacts *psp = p->p_sigacts; 113 int onstack; 114 int fsize, rndfsize; 115 extern char linux_rt_sigcode[], linux_rt_esigcode[]; 116 117 /* Do we need to jump onto the signal stack? */ 118 onstack = (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 119 (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0; 120 121 /* Allocate space for the signal handler context. */ 122 fsize = sizeof(struct linux_rt_sigframe); 123 rndfsize = ((fsize + 15) / 16) * 16; 124 125 if (onstack) 126 sfp = (struct linux_rt_sigframe *) 127 ((caddr_t)psp->ps_sigstk.ss_sp + 128 psp->ps_sigstk.ss_size); 129 else 130 sfp = (struct linux_rt_sigframe *)(alpha_pal_rdusp()); 131 sfp = (struct linux_rt_sigframe *)((caddr_t)sfp - rndfsize); 132 133 #ifdef DEBUG 134 if ((sigdebug & SDB_KSTACK) && p->p_pid = sigpid) 135 printf("linux_sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, 136 sig, &onstack, sfp); 137 #endif /* DEBUG */ 138 139 /* 140 * Build the signal context to be used by sigreturn. 141 */ 142 bzero(&sigframe.uc, sizeof(struct linux_ucontext)); 143 sigframe.uc.uc_mcontext.sc_onstack = onstack; 144 /* XXX XAX is sc_mask the correct field? isn't there more room here? */ 145 native_to_linux_sigset(mask, &sigframe.uc.uc_mcontext.sc_mask); 146 sigframe.uc.uc_mcontext.sc_pc = tf->tf_regs[FRAME_PC]; 147 sigframe.uc.uc_mcontext.sc_ps = ALPHA_PSL_USERMODE; 148 frametoreg(tf, (struct reg *)sigframe.uc.uc_mcontext.sc_regs); 149 sigframe.uc.uc_mcontext.sc_regs[R_SP] = alpha_pal_rdusp(); 150 151 if (p == fpcurproc) { 152 alpha_pal_wrfen(1); 153 savefpstate(&p->p_addr->u_pcb.pcb_fp); 154 alpha_pal_wrfen(0); 155 sigframe.uc.uc_mcontext.sc_fpcr = p->p_addr->u_pcb.pcb_fp.fpr_cr; 156 fpcurproc = NULL; 157 } 158 /* XXX ownedfp ? etc...? */ 159 160 sigframe.uc.uc_mcontext.sc_traparg_a0 = tf->tf_regs[FRAME_A0]; 161 sigframe.uc.uc_mcontext.sc_traparg_a1 = tf->tf_regs[FRAME_A1]; 162 sigframe.uc.uc_mcontext.sc_traparg_a2 = tf->tf_regs[FRAME_A2]; 163 164 /* 165 * XXX XAX Create bogus siginfo data. This can't really 166 * XXX be fixed until NetBSD has realtime signals. 167 * XXX Or we do the emuldata thing. 168 * XXX -erh 169 */ 170 bzero(&sigframe.info, sizeof(struct linux_siginfo)); 171 sigframe.info.lsi_signo = sig; 172 sigframe.info.lsi_code = LINUX_SI_USER; 173 sigframe.info.lsi_pid = p->p_pid; 174 sigframe.info.lsi_uid = p->p_ucred->cr_uid; /* Use real uid here? */ 175 176 if (copyout((caddr_t)&sigframe, (caddr_t)sfp, fsize) != 0) { 177 #ifdef DEBUG 178 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 179 printf("sendsig(%d): copyout failed on sig %d\n", 180 p->p_pid, sig); 181 #endif 182 /* 183 * Process has trashed its stack; give it an illegal 184 * instruction to halt it in its tracks. 185 */ 186 sigexit(p, SIGILL); 187 /* NOTREACHED */ 188 } 189 190 /* Pass pointers to siginfo and ucontext in the regs */ 191 tf->tf_regs[FRAME_A1] = (unsigned long)&sfp->info; 192 tf->tf_regs[FRAME_A2] = (unsigned long)&sfp->uc; 193 194 /* Address of trampoline code. End up at this PC after mi_switch */ 195 tf->tf_regs[FRAME_PC] = 196 (u_int64_t)(PS_STRINGS - (linux_rt_esigcode - linux_rt_sigcode)); 197 198 /* Adjust the stack */ 199 alpha_pal_wrusp((unsigned long)sfp); 200 201 /* Remember that we're now on the signal stack. */ 202 if (onstack) 203 psp->ps_sigstk.ss_flags |= SS_ONSTACK; 204 } 205 206 void setup_linux_sigframe(tf, sig, mask) 207 struct trapframe *tf; 208 int sig; 209 sigset_t *mask; 210 { 211 register struct proc *p = curproc; 212 struct linux_sigframe *sfp, sigframe; 213 struct sigacts *psp = p->p_sigacts; 214 int onstack; 215 int fsize, rndfsize; 216 extern char linux_sigcode[], linux_esigcode[]; 217 218 /* Do we need to jump onto the signal stack? */ 219 onstack = (psp->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 220 (psp->ps_sigact[sig].sa_flags & SA_ONSTACK) != 0; 221 222 /* Allocate space for the signal handler context. */ 223 fsize = sizeof(struct linux_sigframe); 224 rndfsize = ((fsize + 15) / 16) * 16; 225 226 if (onstack) 227 sfp = (struct linux_sigframe *) 228 ((caddr_t)psp->ps_sigstk.ss_sp + 229 psp->ps_sigstk.ss_size); 230 else 231 sfp = (struct linux_sigframe *)(alpha_pal_rdusp()); 232 sfp = (struct linux_sigframe *)((caddr_t)sfp - rndfsize); 233 234 #ifdef DEBUG 235 if ((sigdebug & SDB_KSTACK) && p->p_pid = sigpid) 236 printf("linux_sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid, 237 sig, &onstack, sfp); 238 #endif /* DEBUG */ 239 240 /* 241 * Build the signal context to be used by sigreturn. 242 */ 243 bzero(&sigframe.sf_sc, sizeof(struct linux_ucontext)); 244 sigframe.sf_sc.sc_onstack = onstack; 245 native_to_linux_old_sigset(mask, &sigframe.sf_sc.sc_mask); 246 sigframe.sf_sc.sc_pc = tf->tf_regs[FRAME_PC]; 247 sigframe.sf_sc.sc_ps = ALPHA_PSL_USERMODE; 248 frametoreg(tf, (struct reg *)sigframe.sf_sc.sc_regs); 249 sigframe.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp(); 250 251 if (p == fpcurproc) { 252 alpha_pal_wrfen(1); 253 savefpstate(&p->p_addr->u_pcb.pcb_fp); 254 alpha_pal_wrfen(0); 255 sigframe.sf_sc.sc_fpcr = p->p_addr->u_pcb.pcb_fp.fpr_cr; 256 fpcurproc = NULL; 257 } 258 /* XXX ownedfp ? etc...? */ 259 260 sigframe.sf_sc.sc_traparg_a0 = tf->tf_regs[FRAME_A0]; 261 sigframe.sf_sc.sc_traparg_a1 = tf->tf_regs[FRAME_A1]; 262 sigframe.sf_sc.sc_traparg_a2 = tf->tf_regs[FRAME_A2]; 263 264 if (copyout((caddr_t)&sigframe, (caddr_t)sfp, fsize) != 0) { 265 #ifdef DEBUG 266 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 267 printf("sendsig(%d): copyout failed on sig %d\n", 268 p->p_pid, sig); 269 #endif 270 /* 271 * Process has trashed its stack; give it an illegal 272 * instruction to halt it in its tracks. 273 */ 274 sigexit(p, SIGILL); 275 /* NOTREACHED */ 276 } 277 278 /* Pass pointers to sigcontext in the regs */ 279 tf->tf_regs[FRAME_A1] = 0; 280 tf->tf_regs[FRAME_A2] = (unsigned long)&sfp->sf_sc; 281 282 /* Address of trampoline code. End up at this PC after mi_switch */ 283 tf->tf_regs[FRAME_PC] = 284 (u_int64_t)(PS_STRINGS - (linux_esigcode - linux_sigcode)); 285 286 /* Adjust the stack */ 287 alpha_pal_wrusp((unsigned long)sfp); 288 289 /* Remember that we're now on the signal stack. */ 290 if (onstack) 291 psp->ps_sigstk.ss_flags |= SS_ONSTACK; 292 } 293 294 /* 295 * Send an interrupt to process. 296 * 297 * Stack is set up to allow sigcode stored 298 * in u. to call routine, followed by kcall 299 * to sigreturn routine below. After sigreturn 300 * resets the signal mask, the stack, and the 301 * frame pointer, it returns to the user 302 * specified pc, psl. 303 */ 304 void 305 linux_sendsig(catcher, sig, mask, code) 306 sig_t catcher; 307 int sig; 308 sigset_t *mask; 309 u_long code; 310 { 311 register struct proc *p = curproc; 312 register struct trapframe *tf = p->p_md.md_tf; 313 struct linux_emuldata *edp; 314 315 /* Setup the signal frame (and part of the trapframe) */ 316 /*OLD: if (p->p_sigacts->ps_siginfo & sigmask(sig))*/ 317 /* XXX XAX this is broken now. need someplace to store what 318 XXX XAX kind of signal handler a signal has.*/ 319 #if 0 320 edp = (struct linux_emuldata *)p->p_emuldata; 321 #else 322 edp = 0; 323 #endif 324 if (edp && sigismember(&edp->ps_siginfo, sig)) 325 setup_linux_rt_sigframe(tf, sig, mask); 326 else 327 setup_linux_sigframe(tf, sig, mask); 328 329 /* Signal handler for trampoline code */ 330 tf->tf_regs[FRAME_T12] = (u_int64_t)catcher; 331 tf->tf_regs[FRAME_A0] = native_to_linux_sig[sig]; 332 333 /* 334 * Linux has a custom restorer option. To support it we would 335 * need to store an array of restorers and a sigcode block 336 * which knew to use it. Doesn't seem worth the trouble. 337 * -erh 338 */ 339 340 #ifdef DEBUG 341 if (sigdebug & SDB_FOLLOW) 342 printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid, 343 tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]); 344 if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) 345 printf("sendsig(%d): sig %d returns\n", p->p_pid, sig); 346 #endif 347 } 348 349 /* 350 * System call to cleanup state after a signal 351 * has been taken. Reset signal mask and 352 * stack state from context left by sendsig (above). 353 * Return to previous pc as specified by context 354 * left by sendsig. 355 * Linux real-time signals use a different sigframe, 356 * but the sigcontext is the same. 357 */ 358 359 int 360 linux_restore_sigcontext(p, context) 361 struct proc *p; 362 struct linux_sigcontext context; 363 { 364 sigset_t bss; 365 366 /* 367 * Linux doesn't (yet) have alternate signal stacks. 368 * However, the OSF/1 sigcontext which they use has 369 * an onstack member. This could be needed in the future. 370 */ 371 if (context.sc_onstack & LINUX_SA_ONSTACK) 372 p->p_sigacts->ps_sigstk.ss_flags |= SS_ONSTACK; 373 else 374 p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK; 375 376 /* Reset the signal mask */ 377 /* XXX XAX which sigset do we use? */ 378 linux_to_native_sigset(&context.sc_mask, &bss); 379 (void) sigprocmask1(p, SIG_SETMASK, &bss, 0); 380 381 /* 382 * Check for security violations. 383 * Linux doesn't allow any changes to the PSL. 384 */ 385 if (context.sc_ps != ALPHA_PSL_USERMODE) 386 return(EINVAL); 387 388 p->p_md.md_tf->tf_regs[FRAME_PC] = context.sc_pc; 389 p->p_md.md_tf->tf_regs[FRAME_PS] = context.sc_ps; 390 391 regtoframe((struct reg *)context.sc_regs, p->p_md.md_tf); 392 alpha_pal_wrusp(context.sc_regs[R_SP]); 393 394 if (p == fpcurproc) 395 fpcurproc = NULL; 396 397 /* Restore fp regs and fpr_cr */ 398 bcopy((struct fpreg *)context.sc_fpregs, &p->p_addr->u_pcb.pcb_fp, 399 sizeof(struct fpreg)); 400 /* XXX sc_ownedfp ? */ 401 /* XXX sc_fp_control ? */ 402 403 #ifdef DEBUG 404 if (sigdebug & SDB_FOLLOW) 405 printf("linux_rt_sigreturn(%d): returns\n", p->pid); 406 #endif 407 return (EJUSTRETURN); 408 } 409 410 int 411 linux_sys_rt_sigreturn(p, v, retval) 412 struct proc *p; 413 void *v; 414 register_t *retval; 415 { 416 struct linux_sys_rt_sigreturn_args /* { 417 syscallarg(struct linux_rt_sigframe *) sfp; 418 } */ *uap = v; 419 struct linux_rt_sigframe *sfp, sigframe; 420 421 /* 422 * The trampoline code hands us the context. 423 * It is unsafe to keep track of it ourselves, in the event that a 424 * program jumps out of a signal handler. 425 */ 426 427 sfp = SCARG(uap, sfp); 428 429 if (ALIGN(sfp) != (u_int64_t)sfp) 430 return(EINVAL); 431 432 /* 433 * Fetch the frame structure. 434 */ 435 if (copyin((caddr_t)sfp, &sigframe, 436 sizeof(struct linux_rt_sigframe)) != 0) 437 return (EFAULT); 438 439 return(linux_restore_sigcontext(p, sigframe.uc.uc_mcontext)); 440 } 441 442 443 int 444 linux_sys_sigreturn(p, v, retval) 445 struct proc *p; 446 void *v; 447 register_t *retval; 448 { 449 struct linux_sys_sigreturn_args /* { 450 syscallarg(struct linux_sigframe *) sfp; 451 } */ *uap = v; 452 struct linux_sigcontext *scp, context; 453 454 /* 455 * The trampoline code hands us the context. 456 * It is unsafe to keep track of it ourselves, in the event that a 457 * program jumps out of a signal handler. 458 */ 459 460 /* XXX Only works because sigcontext is first in sigframe */ 461 /* XXX extramask is ignored */ 462 scp = (struct linux_sigcontext *)SCARG(uap, sfp); 463 464 if (ALIGN(scp) != (u_int64_t)scp) 465 return(EINVAL); 466 467 /* 468 * Fetch the context structure. 469 */ 470 if (copyin((caddr_t)scp, &context, 471 sizeof(struct linux_sigcontext)) != 0) 472 return (EFAULT); 473 474 return(linux_restore_sigcontext(p, context)); 475 } 476 477 /* 478 * We come here in a last attempt to satisfy a Linux ioctl() call 479 */ 480 /* XXX XAX update this, add maps, etc... */ 481 int 482 linux_machdepioctl(p, v, retval) 483 struct proc *p; 484 void *v; 485 register_t *retval; 486 { 487 struct linux_sys_ioctl_args /* { 488 syscallarg(int) fd; 489 syscallarg(u_long) com; 490 syscallarg(caddr_t) data; 491 } */ *uap = v; 492 struct sys_ioctl_args bia; 493 u_long com; 494 495 SCARG(&bia, fd) = SCARG(uap, fd); 496 SCARG(&bia, data) = SCARG(uap, data); 497 com = SCARG(uap, com); 498 499 switch (com) { 500 default: 501 printf("linux_machdepioctl: invalid ioctl %08lx\n", com); 502 return EINVAL; 503 } 504 SCARG(&bia, com) = com; 505 return sys_ioctl(p, &bia, retval); 506 } 507 508 /* XXX XAX fix this */ 509 dev_t 510 linux_fakedev(dev) 511 dev_t dev; 512 { 513 return dev; 514 } 515 516