1 /* $NetBSD: linux_machdep.c,v 1.67 2001/08/02 22:04:57 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 2000 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. 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 #if defined(_KERNEL_OPT) 40 #include "opt_vm86.h" 41 #include "opt_user_ldt.h" 42 #endif 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 #include <sys/disklabel.h> 67 #include <sys/ioctl.h> 68 #include <miscfs/specfs/specdev.h> 69 70 #include <compat/linux/common/linux_types.h> 71 #include <compat/linux/common/linux_signal.h> 72 #include <compat/linux/common/linux_util.h> 73 #include <compat/linux/common/linux_ioctl.h> 74 #include <compat/linux/common/linux_hdio.h> 75 #include <compat/linux/common/linux_exec.h> 76 #include <compat/linux/common/linux_machdep.h> 77 78 #include <compat/linux/linux_syscallargs.h> 79 80 #include <machine/cpu.h> 81 #include <machine/cpufunc.h> 82 #include <machine/psl.h> 83 #include <machine/reg.h> 84 #include <machine/segments.h> 85 #include <machine/specialreg.h> 86 #include <machine/sysarch.h> 87 #include <machine/vm86.h> 88 #include <machine/vmparam.h> 89 90 /* 91 * To see whether wscons is configured (for virtual console ioctl calls). 92 */ 93 #if defined(_KERNEL_OPT) 94 #include "wsdisplay.h" 95 #endif 96 #if (NWSDISPLAY > 0) 97 #include <dev/wscons/wsconsio.h> 98 #include <dev/wscons/wsdisplay_usl_io.h> 99 #if defined(_KERNEL_OPT) 100 #include "opt_xserver.h" 101 #endif 102 #endif 103 104 #ifdef USER_LDT 105 #include <machine/cpu.h> 106 int linux_read_ldt __P((struct proc *, struct linux_sys_modify_ldt_args *, 107 register_t *)); 108 int linux_write_ldt __P((struct proc *, struct linux_sys_modify_ldt_args *, 109 register_t *)); 110 #endif 111 112 static struct biosdisk_info *fd2biosinfo __P((struct proc *, struct file *)); 113 extern struct disklist *i386_alldisks; 114 extern const char *findblkname __P((int)); 115 116 /* 117 * Deal with some i386-specific things in the Linux emulation code. 118 */ 119 120 void 121 linux_setregs(p, epp, stack) 122 struct proc *p; 123 struct exec_package *epp; 124 u_long stack; 125 { 126 struct pcb *pcb = &p->p_addr->u_pcb; 127 128 setregs(p, epp, stack); 129 if (i386_use_fxsave) 130 pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __Linux_NPXCW__; 131 else 132 pcb->pcb_savefpu.sv_87.sv_env.en_cw = __Linux_NPXCW__; 133 } 134 135 /* 136 * Send an interrupt to process. 137 * 138 * Stack is set up to allow sigcode stored 139 * in u. to call routine, followed by kcall 140 * to sigreturn routine below. After sigreturn 141 * resets the signal mask, the stack, and the 142 * frame pointer, it returns to the user 143 * specified pc, psl. 144 */ 145 146 void 147 linux_sendsig(catcher, sig, mask, code) 148 sig_t catcher; 149 int sig; 150 sigset_t *mask; 151 u_long code; 152 { 153 struct proc *p = curproc; 154 struct trapframe *tf; 155 struct linux_sigframe *fp, frame; 156 int onstack; 157 158 tf = p->p_md.md_regs; 159 160 /* Do we need to jump onto the signal stack? */ 161 onstack = 162 (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 163 (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0; 164 165 /* Allocate space for the signal handler context. */ 166 if (onstack) 167 fp = (struct linux_sigframe *)((caddr_t)p->p_sigctx.ps_sigstk.ss_sp + 168 p->p_sigctx.ps_sigstk.ss_size); 169 else 170 fp = (struct linux_sigframe *)tf->tf_esp; 171 fp--; 172 173 /* Build stack frame for signal trampoline. */ 174 frame.sf_handler = catcher; 175 frame.sf_sig = native_to_linux_sig[sig]; 176 177 /* Save register context. */ 178 #ifdef VM86 179 if (tf->tf_eflags & PSL_VM) { 180 frame.sf_sc.sc_gs = tf->tf_vm86_gs; 181 frame.sf_sc.sc_fs = tf->tf_vm86_fs; 182 frame.sf_sc.sc_es = tf->tf_vm86_es; 183 frame.sf_sc.sc_ds = tf->tf_vm86_ds; 184 frame.sf_sc.sc_eflags = get_vflags(p); 185 } else 186 #endif 187 { 188 frame.sf_sc.sc_gs = tf->tf_gs; 189 frame.sf_sc.sc_fs = tf->tf_fs; 190 frame.sf_sc.sc_es = tf->tf_es; 191 frame.sf_sc.sc_ds = tf->tf_ds; 192 frame.sf_sc.sc_eflags = tf->tf_eflags; 193 } 194 frame.sf_sc.sc_edi = tf->tf_edi; 195 frame.sf_sc.sc_esi = tf->tf_esi; 196 frame.sf_sc.sc_ebp = tf->tf_ebp; 197 frame.sf_sc.sc_ebx = tf->tf_ebx; 198 frame.sf_sc.sc_edx = tf->tf_edx; 199 frame.sf_sc.sc_ecx = tf->tf_ecx; 200 frame.sf_sc.sc_eax = tf->tf_eax; 201 frame.sf_sc.sc_eip = tf->tf_eip; 202 frame.sf_sc.sc_cs = tf->tf_cs; 203 frame.sf_sc.sc_esp_at_signal = tf->tf_esp; 204 frame.sf_sc.sc_ss = tf->tf_ss; 205 frame.sf_sc.sc_err = tf->tf_err; 206 frame.sf_sc.sc_trapno = tf->tf_trapno; 207 208 /* Save signal stack. */ 209 /* Linux doesn't save the onstack flag in sigframe */ 210 211 /* Save signal mask. */ 212 native_to_linux_old_sigset(mask, &frame.sf_sc.sc_mask); 213 214 if (copyout(&frame, fp, sizeof(frame)) != 0) { 215 /* 216 * Process has trashed its stack; give it an illegal 217 * instruction to halt it in its tracks. 218 */ 219 sigexit(p, SIGILL); 220 /* NOTREACHED */ 221 } 222 223 /* 224 * Build context to run handler in. 225 */ 226 tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); 227 tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); 228 tf->tf_eip = (int)p->p_sigctx.ps_sigcode; 229 tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL); 230 tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC); 231 tf->tf_esp = (int)fp; 232 tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); 233 234 /* Remember that we're now on the signal stack. */ 235 if (onstack) 236 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 237 } 238 239 /* 240 * System call to cleanup state after a signal 241 * has been taken. Reset signal mask and 242 * stack state from context left by sendsig (above). 243 * Return to previous pc and psl as specified by 244 * context left by sendsig. Check carefully to 245 * make sure that the user has not modified the 246 * psl to gain improper privileges or to cause 247 * a machine fault. 248 */ 249 int 250 linux_sys_rt_sigreturn(p, v, retval) 251 struct proc *p; 252 void *v; 253 register_t *retval; 254 { 255 /* XXX XAX write me */ 256 return(ENOSYS); 257 } 258 259 int 260 linux_sys_sigreturn(p, v, retval) 261 struct proc *p; 262 void *v; 263 register_t *retval; 264 { 265 struct linux_sys_sigreturn_args /* { 266 syscallarg(struct linux_sigcontext *) scp; 267 } */ *uap = v; 268 struct linux_sigcontext *scp, context; 269 struct trapframe *tf; 270 sigset_t mask; 271 ssize_t ss_gap; 272 273 /* 274 * The trampoline code hands us the context. 275 * It is unsafe to keep track of it ourselves, in the event that a 276 * program jumps out of a signal handler. 277 */ 278 scp = SCARG(uap, scp); 279 if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0) 280 return (EFAULT); 281 282 /* Restore register context. */ 283 tf = p->p_md.md_regs; 284 #ifdef VM86 285 if (context.sc_eflags & PSL_VM) { 286 tf->tf_vm86_gs = context.sc_gs; 287 tf->tf_vm86_fs = context.sc_fs; 288 tf->tf_vm86_es = context.sc_es; 289 tf->tf_vm86_ds = context.sc_ds; 290 set_vflags(p, context.sc_eflags); 291 } else 292 #endif 293 { 294 /* 295 * Check for security violations. If we're returning to 296 * protected mode, the CPU will validate the segment registers 297 * automatically and generate a trap on violations. We handle 298 * the trap, rather than doing all of the checking here. 299 */ 300 if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || 301 !USERMODE(context.sc_cs, context.sc_eflags)) 302 return (EINVAL); 303 304 /* %fs and %gs were restored by the trampoline. */ 305 tf->tf_es = context.sc_es; 306 tf->tf_ds = context.sc_ds; 307 tf->tf_eflags = context.sc_eflags; 308 } 309 tf->tf_edi = context.sc_edi; 310 tf->tf_esi = context.sc_esi; 311 tf->tf_ebp = context.sc_ebp; 312 tf->tf_ebx = context.sc_ebx; 313 tf->tf_edx = context.sc_edx; 314 tf->tf_ecx = context.sc_ecx; 315 tf->tf_eax = context.sc_eax; 316 tf->tf_eip = context.sc_eip; 317 tf->tf_cs = context.sc_cs; 318 tf->tf_esp = context.sc_esp_at_signal; 319 tf->tf_ss = context.sc_ss; 320 321 /* Restore signal stack. */ 322 /* 323 * Linux really does it this way; it doesn't have space in sigframe 324 * to save the onstack flag. 325 */ 326 ss_gap = (ssize_t) 327 ((caddr_t) context.sc_esp_at_signal - (caddr_t) p->p_sigctx.ps_sigstk.ss_sp); 328 if (ss_gap >= 0 && ss_gap < p->p_sigctx.ps_sigstk.ss_size) 329 p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK; 330 else 331 p->p_sigctx.ps_sigstk.ss_flags &= ~SS_ONSTACK; 332 333 /* Restore signal mask. */ 334 linux_old_to_native_sigset(&context.sc_mask, &mask); 335 (void) sigprocmask1(p, SIG_SETMASK, &mask, 0); 336 337 return (EJUSTRETURN); 338 } 339 340 #ifdef USER_LDT 341 342 int 343 linux_read_ldt(p, uap, retval) 344 struct proc *p; 345 struct linux_sys_modify_ldt_args /* { 346 syscallarg(int) func; 347 syscallarg(void *) ptr; 348 syscallarg(size_t) bytecount; 349 } */ *uap; 350 register_t *retval; 351 { 352 struct i386_get_ldt_args gl; 353 int error; 354 caddr_t sg; 355 char *parms; 356 357 sg = stackgap_init(p->p_emul); 358 359 gl.start = 0; 360 gl.desc = SCARG(uap, ptr); 361 gl.num = SCARG(uap, bytecount) / sizeof(union descriptor); 362 363 parms = stackgap_alloc(&sg, sizeof(gl)); 364 365 if ((error = copyout(&gl, parms, sizeof(gl))) != 0) 366 return (error); 367 368 if ((error = i386_get_ldt(p, parms, retval)) != 0) 369 return (error); 370 371 *retval *= sizeof(union descriptor); 372 return (0); 373 } 374 375 struct linux_ldt_info { 376 u_int entry_number; 377 u_long base_addr; 378 u_int limit; 379 u_int seg_32bit:1; 380 u_int contents:2; 381 u_int read_exec_only:1; 382 u_int limit_in_pages:1; 383 u_int seg_not_present:1; 384 }; 385 386 int 387 linux_write_ldt(p, uap, retval) 388 struct proc *p; 389 struct linux_sys_modify_ldt_args /* { 390 syscallarg(int) func; 391 syscallarg(void *) ptr; 392 syscallarg(size_t) bytecount; 393 } */ *uap; 394 register_t *retval; 395 { 396 struct linux_ldt_info ldt_info; 397 struct segment_descriptor sd; 398 struct i386_set_ldt_args sl; 399 int error; 400 caddr_t sg; 401 char *parms; 402 403 if (SCARG(uap, bytecount) != sizeof(ldt_info)) 404 return (EINVAL); 405 if ((error = copyin(SCARG(uap, ptr), &ldt_info, sizeof(ldt_info))) != 0) 406 return error; 407 if (ldt_info.contents == 3) 408 return (EINVAL); 409 410 sg = stackgap_init(p->p_emul); 411 412 sd.sd_lobase = ldt_info.base_addr & 0xffffff; 413 sd.sd_hibase = (ldt_info.base_addr >> 24) & 0xff; 414 sd.sd_lolimit = ldt_info.limit & 0xffff; 415 sd.sd_hilimit = (ldt_info.limit >> 16) & 0xf; 416 sd.sd_type = 417 16 | (ldt_info.contents << 2) | (!ldt_info.read_exec_only << 1); 418 sd.sd_dpl = SEL_UPL; 419 sd.sd_p = !ldt_info.seg_not_present; 420 sd.sd_def32 = ldt_info.seg_32bit; 421 sd.sd_gran = ldt_info.limit_in_pages; 422 423 sl.start = ldt_info.entry_number; 424 sl.desc = stackgap_alloc(&sg, sizeof(sd)); 425 sl.num = 1; 426 427 #if 0 428 printf("linux_write_ldt: idx=%d, base=%x, limit=%x\n", 429 ldt_info.entry_number, ldt_info.base_addr, ldt_info.limit); 430 #endif 431 432 parms = stackgap_alloc(&sg, sizeof(sl)); 433 434 if ((error = copyout(&sd, sl.desc, sizeof(sd))) != 0) 435 return (error); 436 if ((error = copyout(&sl, parms, sizeof(sl))) != 0) 437 return (error); 438 439 if ((error = i386_set_ldt(p, parms, retval)) != 0) 440 return (error); 441 442 *retval = 0; 443 return (0); 444 } 445 446 #endif /* USER_LDT */ 447 448 int 449 linux_sys_modify_ldt(p, v, retval) 450 struct proc *p; 451 void *v; 452 register_t *retval; 453 { 454 struct linux_sys_modify_ldt_args /* { 455 syscallarg(int) func; 456 syscallarg(void *) ptr; 457 syscallarg(size_t) bytecount; 458 } */ *uap = v; 459 460 switch (SCARG(uap, func)) { 461 #ifdef USER_LDT 462 case 0: 463 return (linux_read_ldt(p, uap, retval)); 464 465 case 1: 466 return (linux_write_ldt(p, uap, retval)); 467 #endif /* USER_LDT */ 468 469 default: 470 return (ENOSYS); 471 } 472 } 473 474 /* 475 * XXX Pathetic hack to make svgalib work. This will fake the major 476 * device number of an opened VT so that svgalib likes it. grmbl. 477 * Should probably do it 'wrong the right way' and use a mapping 478 * array for all major device numbers, and map linux_mknod too. 479 */ 480 dev_t 481 linux_fakedev(dev) 482 dev_t dev; 483 { 484 #if (NWSDISPLAY > 0) 485 if (major(dev) == NETBSD_WSCONS_MAJOR) 486 return makedev(LINUX_CONS_MAJOR, (minor(dev) + 1)); 487 #endif 488 return dev; 489 } 490 491 #if (NWSDISPLAY > 0) 492 /* 493 * That's not complete, but enough to get an X server running. 494 */ 495 #define NR_KEYS 128 496 static const u_short plain_map[NR_KEYS] = { 497 0x0200, 0x001b, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 498 0x0037, 0x0038, 0x0039, 0x0030, 0x002d, 0x003d, 0x007f, 0x0009, 499 0x0b71, 0x0b77, 0x0b65, 0x0b72, 0x0b74, 0x0b79, 0x0b75, 0x0b69, 500 0x0b6f, 0x0b70, 0x005b, 0x005d, 0x0201, 0x0702, 0x0b61, 0x0b73, 501 0x0b64, 0x0b66, 0x0b67, 0x0b68, 0x0b6a, 0x0b6b, 0x0b6c, 0x003b, 502 0x0027, 0x0060, 0x0700, 0x005c, 0x0b7a, 0x0b78, 0x0b63, 0x0b76, 503 0x0b62, 0x0b6e, 0x0b6d, 0x002c, 0x002e, 0x002f, 0x0700, 0x030c, 504 0x0703, 0x0020, 0x0207, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 505 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x0208, 0x0209, 0x0307, 506 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, 507 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x003c, 0x010a, 508 0x010b, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 509 0x030e, 0x0702, 0x030d, 0x001c, 0x0701, 0x0205, 0x0114, 0x0603, 510 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, 511 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, 512 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 513 }, shift_map[NR_KEYS] = { 514 0x0200, 0x001b, 0x0021, 0x0040, 0x0023, 0x0024, 0x0025, 0x005e, 515 0x0026, 0x002a, 0x0028, 0x0029, 0x005f, 0x002b, 0x007f, 0x0009, 516 0x0b51, 0x0b57, 0x0b45, 0x0b52, 0x0b54, 0x0b59, 0x0b55, 0x0b49, 517 0x0b4f, 0x0b50, 0x007b, 0x007d, 0x0201, 0x0702, 0x0b41, 0x0b53, 518 0x0b44, 0x0b46, 0x0b47, 0x0b48, 0x0b4a, 0x0b4b, 0x0b4c, 0x003a, 519 0x0022, 0x007e, 0x0700, 0x007c, 0x0b5a, 0x0b58, 0x0b43, 0x0b56, 520 0x0b42, 0x0b4e, 0x0b4d, 0x003c, 0x003e, 0x003f, 0x0700, 0x030c, 521 0x0703, 0x0020, 0x0207, 0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 522 0x010f, 0x0110, 0x0111, 0x0112, 0x0113, 0x0213, 0x0203, 0x0307, 523 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, 524 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x003e, 0x010a, 525 0x010b, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 526 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, 527 0x020b, 0x0601, 0x0602, 0x0117, 0x0600, 0x020a, 0x0115, 0x0116, 528 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, 529 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 530 }, altgr_map[NR_KEYS] = { 531 0x0200, 0x0200, 0x0200, 0x0040, 0x0200, 0x0024, 0x0200, 0x0200, 532 0x007b, 0x005b, 0x005d, 0x007d, 0x005c, 0x0200, 0x0200, 0x0200, 533 0x0b71, 0x0b77, 0x0918, 0x0b72, 0x0b74, 0x0b79, 0x0b75, 0x0b69, 534 0x0b6f, 0x0b70, 0x0200, 0x007e, 0x0201, 0x0702, 0x0914, 0x0b73, 535 0x0917, 0x0919, 0x0b67, 0x0b68, 0x0b6a, 0x0b6b, 0x0b6c, 0x0200, 536 0x0200, 0x0200, 0x0700, 0x0200, 0x0b7a, 0x0b78, 0x0916, 0x0b76, 537 0x0915, 0x0b6e, 0x0b6d, 0x0200, 0x0200, 0x0200, 0x0700, 0x030c, 538 0x0703, 0x0200, 0x0207, 0x050c, 0x050d, 0x050e, 0x050f, 0x0510, 539 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0208, 0x0202, 0x0911, 540 0x0912, 0x0913, 0x030b, 0x090e, 0x090f, 0x0910, 0x030a, 0x090b, 541 0x090c, 0x090d, 0x090a, 0x0310, 0x0206, 0x0200, 0x007c, 0x0516, 542 0x0517, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 543 0x030e, 0x0702, 0x030d, 0x0200, 0x0701, 0x0205, 0x0114, 0x0603, 544 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, 545 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, 546 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 547 }, ctrl_map[NR_KEYS] = { 548 0x0200, 0x0200, 0x0200, 0x0000, 0x001b, 0x001c, 0x001d, 0x001e, 549 0x001f, 0x007f, 0x0200, 0x0200, 0x001f, 0x0200, 0x0008, 0x0200, 550 0x0011, 0x0017, 0x0005, 0x0012, 0x0014, 0x0019, 0x0015, 0x0009, 551 0x000f, 0x0010, 0x001b, 0x001d, 0x0201, 0x0702, 0x0001, 0x0013, 552 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c, 0x0200, 553 0x0007, 0x0000, 0x0700, 0x001c, 0x001a, 0x0018, 0x0003, 0x0016, 554 0x0002, 0x000e, 0x000d, 0x0200, 0x020e, 0x007f, 0x0700, 0x030c, 555 0x0703, 0x0000, 0x0207, 0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 556 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x0208, 0x0204, 0x0307, 557 0x0308, 0x0309, 0x030b, 0x0304, 0x0305, 0x0306, 0x030a, 0x0301, 558 0x0302, 0x0303, 0x0300, 0x0310, 0x0206, 0x0200, 0x0200, 0x010a, 559 0x010b, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 560 0x030e, 0x0702, 0x030d, 0x001c, 0x0701, 0x0205, 0x0114, 0x0603, 561 0x0118, 0x0601, 0x0602, 0x0117, 0x0600, 0x0119, 0x0115, 0x0116, 562 0x011a, 0x010c, 0x010d, 0x011b, 0x011c, 0x0110, 0x0311, 0x011d, 563 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 0x0200, 564 }; 565 566 const u_short * const linux_keytabs[] = { 567 plain_map, shift_map, altgr_map, altgr_map, ctrl_map 568 }; 569 #endif 570 571 static struct biosdisk_info * 572 fd2biosinfo(p, fp) 573 struct proc *p; 574 struct file *fp; 575 { 576 struct vnode *vp; 577 const char *blkname; 578 char diskname[16]; 579 int i; 580 struct nativedisk_info *nip; 581 struct disklist *dl = i386_alldisks; 582 583 if (fp->f_type != DTYPE_VNODE) 584 return NULL; 585 vp = (struct vnode *)fp->f_data; 586 587 if (vp->v_type != VBLK) 588 return NULL; 589 590 blkname = findblkname(major(vp->v_rdev)); 591 snprintf(diskname, sizeof diskname, "%s%u", blkname, 592 DISKUNIT(vp->v_rdev)); 593 594 for (i = 0; i < dl->dl_nnativedisks; i++) { 595 nip = &dl->dl_nativedisks[i]; 596 if (strcmp(diskname, nip->ni_devname)) 597 continue; 598 if (nip->ni_nmatches != 0) 599 return &dl->dl_biosdisks[nip->ni_biosmatches[0]]; 600 } 601 602 return NULL; 603 } 604 605 606 /* 607 * We come here in a last attempt to satisfy a Linux ioctl() call 608 */ 609 int 610 linux_machdepioctl(p, v, retval) 611 struct proc *p; 612 void *v; 613 register_t *retval; 614 { 615 struct linux_sys_ioctl_args /* { 616 syscallarg(int) fd; 617 syscallarg(u_long) com; 618 syscallarg(caddr_t) data; 619 } */ *uap = v; 620 struct sys_ioctl_args bia; 621 u_long com; 622 int error, error1; 623 #if (NWSDISPLAY > 0) 624 struct vt_mode lvt; 625 caddr_t bvtp, sg; 626 struct kbentry kbe; 627 #endif 628 struct linux_hd_geometry hdg; 629 struct linux_hd_big_geometry hdg_big; 630 struct biosdisk_info *bip; 631 struct filedesc *fdp; 632 struct file *fp; 633 int fd; 634 struct disklabel label, *labp; 635 struct partinfo partp; 636 int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *)); 637 u_long start, biostotal, realtotal; 638 u_char heads, sectors; 639 u_int cylinders; 640 struct ioctl_pt pt; 641 642 fd = SCARG(uap, fd); 643 SCARG(&bia, fd) = fd; 644 SCARG(&bia, data) = SCARG(uap, data); 645 com = SCARG(uap, com); 646 647 fdp = p->p_fd; 648 649 if ((fp = fd_getfile(fdp, fd)) == NULL) 650 return (EBADF); 651 652 switch (com) { 653 #if (NWSDISPLAY > 0) 654 case LINUX_KDGKBMODE: 655 com = KDGKBMODE; 656 break; 657 case LINUX_KDSKBMODE: 658 com = KDSKBMODE; 659 if ((unsigned)SCARG(uap, data) == LINUX_K_MEDIUMRAW) 660 SCARG(&bia, data) = (caddr_t)K_RAW; 661 break; 662 case LINUX_KIOCSOUND: 663 SCARG(&bia, data) = 664 (caddr_t)(((unsigned long)SCARG(&bia, data)) & 0xffff); 665 /* fall through */ 666 case LINUX_KDMKTONE: 667 com = KDMKTONE; 668 break; 669 case LINUX_KDSETMODE: 670 com = KDSETMODE; 671 break; 672 case LINUX_KDGETMODE: 673 /* KD_* values are equal to the wscons numbers */ 674 com = WSDISPLAYIO_GMODE; 675 break; 676 case LINUX_KDENABIO: 677 com = KDENABIO; 678 break; 679 case LINUX_KDDISABIO: 680 com = KDDISABIO; 681 break; 682 case LINUX_KDGETLED: 683 com = KDGETLED; 684 break; 685 case LINUX_KDSETLED: 686 com = KDSETLED; 687 break; 688 case LINUX_VT_OPENQRY: 689 com = VT_OPENQRY; 690 break; 691 case LINUX_VT_GETMODE: 692 SCARG(&bia, com) = VT_GETMODE; 693 if ((error = sys_ioctl(p, &bia, retval))) 694 return error; 695 if ((error = copyin(SCARG(uap, data), (caddr_t)&lvt, 696 sizeof (struct vt_mode)))) 697 return error; 698 lvt.relsig = native_to_linux_sig[lvt.relsig]; 699 lvt.acqsig = native_to_linux_sig[lvt.acqsig]; 700 lvt.frsig = native_to_linux_sig[lvt.frsig]; 701 return copyout((caddr_t)&lvt, SCARG(uap, data), 702 sizeof (struct vt_mode)); 703 case LINUX_VT_SETMODE: 704 com = VT_SETMODE; 705 if ((error = copyin(SCARG(uap, data), (caddr_t)&lvt, 706 sizeof (struct vt_mode)))) 707 return error; 708 lvt.relsig = linux_to_native_sig[lvt.relsig]; 709 lvt.acqsig = linux_to_native_sig[lvt.acqsig]; 710 lvt.frsig = linux_to_native_sig[lvt.frsig]; 711 sg = stackgap_init(p->p_emul); 712 bvtp = stackgap_alloc(&sg, sizeof (struct vt_mode)); 713 if ((error = copyout(&lvt, bvtp, sizeof (struct vt_mode)))) 714 return error; 715 SCARG(&bia, data) = bvtp; 716 break; 717 case LINUX_VT_DISALLOCATE: 718 /* XXX should use WSDISPLAYIO_DELSCREEN */ 719 return 0; 720 case LINUX_VT_RELDISP: 721 com = VT_RELDISP; 722 break; 723 case LINUX_VT_ACTIVATE: 724 com = VT_ACTIVATE; 725 break; 726 case LINUX_VT_WAITACTIVE: 727 com = VT_WAITACTIVE; 728 break; 729 case LINUX_VT_GETSTATE: 730 com = VT_GETSTATE; 731 break; 732 case LINUX_KDGKBTYPE: 733 /* This is what Linux does. */ 734 return (subyte(SCARG(uap, data), KB_101)); 735 case LINUX_KDGKBENT: 736 /* 737 * The Linux KDGKBENT ioctl is different from the 738 * SYSV original. So we handle it in machdep code. 739 * XXX We should use keyboard mapping information 740 * from wsdisplay, but this would be expensive. 741 */ 742 if ((error = copyin(SCARG(uap, data), &kbe, 743 sizeof(struct kbentry)))) 744 return (error); 745 if (kbe.kb_table >= sizeof(linux_keytabs) / sizeof(u_short *) 746 || kbe.kb_index >= NR_KEYS) 747 return (EINVAL); 748 kbe.kb_value = linux_keytabs[kbe.kb_table][kbe.kb_index]; 749 return (copyout(&kbe, SCARG(uap, data), 750 sizeof(struct kbentry))); 751 #endif 752 case LINUX_HDIO_GETGEO: 753 case LINUX_HDIO_GETGEO_BIG: 754 /* 755 * Try to mimic Linux behaviour: return the BIOS geometry 756 * if possible (extending its # of cylinders if it's beyond 757 * the 1023 limit), fall back to the MI geometry (i.e. 758 * the real geometry) if not found, by returning an 759 * error. See common/linux_hdio.c 760 */ 761 FILE_USE(fp); 762 bip = fd2biosinfo(p, fp); 763 ioctlf = fp->f_ops->fo_ioctl; 764 error = ioctlf(fp, DIOCGDEFLABEL, (caddr_t)&label, p); 765 error1 = ioctlf(fp, DIOCGPART, (caddr_t)&partp, p); 766 FILE_UNUSE(fp, p); 767 if (error != 0 && error1 != 0) 768 return error1; 769 labp = error != 0 ? &label : partp.disklab; 770 start = error1 != 0 ? partp.part->p_offset : 0; 771 if (bip != NULL && bip->bi_head != 0 && bip->bi_sec != 0 772 && bip->bi_cyl != 0) { 773 heads = bip->bi_head; 774 sectors = bip->bi_sec; 775 cylinders = bip->bi_cyl; 776 biostotal = heads * sectors * cylinders; 777 realtotal = labp->d_ntracks * labp->d_nsectors * 778 labp->d_ncylinders; 779 if (realtotal > biostotal) 780 cylinders = realtotal / (heads * sectors); 781 } else { 782 heads = labp->d_ntracks; 783 cylinders = labp->d_ncylinders; 784 sectors = labp->d_nsectors; 785 } 786 if (com == LINUX_HDIO_GETGEO) { 787 hdg.start = start; 788 hdg.heads = heads; 789 hdg.cylinders = cylinders; 790 hdg.sectors = sectors; 791 return copyout(&hdg, SCARG(uap, data), sizeof hdg); 792 } else { 793 hdg_big.start = start; 794 hdg_big.heads = heads; 795 hdg_big.cylinders = cylinders; 796 hdg_big.sectors = sectors; 797 return copyout(&hdg_big, SCARG(uap, data), 798 sizeof hdg_big); 799 } 800 return 0; 801 802 default: 803 /* 804 * Unknown to us. If it's on a device, just pass it through 805 * using PTIOCLINUX, the device itself might be able to 806 * make some sense of it. 807 * XXX hack: if the function returns EJUSTRETURN, 808 * it has stuffed a sysctl return value in pt.data. 809 */ 810 FILE_USE(fp); 811 ioctlf = fp->f_ops->fo_ioctl; 812 pt.com = SCARG(uap, com); 813 pt.data = SCARG(uap, data); 814 error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p); 815 FILE_UNUSE(fp, p); 816 if (error == EJUSTRETURN) { 817 retval[0] = (register_t)pt.data; 818 error = 0; 819 } 820 821 if (error == ENOTTY) 822 printf("linux_machdepioctl: invalid ioctl %08lx\n", 823 com); 824 return error; 825 } 826 SCARG(&bia, com) = com; 827 return sys_ioctl(p, &bia, retval); 828 } 829 830 /* 831 * Set I/O permissions for a process. Just set the maximum level 832 * right away (ignoring the argument), otherwise we would have 833 * to rely on I/O permission maps, which are not implemented. 834 */ 835 int 836 linux_sys_iopl(p, v, retval) 837 struct proc *p; 838 void *v; 839 register_t *retval; 840 { 841 #if 0 842 struct linux_sys_iopl_args /* { 843 syscallarg(int) level; 844 } */ *uap = v; 845 #endif 846 struct trapframe *fp = p->p_md.md_regs; 847 848 if (suser(p->p_ucred, &p->p_acflag) != 0) 849 return EPERM; 850 fp->tf_eflags |= PSL_IOPL; 851 *retval = 0; 852 return 0; 853 } 854 855 /* 856 * See above. If a root process tries to set access to an I/O port, 857 * just let it have the whole range. 858 */ 859 int 860 linux_sys_ioperm(p, v, retval) 861 struct proc *p; 862 void *v; 863 register_t *retval; 864 { 865 struct linux_sys_ioperm_args /* { 866 syscallarg(unsigned int) lo; 867 syscallarg(unsigned int) hi; 868 syscallarg(int) val; 869 } */ *uap = v; 870 struct trapframe *fp = p->p_md.md_regs; 871 872 if (suser(p->p_ucred, &p->p_acflag) != 0) 873 return EPERM; 874 if (SCARG(uap, val)) 875 fp->tf_eflags |= PSL_IOPL; 876 *retval = 0; 877 return 0; 878 } 879