Home | History | Annotate | Line # | Download | only in i386
linux_machdep.c revision 1.49
      1 /*	$NetBSD: linux_machdep.c,v 1.49 2000/05/15 01:12:07 jhawk 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 	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 	struct proc *p = curproc;
    144 	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_old_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 	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_old_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)
    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)
    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 	case LINUX_KDGKBTYPE:
    647 		/* This is what Linux does. */
    648 		return (subyte(SCARG(uap, data), KB_101));
    649 	case LINUX_KDGKBENT:
    650 		/*
    651 		 * The Linux KDGKBENT ioctl is different from the
    652 		 * SYSV original. So we handle it in machdep code.
    653 		 * XXX We should use keyboard mapping information
    654 		 * from wsdisplay, but this would be expensive.
    655 		 */
    656 		if ((error = copyin(SCARG(uap, data), &kbe,
    657 				    sizeof(struct kbentry))))
    658 			return (error);
    659 		if (kbe.kb_table >= sizeof(linux_keytabs) / sizeof(u_short *)
    660 		    || kbe.kb_index >= NR_KEYS)
    661 			return (EINVAL);
    662 		kbe.kb_value = linux_keytabs[kbe.kb_table][kbe.kb_index];
    663 		return (copyout(&kbe, SCARG(uap, data),
    664 				sizeof(struct kbentry)));
    665 #endif
    666 	default:
    667 		printf("linux_machdepioctl: invalid ioctl %08lx\n", com);
    668 		return EINVAL;
    669 	}
    670 	SCARG(&bia, com) = com;
    671 	return sys_ioctl(p, &bia, retval);
    672 }
    673 
    674 /*
    675  * Set I/O permissions for a process. Just set the maximum level
    676  * right away (ignoring the argument), otherwise we would have
    677  * to rely on I/O permission maps, which are not implemented.
    678  */
    679 int
    680 linux_sys_iopl(p, v, retval)
    681 	struct proc *p;
    682 	void *v;
    683 	register_t *retval;
    684 {
    685 #if 0
    686 	struct linux_sys_iopl_args /* {
    687 		syscallarg(int) level;
    688 	} */ *uap = v;
    689 #endif
    690 	struct trapframe *fp = p->p_md.md_regs;
    691 
    692 	if (suser(p->p_ucred, &p->p_acflag) != 0)
    693 		return EPERM;
    694 	fp->tf_eflags |= PSL_IOPL;
    695 	*retval = 0;
    696 	return 0;
    697 }
    698 
    699 /*
    700  * See above. If a root process tries to set access to an I/O port,
    701  * just let it have the whole range.
    702  */
    703 int
    704 linux_sys_ioperm(p, v, retval)
    705 	struct proc *p;
    706 	void *v;
    707 	register_t *retval;
    708 {
    709 	struct linux_sys_ioperm_args /* {
    710 		syscallarg(unsigned int) lo;
    711 		syscallarg(unsigned int) hi;
    712 		syscallarg(int) val;
    713 	} */ *uap = v;
    714 	struct trapframe *fp = p->p_md.md_regs;
    715 
    716 	if (suser(p->p_ucred, &p->p_acflag) != 0)
    717 		return EPERM;
    718 	if (SCARG(uap, val))
    719 		fp->tf_eflags |= PSL_IOPL;
    720 	*retval = 0;
    721 	return 0;
    722 }
    723