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