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