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