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