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