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