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