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