1 /* $NetBSD: linux_machdep.c,v 1.3 2001/10/06 13:32:18 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 <sys/sysctl.h> 64 #include <miscfs/specfs/specdev.h> 65 66 #include <compat/linux/common/linux_types.h> 67 #include <compat/linux/common/linux_signal.h> 68 #include <compat/linux/common/linux_util.h> 69 #include <compat/linux/common/linux_ioctl.h> 70 #include <compat/linux/common/linux_hdio.h> 71 #include <compat/linux/common/linux_exec.h> 72 #include <compat/linux/common/linux_machdep.h> 73 74 #include <compat/linux/linux_syscallargs.h> 75 76 #include <machine/cpu.h> 77 #include <machine/psl.h> 78 #include <machine/reg.h> 79 #include <machine/regnum.h> 80 #include <machine/vmparam.h> 81 #include <machine/locore.h> 82 83 /* 84 * To see whether wscons is configured (for virtual console ioctl calls). 85 */ 86 #if defined(_KERNEL_OPT) 87 #include "wsdisplay.h" 88 #endif 89 #if (NWSDISPLAY > 0) 90 #include <dev/wscons/wsconsio.h> 91 #include <dev/wscons/wsdisplay_usl_io.h> 92 #endif 93 94 /* 95 * Set set up registers on exec. 96 * XXX not used at the moment since in sys/kern/exec_conf, LINUX_COMPAT 97 * entry uses NetBSD's native setregs instead of linux_setregs 98 */ 99 void 100 linux_setregs(p, pack, stack) 101 struct proc *p; 102 struct exec_package *pack; 103 u_long stack; 104 { 105 setregs(p, pack, stack); 106 return; 107 } 108 109 /* 110 * Send an interrupt to process. 111 * 112 * Adapted from sys/arch/mips/mips/mips_machdep.c 113 * 114 * XXX Does not work well yet with RT signals 115 * 116 */ 117 118 void 119 linux_sendsig(catcher, sig, mask, code) /* XXX Check me */ 120 sig_t catcher; 121 int sig; 122 sigset_t *mask; 123 u_long code; 124 { 125 struct proc *p = curproc; 126 struct linux_sigframe *fp; 127 struct frame *f; 128 int i,onstack; 129 struct linux_sigframe sf; 130 131 printf("linux_sendsig()\n"); 132 f = (struct frame *)p->p_md.md_regs; 133 printf("f = %p\n", f); 134 135 /* 136 * Do we need to jump onto the signal stack? 137 */ 138 onstack = 139 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 140 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 141 142 /* 143 * Signal stack is broken (see at the end of linux_sigreturn), so we do 144 * not use it yet. XXX fix this. 145 */ 146 onstack=0; 147 148 /* 149 * Allocate space for the signal handler context. 150 */ 151 if (onstack) 152 fp = (struct linux_sigframe *) 153 ((caddr_t)p->p_sigctx.ps_sigstk.ss_sp 154 + p->p_sigctx.ps_sigstk.ss_size); 155 else 156 /* cast for _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN case */ 157 fp = (struct linux_sigframe *)(u_int32_t)f->f_regs[SP]; 158 159 printf("fp = %p, sf = %p\n", fp, &sf); 160 /* Build stack frame for signal trampoline. */ 161 memset(&sf, 0, sizeof sf); 162 sf.lsf_ass[0] = 0; /* XXX */ 163 sf.lsf_ass[1] = 0; 164 sf.lsf_code[0] = 0x24020000; /* li v0, __NR_sigreturn */ 165 sf.lsf_code[0] = 0x0000000c; /* syscall */ 166 native_to_linux_sigset(mask, &sf.lsf_mask); 167 for (i=0; i<32; i++) 168 sf.lsf_sc.lsc_regs[i] = f->f_regs[i]; 169 sf.lsf_sc.lsc_mdhi = f->f_regs[MULHI]; 170 sf.lsf_sc.lsc_mdlo = f->f_regs[MULLO]; 171 sf.lsf_sc.lsc_pc = f->f_regs[PC]; 172 sf.lsf_sc.lsc_status = 0; /* XXX */ 173 sf.lsf_sc.lsc_ownedfp = 0; /* XXX */ 174 sf.lsf_sc.lsc_fpc_csr = f->f_regs[SR]; 175 sf.lsf_sc.lsc_fpc_eir = f->f_regs[RA]; /* XXX */ 176 sf.lsf_sc.lsc_cause = f->f_regs[CAUSE]; 177 sf.lsf_sc.lsc_badvaddr = f->f_regs[BADVADDR]; /* XXX */ 178 179 180 /* 181 * Save signal stack. XXX broken 182 */ 183 /* kregs.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK; */ 184 185 /* 186 * Install the sigframe onto the stack 187 */ 188 fp -= sizeof(struct linux_sigframe); 189 if (copyout(&sf, fp, sizeof(sf)) != 0) { 190 /* 191 * Process has trashed its stack; give it an illegal 192 * instruction to halt it in its tracks. 193 */ 194 sigexit(p, SIGILL); 195 /* NOTREACHED */ 196 } 197 198 /* Set up the registers to return to sigcode. */ 199 f->f_regs[A0] = native_to_linux_sig[sig]; 200 f->f_regs[A1] = 0; 201 f->f_regs[A2] = (int)&fp->lsf_sc; 202 203 f->f_regs[SP] = (int)fp; 204 f->f_regs[RA] = (int)p->p_sigctx.ps_sigcode; 205 f->f_regs[T9] = (int)catcher; 206 f->f_regs[PC] = (int)catcher; 207 208 /* Signal trampoline code is at base of user stack. */ 209 210 /* Remember that we're now on the signal stack. */ 211 if (onstack) 212 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 213 214 return; 215 } 216 217 /* 218 * System call to cleanup state after a signal 219 * has been taken. Reset signal mask and 220 * stack state from context left by sendsig (above). 221 */ 222 int 223 linux_sys_sigreturn(p, v, retval) 224 struct proc *p; 225 void *v; 226 register_t *retval; 227 { 228 struct linux_sys_sigreturn_args /* { 229 syscallarg(struct linux_pt_regs) regs; 230 } */ *uap = v; 231 struct linux_pt_regs regs, kregs; 232 struct linux_sigframe *sf, ksf; 233 struct frame *f; 234 sigset_t mask; 235 int i, error; 236 237 printf("linux_sys_sigreturn()\n"); 238 /* 239 * The trampoline code hands us the context. 240 * It is unsafe to keep track of it ourselves, in the event that a 241 * program jumps out of a signal handler. 242 */ 243 regs = SCARG(uap, regs); 244 245 kregs = regs; 246 /* if ((error = copyin(regs, &kregs, sizeof(kregs))) != 0) 247 return (error); */ 248 249 sf = (struct linux_sigframe *)kregs.lregs[29]; 250 if ((error = copyin(sf, &ksf, sizeof(ksf))) != 0) 251 return (error); 252 253 /* Restore the register context. */ 254 f = (struct frame *)p->p_md.md_regs; 255 printf("sf = %p, f = %p\n", sf, f); 256 for (i=0; i<32; i++) 257 f->f_regs[i] = kregs.lregs[i]; 258 f->f_regs[MULLO] = kregs.llo; 259 f->f_regs[MULHI] = kregs.lhi; 260 f->f_regs[PC] = kregs.lcp0_spc; 261 f->f_regs[BADVADDR] = kregs.lcp0_badvaddr; 262 f->f_regs[CAUSE] = kregs.lcp0_cause; 263 264 /* Restore signal stack. */ 265 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 266 267 /* Restore signal mask. */ 268 linux_to_native_sigset((linux_sigset_t *)&ksf.lsf_mask, &mask); 269 (void)sigprocmask1(p, SIG_SETMASK, &mask, 0); 270 271 return (EJUSTRETURN); 272 } 273 274 275 int 276 linux_sys_rt_sigreturn(p, v, retval) 277 struct proc *p; 278 void *v; 279 register_t *retval; 280 { 281 return 0; 282 } 283 284 285 #if 0 286 int 287 linux_sys_modify_ldt(p, v, retval) 288 struct proc *p; 289 void *v; 290 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 299 return 0; 300 } 301 #endif 302 303 /* 304 * major device numbers remapping 305 */ 306 dev_t 307 linux_fakedev(dev) 308 dev_t dev; 309 { 310 /* XXX write me */ 311 return dev; 312 } 313 314 /* 315 * We come here in a last attempt to satisfy a Linux ioctl() call 316 */ 317 int 318 linux_machdepioctl(p, v, retval) 319 struct proc *p; 320 void *v; 321 register_t *retval; 322 { 323 return 0; 324 } 325 326 /* 327 * See above. If a root process tries to set access to an I/O port, 328 * just let it have the whole range. 329 */ 330 int 331 linux_sys_ioperm(p, v, retval) 332 struct proc *p; 333 void *v; 334 register_t *retval; 335 { 336 /* 337 * This syscall is not implemented in Linux/Mips: we should not be here 338 */ 339 #ifdef DEBUG_LINUX 340 printf("linux_sys_ioperm: should not be here.\n"); 341 #endif 342 return 0; 343 } 344 345 /* 346 * wrapper linux_sys_new_uname() -> linux_sys_uname() 347 */ 348 int 349 linux_sys_new_uname(p, v, retval) 350 struct proc *p; 351 void *v; 352 register_t *retval; 353 { 354 return linux_sys_uname(p, v, retval); 355 } 356 357 /* 358 * In Linux, cacheflush is icurrently implemented 359 * as a whole cache flush (arguments are ignored) 360 * we emulate this broken beahior. 361 */ 362 int 363 linux_sys_cacheflush(p, v, retval) 364 struct proc *p; 365 void *v; 366 register_t *retval; 367 { 368 MachFlushCache(); 369 return 0; 370 } 371 372 /* 373 * This system call is depecated in Linux, but 374 * some binaries and some libraries use it. 375 */ 376 int 377 linux_sys_sysmips(p, v, retval) 378 struct proc *p; 379 void *v; 380 register_t *retval; 381 { 382 struct linux_sys_sysmips_args { 383 syscallarg(int) cmd; 384 syscallarg(int) arg1; 385 syscallarg(int) arg2; 386 syscallarg(int) arg3; 387 } *uap = v; 388 int error; 389 390 switch (SCARG(uap, cmd)) { 391 case LINUX_SETNAME: { 392 char nodename [LINUX___NEW_UTS_LEN + 1]; 393 int name; 394 size_t len; 395 396 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 397 return error; 398 if ((error = copyinstr((char *)SCARG(uap, arg1), nodename, 399 LINUX___NEW_UTS_LEN, &len)) != 0) 400 return error; 401 402 name = KERN_HOSTNAME; 403 return (kern_sysctl(&name, 1, 0, 0, nodename, len, p)); 404 405 break; 406 } 407 case LINUX_MIPS_ATOMIC_SET: { 408 void *addr; 409 int s; 410 411 addr = (void *)SCARG(uap, arg1); 412 413 if ((uvm_useracc((caddr_t)addr, sizeof(int), 414 B_READ | B_WRITE)) != 1) 415 return EFAULT; 416 417 s = splhigh(); 418 /* 419 * No error testing here. This is bad, but Linux does 420 * it like this. The source aknowledge "This is broken" 421 * in a comment... 422 */ 423 *retval = (register_t)fubyte(addr); 424 error = subyte(addr, SCARG(uap, arg2)); 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 MachFlushCache(); 434 break; 435 case LINUX_MIPS_RDNVRAM: 436 return EIO; 437 break; 438 default: 439 return EINVAL; 440 break; 441 } 442 #ifdef DEBUG_LINUX 443 printf("linux_sys_sysmips(): unimplemented command %d\n", 444 SCARG(uap,cmd)); 445 #endif /* DEBUG_LINUX */ 446 return 0; 447 } 448