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