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