1 /* $NetBSD: linux_machdep.c,v 1.41 2010/07/07 01:30: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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.41 2010/07/07 01:30:34 chs Exp $"); 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/signalvar.h> 38 #include <sys/kernel.h> 39 #include <sys/proc.h> 40 #include <sys/buf.h> 41 #include <sys/reboot.h> 42 #include <sys/conf.h> 43 #include <sys/exec.h> 44 #include <sys/file.h> 45 #include <sys/callout.h> 46 #include <sys/malloc.h> 47 #include <sys/mbuf.h> 48 #include <sys/msgbuf.h> 49 #include <sys/mount.h> 50 #include <sys/vnode.h> 51 #include <sys/device.h> 52 #include <sys/syscallargs.h> 53 #include <sys/filedesc.h> 54 #include <sys/exec_elf.h> 55 #include <sys/disklabel.h> 56 #include <sys/ioctl.h> 57 #include <sys/sysctl.h> 58 #include <sys/kauth.h> 59 #include <miscfs/specfs/specdev.h> 60 61 #include <compat/linux/common/linux_types.h> 62 #include <compat/linux/common/linux_signal.h> 63 #include <compat/linux/common/linux_util.h> 64 #include <compat/linux/common/linux_ioctl.h> 65 #include <compat/linux/common/linux_hdio.h> 66 #include <compat/linux/common/linux_exec.h> 67 #include <compat/linux/common/linux_machdep.h> 68 69 #include <compat/linux/linux_syscallargs.h> 70 71 #include <sys/cpu.h> 72 #include <machine/psl.h> 73 #include <machine/reg.h> 74 #include <machine/regnum.h> 75 #include <machine/vmparam.h> 76 #include <machine/locore.h> 77 78 #include <mips/cache.h> 79 80 /* 81 * To see whether wscons is configured (for virtual console ioctl calls). 82 */ 83 #if defined(_KERNEL_OPT) 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 #endif 90 91 /* 92 * Set set up registers on exec. 93 */ 94 void 95 linux_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 96 { 97 setregs(l, pack, stack); 98 return; 99 } 100 101 /* 102 * Send an interrupt to process. 103 * 104 * Adapted from sys/arch/mips/mips/mips_machdep.c 105 * 106 * XXX Does not work well yet with RT signals 107 * 108 */ 109 110 void 111 linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) 112 { 113 const int sig = ksi->ksi_signo; 114 struct lwp *l = curlwp; 115 struct proc *p = l->l_proc; 116 struct linux_sigframe *fp; 117 struct frame *f; 118 int i, onstack, error; 119 sig_t catcher = SIGACTION(p, sig).sa_handler; 120 struct linux_sigframe sf; 121 122 #ifdef DEBUG_LINUX 123 printf("linux_sendsig()\n"); 124 #endif /* DEBUG_LINUX */ 125 f = (struct frame *)l->l_md.md_regs; 126 127 /* 128 * Do we need to jump onto the signal stack? 129 */ 130 onstack = 131 (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 132 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 133 134 /* 135 * Signal stack is broken (see at the end of linux_sigreturn), so we do 136 * not use it yet. XXX fix this. 137 */ 138 onstack=0; 139 140 /* 141 * Allocate space for the signal handler context. 142 */ 143 if (onstack) 144 fp = (struct linux_sigframe *) 145 ((uintptr_t)l->l_sigstk.ss_sp 146 + l->l_sigstk.ss_size); 147 else 148 /* cast for O64 ABI case */ 149 fp = (struct linux_sigframe *)(uintptr_t)f->f_regs[_R_SP]; 150 151 /* 152 * Build stack frame for signal trampoline. 153 */ 154 memset(&sf, 0, sizeof sf); 155 156 /* 157 * This is the signal trampoline used by Linux, we don't use it, 158 * but we set it up in case an application expects it to be there 159 */ 160 sf.lsf_code[0] = 0x24020000; /* li v0, __NR_sigreturn */ 161 sf.lsf_code[1] = 0x0000000c; /* syscall */ 162 163 native_to_linux_sigset(&sf.lsf_mask, mask); 164 for (i=0; i<32; i++) { 165 sf.lsf_sc.lsc_regs[i] = f->f_regs[i]; 166 } 167 sf.lsf_sc.lsc_mdhi = f->f_regs[_R_MULHI]; 168 sf.lsf_sc.lsc_mdlo = f->f_regs[_R_MULLO]; 169 sf.lsf_sc.lsc_pc = f->f_regs[_R_PC]; 170 sf.lsf_sc.lsc_status = f->f_regs[_R_SR]; 171 sf.lsf_sc.lsc_cause = f->f_regs[_R_CAUSE]; 172 sf.lsf_sc.lsc_badvaddr = f->f_regs[_R_BADVADDR]; 173 sendsig_reset(l, sig); 174 175 /* 176 * Save signal stack. XXX broken 177 */ 178 /* kregs.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; */ 179 180 /* 181 * Install the sigframe onto the stack 182 */ 183 fp -= sizeof(struct linux_sigframe); 184 mutex_exit(p->p_lock); 185 error = copyout(&sf, fp, sizeof(sf)); 186 mutex_enter(p->p_lock); 187 188 if (error != 0) { 189 /* 190 * Process has trashed its stack; give it an illegal 191 * instruction to halt it in its tracks. 192 */ 193 #ifdef DEBUG_LINUX 194 printf("linux_sendsig: stack trashed\n"); 195 #endif /* DEBUG_LINUX */ 196 sigexit(l, SIGILL); 197 /* NOTREACHED */ 198 } 199 200 /* Set up the registers to return to sigcode. */ 201 f->f_regs[_R_A0] = native_to_linux_signo[sig]; 202 f->f_regs[_R_A1] = 0; 203 f->f_regs[_R_A2] = (unsigned long)&fp->lsf_sc; 204 205 #ifdef DEBUG_LINUX 206 printf("sigcontext is at %p\n", &fp->lsf_sc); 207 #endif /* DEBUG_LINUX */ 208 209 f->f_regs[_R_SP] = (unsigned long)fp; 210 /* Signal trampoline code is at base of user stack. */ 211 f->f_regs[_R_RA] = (unsigned long)p->p_sigctx.ps_sigcode; 212 f->f_regs[_R_T9] = (unsigned long)catcher; 213 f->f_regs[_R_PC] = (unsigned long)catcher; 214 215 /* Remember that we're now on the signal stack. */ 216 if (onstack) 217 l->l_sigstk.ss_flags |= SS_ONSTACK; 218 219 return; 220 } 221 222 /* 223 * System call to cleanup state after a signal 224 * has been taken. Reset signal mask and 225 * stack state from context left by sendsig (above). 226 */ 227 int 228 linux_sys_sigreturn(struct lwp *l, const struct linux_sys_sigreturn_args *uap, register_t *retval) 229 { 230 /* { 231 syscallarg(struct linux_sigframe *) sf; 232 } */ 233 struct proc *p = l->l_proc; 234 struct linux_sigframe *sf, ksf; 235 struct frame *f; 236 sigset_t mask; 237 int i, error; 238 239 #ifdef DEBUG_LINUX 240 printf("linux_sys_sigreturn()\n"); 241 #endif /* DEBUG_LINUX */ 242 243 /* 244 * The trampoline code hands us the context. 245 * It is unsafe to keep track of it ourselves, in the event that a 246 * program jumps out of a signal handler. 247 */ 248 sf = SCARG(uap, sf); 249 250 if ((error = copyin(sf, &ksf, sizeof(ksf))) != 0) 251 return (error); 252 253 /* Restore the register context. */ 254 f = (struct frame *)l->l_md.md_regs; 255 for (i=0; i<32; i++) 256 f->f_regs[i] = ksf.lsf_sc.lsc_regs[i]; 257 f->f_regs[_R_MULLO] = ksf.lsf_sc.lsc_mdlo; 258 f->f_regs[_R_MULHI] = ksf.lsf_sc.lsc_mdhi; 259 f->f_regs[_R_PC] = ksf.lsf_sc.lsc_pc; 260 f->f_regs[_R_BADVADDR] = ksf.lsf_sc.lsc_badvaddr; 261 f->f_regs[_R_CAUSE] = ksf.lsf_sc.lsc_cause; 262 263 mutex_enter(p->p_lock); 264 265 /* Restore signal stack. */ 266 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 267 268 /* Restore signal mask. */ 269 linux_to_native_sigset(&mask, (linux_sigset_t *)&ksf.lsf_mask); 270 (void)sigprocmask1(l, SIG_SETMASK, &mask, 0); 271 272 mutex_exit(p->p_lock); 273 274 return (EJUSTRETURN); 275 } 276 277 278 int 279 linux_sys_rt_sigreturn(struct lwp *l, const struct linux_sys_rt_sigreturn_args *v, register_t *retval) 280 { 281 return (ENOSYS); 282 } 283 284 285 #if 0 286 int 287 linux_sys_modify_ldt(struct lwp *l, const struct linux_sys_modify_ldt_args *uap, register_t *retval) 288 { 289 /* 290 * This syscall is not implemented in Linux/Mips: we should not 291 * be here 292 */ 293 #ifdef DEBUG_LINUX 294 printf("linux_sys_modify_ldt: should not be here.\n"); 295 #endif /* DEBUG_LINUX */ 296 return 0; 297 } 298 #endif 299 300 /* 301 * major device numbers remapping 302 */ 303 dev_t 304 linux_fakedev(dev_t dev, int raw) 305 { 306 /* XXX write me */ 307 return dev; 308 } 309 310 /* 311 * We come here in a last attempt to satisfy a Linux ioctl() call 312 */ 313 int 314 linux_machdepioctl(struct lwp *l, const struct linux_sys_ioctl_args *uap, register_t *retval) 315 { 316 return 0; 317 } 318 319 /* 320 * See above. If a root process tries to set access to an I/O port, 321 * just let it have the whole range. 322 */ 323 int 324 linux_sys_ioperm(struct lwp *l, const struct linux_sys_ioperm_args *uap, register_t *retval) 325 { 326 /* 327 * This syscall is not implemented in Linux/Mips: we should not be here 328 */ 329 #ifdef DEBUG_LINUX 330 printf("linux_sys_ioperm: should not be here.\n"); 331 #endif /* DEBUG_LINUX */ 332 return 0; 333 } 334 335 /* 336 * wrapper linux_sys_new_uname() -> linux_sys_uname() 337 */ 338 int 339 linux_sys_new_uname(struct lwp *l, const struct linux_sys_new_uname_args *uap, register_t *retval) 340 { 341 /* 342 * Use this if you want to try Linux emulation with a glibc-2.2 343 * or higher. Note that signals will not work 344 */ 345 #if 0 346 struct linux_sys_uname_args /* { 347 syscallarg(struct linux_utsname *) up; 348 } */ *uap = v; 349 struct linux_utsname luts; 350 351 strlcpy(luts.l_sysname, linux_sysname, sizeof(luts.l_sysname)); 352 strlcpy(luts.l_nodename, hostname, sizeof(luts.l_nodename)); 353 strlcpy(luts.l_release, "2.4.0", sizeof(luts.l_release)); 354 strlcpy(luts.l_version, linux_version, sizeof(luts.l_version)); 355 strlcpy(luts.l_machine, machine, sizeof(luts.l_machine)); 356 strlcpy(luts.l_domainname, domainname, sizeof(luts.l_domainname)); 357 358 return copyout(&luts, SCARG(uap, up), sizeof(luts)); 359 #else 360 return linux_sys_uname(l, (const void *)uap, retval); 361 #endif 362 } 363 364 /* 365 * In Linux, cacheflush is currently implemented 366 * as a whole cache flush (arguments are ignored) 367 * we emulate this broken beahior. 368 */ 369 int 370 linux_sys_cacheflush(struct lwp *l, const struct linux_sys_cacheflush_args *uap, register_t *retval) 371 { 372 mips_icache_sync_all(); 373 mips_dcache_wbinv_all(); 374 return 0; 375 } 376 377 /* 378 * This system call is depecated in Linux, but 379 * some binaries and some libraries use it. 380 */ 381 int 382 linux_sys_sysmips(struct lwp *l, const struct linux_sys_sysmips_args *uap, register_t *retval) 383 { 384 /* { 385 syscallarg(int) cmd; 386 syscallarg(int) arg1; 387 syscallarg(int) arg2; 388 syscallarg(int) arg3; 389 } */ 390 int error; 391 392 switch (SCARG(uap, cmd)) { 393 case LINUX_SETNAME: { 394 char nodename [LINUX___NEW_UTS_LEN + 1]; 395 int name[2]; 396 size_t len; 397 398 if ((error = copyinstr((char *)SCARG(uap, arg1), nodename, 399 LINUX___NEW_UTS_LEN, &len)) != 0) 400 return error; 401 402 name[0] = CTL_KERN; 403 name[1] = KERN_HOSTNAME; 404 return (old_sysctl(&name[0], 2, 0, 0, nodename, len, NULL)); 405 406 break; 407 } 408 case LINUX_MIPS_ATOMIC_SET: { 409 void *addr; 410 int s; 411 u_int8_t value = 0; 412 413 addr = (void *)SCARG(uap, arg1); 414 415 s = splhigh(); 416 /* 417 * No error testing here. This is bad, but Linux does 418 * it like this. The source aknowledge "This is broken" 419 * in a comment... 420 */ 421 (void) copyin(addr, &value, 1); 422 *retval = value; 423 value = (u_int8_t) SCARG(uap, arg2); 424 error = copyout(&value, addr, 1); 425 splx(s); 426 427 return 0; 428 break; 429 } 430 case LINUX_MIPS_FIXADE: /* XXX not implemented */ 431 break; 432 case LINUX_FLUSH_CACHE: 433 mips_icache_sync_all(); 434 mips_dcache_wbinv_all(); 435 break; 436 case LINUX_MIPS_RDNVRAM: 437 return EIO; 438 break; 439 default: 440 return EINVAL; 441 break; 442 } 443 #ifdef DEBUG_LINUX 444 printf("linux_sys_sysmips(): unimplemented command %d\n", 445 SCARG(uap,cmd)); 446 #endif /* DEBUG_LINUX */ 447 return 0; 448 } 449 450 int 451 linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg) 452 { 453 return 0; 454 } 455 456 int 457 linux_sys_set_thread_area(struct lwp *l, const struct linux_sys_set_thread_area_args *uap, register_t *retval) 458 { 459 /* { 460 syscallarg(void *) tls; 461 } */ 462 463 return lwp_setprivate(l, SCARG(uap, tls)); 464 } 465