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