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