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