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