xref: /netbsd-src/sys/compat/linux/arch/i386/linux_machdep.c (revision dc306354b0b29af51801a7632f1e95265a68cd81)
1 /*	$NetBSD: linux_machdep.c,v 1.46 1999/01/08 11:59:38 kleink Exp $	*/
2 
3 /*-
4  * Copyright (c) 1995 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 "opt_vm86.h"
40 #include "opt_user_ldt.h"
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/signalvar.h>
45 #include <sys/kernel.h>
46 #include <sys/map.h>
47 #include <sys/proc.h>
48 #include <sys/user.h>
49 #include <sys/buf.h>
50 #include <sys/reboot.h>
51 #include <sys/conf.h>
52 #include <sys/exec.h>
53 #include <sys/file.h>
54 #include <sys/callout.h>
55 #include <sys/malloc.h>
56 #include <sys/mbuf.h>
57 #include <sys/msgbuf.h>
58 #include <sys/mount.h>
59 #include <sys/vnode.h>
60 #include <sys/device.h>
61 #include <sys/syscallargs.h>
62 #include <sys/filedesc.h>
63 #include <sys/exec_elf.h>
64 
65 #include <compat/linux/common/linux_types.h>
66 #include <compat/linux/common/linux_signal.h>
67 #include <compat/linux/common/linux_util.h>
68 #include <compat/linux/common/linux_ioctl.h>
69 #include <compat/linux/common/linux_exec.h>
70 #include <compat/linux/common/linux_machdep.h>
71 
72 #include <compat/linux/linux_syscallargs.h>
73 
74 #include <machine/cpu.h>
75 #include <machine/cpufunc.h>
76 #include <machine/psl.h>
77 #include <machine/reg.h>
78 #include <machine/segments.h>
79 #include <machine/specialreg.h>
80 #include <machine/sysarch.h>
81 #include <machine/vm86.h>
82 #include <machine/vmparam.h>
83 
84 /*
85  * To see whether pcvt is configured (for virtual console ioctl calls).
86  */
87 #ifndef NVT
88 #include "vt.h"
89 #endif
90 #if NVT > 0
91 #include <arch/i386/isa/pcvt/pcvt_ioctl.h>
92 #endif
93 
94 #include "wsdisplay.h"
95 #if (NWSDISPLAY > 0)
96 #include <sys/ioctl.h>
97 #include <dev/wscons/wsdisplay_usl_io.h>
98 #include "opt_xserver.h"
99 #endif
100 
101 #ifdef USER_LDT
102 #include <machine/cpu.h>
103 int linux_read_ldt __P((struct proc *, struct linux_sys_modify_ldt_args *,
104     register_t *));
105 int linux_write_ldt __P((struct proc *, struct linux_sys_modify_ldt_args *,
106     register_t *));
107 #endif
108 
109 /*
110  * Deal with some i386-specific things in the Linux emulation code.
111  */
112 
113 void
114 linux_setregs(p, epp, stack)
115 	struct proc *p;
116 	struct exec_package *epp;
117 	u_long stack;
118 {
119 	register struct pcb *pcb = &p->p_addr->u_pcb;
120 
121 	setregs(p, epp, stack);
122 	pcb->pcb_savefpu.sv_env.en_cw = __Linux_NPXCW__;
123 }
124 
125 /*
126  * Send an interrupt to process.
127  *
128  * Stack is set up to allow sigcode stored
129  * in u. to call routine, followed by kcall
130  * to sigreturn routine below.  After sigreturn
131  * resets the signal mask, the stack, and the
132  * frame pointer, it returns to the user
133  * specified pc, psl.
134  */
135 
136 void
137 linux_sendsig(catcher, sig, mask, code)
138 	sig_t catcher;
139 	int sig;
140 	sigset_t *mask;
141 	u_long code;
142 {
143 	register struct proc *p = curproc;
144 	register struct trapframe *tf;
145 	struct linux_sigframe *fp, frame;
146 	struct sigacts *psp = p->p_sigacts;
147 
148 	tf = p->p_md.md_regs;
149 
150 	/* Allocate space for the signal handler context. */
151 	/* XXX Linux doesn't support the signal stack. */
152 	fp = (struct linux_sigframe *)tf->tf_esp;
153 	fp--;
154 
155 	/* Build stack frame for signal trampoline. */
156 	frame.sf_handler = catcher;
157 	frame.sf_sig = native_to_linux_sig[sig];
158 
159 	/* Save register context. */
160 #ifdef VM86
161 	if (tf->tf_eflags & PSL_VM) {
162 		frame.sf_sc.sc_gs = tf->tf_vm86_gs;
163 		frame.sf_sc.sc_fs = tf->tf_vm86_fs;
164 		frame.sf_sc.sc_es = tf->tf_vm86_es;
165 		frame.sf_sc.sc_ds = tf->tf_vm86_ds;
166 		frame.sf_sc.sc_eflags = get_vflags(p);
167 	} else
168 #endif
169 	{
170 		__asm("movl %%gs,%w0" : "=r" (frame.sf_sc.sc_gs));
171 		__asm("movl %%fs,%w0" : "=r" (frame.sf_sc.sc_fs));
172 		frame.sf_sc.sc_es = tf->tf_es;
173 		frame.sf_sc.sc_ds = tf->tf_ds;
174 		frame.sf_sc.sc_eflags = tf->tf_eflags;
175 	}
176 	frame.sf_sc.sc_edi = tf->tf_edi;
177 	frame.sf_sc.sc_esi = tf->tf_esi;
178 	frame.sf_sc.sc_ebp = tf->tf_ebp;
179 	frame.sf_sc.sc_ebx = tf->tf_ebx;
180 	frame.sf_sc.sc_edx = tf->tf_edx;
181 	frame.sf_sc.sc_ecx = tf->tf_ecx;
182 	frame.sf_sc.sc_eax = tf->tf_eax;
183 	frame.sf_sc.sc_eip = tf->tf_eip;
184 	frame.sf_sc.sc_cs = tf->tf_cs;
185 	frame.sf_sc.sc_esp_at_signal = tf->tf_esp;
186 	frame.sf_sc.sc_ss = tf->tf_ss;
187 	frame.sf_sc.sc_err = tf->tf_err;
188 	frame.sf_sc.sc_trapno = tf->tf_trapno;
189 
190 	/* Save signal stack. */
191 	/* XXX Linux doesn't support the signal stack. */
192 
193 	/* Save signal mask. */
194 	native_to_linux_sigset(mask, &frame.sf_sc.sc_mask);
195 
196 	if (copyout(&frame, fp, sizeof(frame)) != 0) {
197 		/*
198 		 * Process has trashed its stack; give it an illegal
199 		 * instruction to halt it in its tracks.
200 		 */
201 		sigexit(p, SIGILL);
202 		/* NOTREACHED */
203 	}
204 
205 	/*
206 	 * Build context to run handler in.
207 	 */
208 	tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
209 	tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
210 	tf->tf_eip = (int)psp->ps_sigcode;
211 	tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
212 	tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
213 	tf->tf_esp = (int)fp;
214 	tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
215 
216 	/* Remember that we're now on the signal stack. */
217 	/* XXX Linux doesn't support the signal stack. */
218 }
219 
220 /*
221  * System call to cleanup state after a signal
222  * has been taken.  Reset signal mask and
223  * stack state from context left by sendsig (above).
224  * Return to previous pc and psl as specified by
225  * context left by sendsig. Check carefully to
226  * make sure that the user has not modified the
227  * psl to gain improper privileges or to cause
228  * a machine fault.
229  */
230 int
231 linux_sys_rt_sigreturn(p, v, retval)
232 	struct proc *p;
233 	void *v;
234 	register_t *retval;
235 {
236 	/* XXX XAX write me */
237 	return(ENOSYS);
238 }
239 
240 int
241 linux_sys_sigreturn(p, v, retval)
242 	struct proc *p;
243 	void *v;
244 	register_t *retval;
245 {
246 	struct linux_sys_sigreturn_args /* {
247 		syscallarg(struct linux_sigcontext *) scp;
248 	} */ *uap = v;
249 	struct linux_sigcontext *scp, context;
250 	register struct trapframe *tf;
251 	sigset_t mask;
252 
253 	/*
254 	 * The trampoline code hands us the context.
255 	 * It is unsafe to keep track of it ourselves, in the event that a
256 	 * program jumps out of a signal handler.
257 	 */
258 	scp = SCARG(uap, scp);
259 	if (copyin((caddr_t)scp, &context, sizeof(*scp)) != 0)
260 		return (EFAULT);
261 
262 	/* Restore register context. */
263 	tf = p->p_md.md_regs;
264 #ifdef VM86
265 	if (context.sc_eflags & PSL_VM) {
266 		tf->tf_vm86_gs = context.sc_gs;
267 		tf->tf_vm86_fs = context.sc_fs;
268 		tf->tf_vm86_es = context.sc_es;
269 		tf->tf_vm86_ds = context.sc_ds;
270 		set_vflags(p, context.sc_eflags);
271 	} else
272 #endif
273 	{
274 		/*
275 		 * Check for security violations.  If we're returning to
276 		 * protected mode, the CPU will validate the segment registers
277 		 * automatically and generate a trap on violations.  We handle
278 		 * the trap, rather than doing all of the checking here.
279 		 */
280 		if (((context.sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
281 		    !USERMODE(context.sc_cs, context.sc_eflags))
282 			return (EINVAL);
283 
284 		/* %fs and %gs were restored by the trampoline. */
285 		tf->tf_es = context.sc_es;
286 		tf->tf_ds = context.sc_ds;
287 		tf->tf_eflags = context.sc_eflags;
288 	}
289 	tf->tf_edi = context.sc_edi;
290 	tf->tf_esi = context.sc_esi;
291 	tf->tf_ebp = context.sc_ebp;
292 	tf->tf_ebx = context.sc_ebx;
293 	tf->tf_edx = context.sc_edx;
294 	tf->tf_ecx = context.sc_ecx;
295 	tf->tf_eax = context.sc_eax;
296 	tf->tf_eip = context.sc_eip;
297 	tf->tf_cs = context.sc_cs;
298 	tf->tf_esp = context.sc_esp_at_signal;
299 	tf->tf_ss = context.sc_ss;
300 
301 	/* Restore signal stack. */
302 	p->p_sigacts->ps_sigstk.ss_flags &= ~SS_ONSTACK;
303 
304 	/* Restore signal mask. */
305 	linux_to_native_sigset(&context.sc_mask, &mask);
306 	(void) sigprocmask1(p, SIG_SETMASK, &mask, 0);
307 
308 	return (EJUSTRETURN);
309 }
310 
311 #ifdef USER_LDT
312 
313 int
314 linux_read_ldt(p, uap, retval)
315 	struct proc *p;
316 	struct linux_sys_modify_ldt_args /* {
317 		syscallarg(int) func;
318 		syscallarg(void *) ptr;
319 		syscallarg(size_t) bytecount;
320 	} */ *uap;
321 	register_t *retval;
322 {
323 	struct i386_get_ldt_args gl;
324 	int error;
325 	caddr_t sg;
326 	char *parms;
327 
328 	sg = stackgap_init(p->p_emul);
329 
330 	gl.start = 0;
331 	gl.desc = SCARG(uap, ptr);
332 	gl.num = SCARG(uap, bytecount) / sizeof(union descriptor);
333 
334 	parms = stackgap_alloc(&sg, sizeof(gl));
335 
336 	if ((error = copyout(&gl, parms, sizeof(gl))) != 0)
337 		return (error);
338 
339 	if ((error = i386_get_ldt(p, parms, retval)) != 0)
340 		return (error);
341 
342 	*retval *= sizeof(union descriptor);
343 	return (0);
344 }
345 
346 struct linux_ldt_info {
347 	u_int entry_number;
348 	u_long base_addr;
349 	u_int limit;
350 	u_int seg_32bit:1;
351 	u_int contents:2;
352 	u_int read_exec_only:1;
353 	u_int limit_in_pages:1;
354 	u_int seg_not_present:1;
355 };
356 
357 int
358 linux_write_ldt(p, uap, retval)
359 	struct proc *p;
360 	struct linux_sys_modify_ldt_args /* {
361 		syscallarg(int) func;
362 		syscallarg(void *) ptr;
363 		syscallarg(size_t) bytecount;
364 	} */ *uap;
365 	register_t *retval;
366 {
367 	struct linux_ldt_info ldt_info;
368 	struct segment_descriptor sd;
369 	struct i386_set_ldt_args sl;
370 	int error;
371 	caddr_t sg;
372 	char *parms;
373 
374 	if (SCARG(uap, bytecount) != sizeof(ldt_info))
375 		return (EINVAL);
376 	if ((error = copyin(SCARG(uap, ptr), &ldt_info, sizeof(ldt_info))) != 0)
377 		return error;
378 	if (ldt_info.contents == 3)
379 		return (EINVAL);
380 
381 	sg = stackgap_init(p->p_emul);
382 
383 	sd.sd_lobase = ldt_info.base_addr & 0xffffff;
384 	sd.sd_hibase = (ldt_info.base_addr >> 24) & 0xff;
385 	sd.sd_lolimit = ldt_info.limit & 0xffff;
386 	sd.sd_hilimit = (ldt_info.limit >> 16) & 0xf;
387 	sd.sd_type =
388 	    16 | (ldt_info.contents << 2) | (!ldt_info.read_exec_only << 1);
389 	sd.sd_dpl = SEL_UPL;
390 	sd.sd_p = !ldt_info.seg_not_present;
391 	sd.sd_def32 = ldt_info.seg_32bit;
392 	sd.sd_gran = ldt_info.limit_in_pages;
393 
394 	sl.start = ldt_info.entry_number;
395 	sl.desc = stackgap_alloc(&sg, sizeof(sd));
396 	sl.num = 1;
397 
398 #if 0
399 	printf("linux_write_ldt: idx=%d, base=%x, limit=%x\n",
400 	    ldt_info.entry_number, ldt_info.base_addr, ldt_info.limit);
401 #endif
402 
403 	parms = stackgap_alloc(&sg, sizeof(sl));
404 
405 	if ((error = copyout(&sd, sl.desc, sizeof(sd))) != 0)
406 		return (error);
407 	if ((error = copyout(&sl, parms, sizeof(sl))) != 0)
408 		return (error);
409 
410 	if ((error = i386_set_ldt(p, parms, retval)) != 0)
411 		return (error);
412 
413 	*retval = 0;
414 	return (0);
415 }
416 
417 #endif /* USER_LDT */
418 
419 int
420 linux_sys_modify_ldt(p, v, retval)
421 	struct proc *p;
422 	void *v;
423 	register_t *retval;
424 {
425 	struct linux_sys_modify_ldt_args /* {
426 		syscallarg(int) func;
427 		syscallarg(void *) ptr;
428 		syscallarg(size_t) bytecount;
429 	} */ *uap = v;
430 
431 	switch (SCARG(uap, func)) {
432 #ifdef USER_LDT
433 	case 0:
434 		return (linux_read_ldt(p, uap, retval));
435 
436 	case 1:
437 		return (linux_write_ldt(p, uap, retval));
438 #endif /* USER_LDT */
439 
440 	default:
441 		return (ENOSYS);
442 	}
443 }
444 
445 /*
446  * XXX Pathetic hack to make svgalib work. This will fake the major
447  * device number of an opened VT so that svgalib likes it. grmbl.
448  * Should probably do it 'wrong the right way' and use a mapping
449  * array for all major device numbers, and map linux_mknod too.
450  */
451 dev_t
452 linux_fakedev(dev)
453 	dev_t dev;
454 {
455 #if (NVT > 0)
456 	if (major(dev) == NETBSD_PCCONS_MAJOR)
457 		return makedev(LINUX_CONS_MAJOR, (minor(dev) + 1));
458 #endif
459 #if (NWSDISPLAY > 0)
460 	if (major(dev) == NETBSD_WSCONS_MAJOR)
461 		return makedev(LINUX_CONS_MAJOR, (minor(dev) + 1));
462 #endif
463 	return dev;
464 }
465 
466 #if (NWSDISPLAY > 0) && defined(XSERVER)
467 /*
468  * That's not complete, but enough to get an X server running.
469  */
470 #define NR_KEYS 128
471 static u_short plain_map[NR_KEYS] = {
472 	0x0200,	0x001b,	0x0031,	0x0032,	0x0033,	0x0034,	0x0035,	0x0036,
473 	0x0037,	0x0038,	0x0039,	0x0030,	0x002d,	0x003d,	0x007f,	0x0009,
474 	0x0b71,	0x0b77,	0x0b65,	0x0b72,	0x0b74,	0x0b79,	0x0b75,	0x0b69,
475 	0x0b6f,	0x0b70,	0x005b,	0x005d,	0x0201,	0x0702,	0x0b61,	0x0b73,
476 	0x0b64,	0x0b66,	0x0b67,	0x0b68,	0x0b6a,	0x0b6b,	0x0b6c,	0x003b,
477 	0x0027,	0x0060,	0x0700,	0x005c,	0x0b7a,	0x0b78,	0x0b63,	0x0b76,
478 	0x0b62,	0x0b6e,	0x0b6d,	0x002c,	0x002e,	0x002f,	0x0700,	0x030c,
479 	0x0703,	0x0020,	0x0207,	0x0100,	0x0101,	0x0102,	0x0103,	0x0104,
480 	0x0105,	0x0106,	0x0107,	0x0108,	0x0109,	0x0208,	0x0209,	0x0307,
481 	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,
482 	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x003c,	0x010a,
483 	0x010b,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
484 	0x030e,	0x0702,	0x030d,	0x001c,	0x0701,	0x0205,	0x0114,	0x0603,
485 	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,
486 	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,
487 	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
488 }, shift_map[NR_KEYS] = {
489 	0x0200,	0x001b,	0x0021,	0x0040,	0x0023,	0x0024,	0x0025,	0x005e,
490 	0x0026,	0x002a,	0x0028,	0x0029,	0x005f,	0x002b,	0x007f,	0x0009,
491 	0x0b51,	0x0b57,	0x0b45,	0x0b52,	0x0b54,	0x0b59,	0x0b55,	0x0b49,
492 	0x0b4f,	0x0b50,	0x007b,	0x007d,	0x0201,	0x0702,	0x0b41,	0x0b53,
493 	0x0b44,	0x0b46,	0x0b47,	0x0b48,	0x0b4a,	0x0b4b,	0x0b4c,	0x003a,
494 	0x0022,	0x007e,	0x0700,	0x007c,	0x0b5a,	0x0b58,	0x0b43,	0x0b56,
495 	0x0b42,	0x0b4e,	0x0b4d,	0x003c,	0x003e,	0x003f,	0x0700,	0x030c,
496 	0x0703,	0x0020,	0x0207,	0x010a,	0x010b,	0x010c,	0x010d,	0x010e,
497 	0x010f,	0x0110,	0x0111,	0x0112,	0x0113,	0x0213,	0x0203,	0x0307,
498 	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,
499 	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x003e,	0x010a,
500 	0x010b,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
501 	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,
502 	0x020b,	0x0601,	0x0602,	0x0117,	0x0600,	0x020a,	0x0115,	0x0116,
503 	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,
504 	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
505 }, altgr_map[NR_KEYS] = {
506 	0x0200,	0x0200,	0x0200,	0x0040,	0x0200,	0x0024,	0x0200,	0x0200,
507 	0x007b,	0x005b,	0x005d,	0x007d,	0x005c,	0x0200,	0x0200,	0x0200,
508 	0x0b71,	0x0b77,	0x0918,	0x0b72,	0x0b74,	0x0b79,	0x0b75,	0x0b69,
509 	0x0b6f,	0x0b70,	0x0200,	0x007e,	0x0201,	0x0702,	0x0914,	0x0b73,
510 	0x0917,	0x0919,	0x0b67,	0x0b68,	0x0b6a,	0x0b6b,	0x0b6c,	0x0200,
511 	0x0200,	0x0200,	0x0700,	0x0200,	0x0b7a,	0x0b78,	0x0916,	0x0b76,
512 	0x0915,	0x0b6e,	0x0b6d,	0x0200,	0x0200,	0x0200,	0x0700,	0x030c,
513 	0x0703,	0x0200,	0x0207,	0x050c,	0x050d,	0x050e,	0x050f,	0x0510,
514 	0x0511,	0x0512,	0x0513,	0x0514,	0x0515,	0x0208,	0x0202,	0x0911,
515 	0x0912,	0x0913,	0x030b,	0x090e,	0x090f,	0x0910,	0x030a,	0x090b,
516 	0x090c,	0x090d,	0x090a,	0x0310,	0x0206,	0x0200,	0x007c,	0x0516,
517 	0x0517,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
518 	0x030e,	0x0702,	0x030d,	0x0200,	0x0701,	0x0205,	0x0114,	0x0603,
519 	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,
520 	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,
521 	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
522 }, ctrl_map[NR_KEYS] = {
523 	0x0200,	0x0200,	0x0200,	0x0000,	0x001b,	0x001c,	0x001d,	0x001e,
524 	0x001f,	0x007f,	0x0200,	0x0200,	0x001f,	0x0200,	0x0008,	0x0200,
525 	0x0011,	0x0017,	0x0005,	0x0012,	0x0014,	0x0019,	0x0015,	0x0009,
526 	0x000f,	0x0010,	0x001b,	0x001d,	0x0201,	0x0702,	0x0001,	0x0013,
527 	0x0004,	0x0006,	0x0007,	0x0008,	0x000a,	0x000b,	0x000c,	0x0200,
528 	0x0007,	0x0000,	0x0700,	0x001c,	0x001a,	0x0018,	0x0003,	0x0016,
529 	0x0002,	0x000e,	0x000d,	0x0200,	0x020e,	0x007f,	0x0700,	0x030c,
530 	0x0703,	0x0000,	0x0207,	0x0100,	0x0101,	0x0102,	0x0103,	0x0104,
531 	0x0105,	0x0106,	0x0107,	0x0108,	0x0109,	0x0208,	0x0204,	0x0307,
532 	0x0308,	0x0309,	0x030b,	0x0304,	0x0305,	0x0306,	0x030a,	0x0301,
533 	0x0302,	0x0303,	0x0300,	0x0310,	0x0206,	0x0200,	0x0200,	0x010a,
534 	0x010b,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
535 	0x030e,	0x0702,	0x030d,	0x001c,	0x0701,	0x0205,	0x0114,	0x0603,
536 	0x0118,	0x0601,	0x0602,	0x0117,	0x0600,	0x0119,	0x0115,	0x0116,
537 	0x011a,	0x010c,	0x010d,	0x011b,	0x011c,	0x0110,	0x0311,	0x011d,
538 	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,	0x0200,
539 };
540 
541 u_short *linux_keytabs[] = {
542 	plain_map, shift_map, altgr_map, altgr_map, ctrl_map
543 };
544 #endif
545 
546 /*
547  * We come here in a last attempt to satisfy a Linux ioctl() call
548  */
549 int
550 linux_machdepioctl(p, v, retval)
551 	struct proc *p;
552 	void *v;
553 	register_t *retval;
554 {
555 	struct linux_sys_ioctl_args /* {
556 		syscallarg(int) fd;
557 		syscallarg(u_long) com;
558 		syscallarg(caddr_t) data;
559 	} */ *uap = v;
560 	struct sys_ioctl_args bia;
561 	u_long com;
562 #if (NVT > 0) || (NWSDISPLAY > 0)
563 	int error;
564 	struct vt_mode lvt;
565 	caddr_t bvtp, sg;
566 #endif
567 #if (NWSDISPLAY > 0) && defined(XSERVER)
568 	struct kbentry kbe;
569 #endif
570 
571 	SCARG(&bia, fd) = SCARG(uap, fd);
572 	SCARG(&bia, data) = SCARG(uap, data);
573 	com = SCARG(uap, com);
574 
575 	switch (com) {
576 #if (NVT > 0) || (NWSDISPLAY > 0)
577 	case LINUX_KDGKBMODE:
578 		com = KDGKBMODE;
579 		break;
580 	case LINUX_KDSKBMODE:
581 		com = KDSKBMODE;
582 		if ((unsigned)SCARG(uap, data) == LINUX_K_MEDIUMRAW)
583 			SCARG(&bia, data) = (caddr_t)K_RAW;
584 		break;
585 	case LINUX_KDMKTONE:
586 		com = KDMKTONE;
587 		break;
588 	case LINUX_KDSETMODE:
589 		com = KDSETMODE;
590 		break;
591 	case LINUX_KDENABIO:
592 		com = KDENABIO;
593 		break;
594 	case LINUX_KDDISABIO:
595 		com = KDDISABIO;
596 		break;
597 	case LINUX_KDGETLED:
598 		com = KDGETLED;
599 		break;
600 	case LINUX_KDSETLED:
601 		com = KDSETLED;
602 		break;
603 	case LINUX_VT_OPENQRY:
604 		com = VT_OPENQRY;
605 		break;
606 	case LINUX_VT_GETMODE:
607 		SCARG(&bia, com) = VT_GETMODE;
608 		if ((error = sys_ioctl(p, &bia, retval)))
609 			return error;
610 		if ((error = copyin(SCARG(uap, data), (caddr_t)&lvt,
611 		    sizeof (struct vt_mode))))
612 			return error;
613 		lvt.relsig = native_to_linux_sig[lvt.relsig];
614 		lvt.acqsig = native_to_linux_sig[lvt.acqsig];
615 		lvt.frsig = native_to_linux_sig[lvt.frsig];
616 		return copyout((caddr_t)&lvt, SCARG(uap, data),
617 		    sizeof (struct vt_mode));
618 	case LINUX_VT_SETMODE:
619 		com = VT_SETMODE;
620 		if ((error = copyin(SCARG(uap, data), (caddr_t)&lvt,
621 		    sizeof (struct vt_mode))))
622 			return error;
623 		lvt.relsig = linux_to_native_sig[lvt.relsig];
624 		lvt.acqsig = linux_to_native_sig[lvt.acqsig];
625 		lvt.frsig = linux_to_native_sig[lvt.frsig];
626 		sg = stackgap_init(p->p_emul);
627 		bvtp = stackgap_alloc(&sg, sizeof (struct vt_mode));
628 		if ((error = copyout(&lvt, bvtp, sizeof (struct vt_mode))))
629 			return error;
630 		SCARG(&bia, data) = bvtp;
631 		break;
632 	case LINUX_VT_RELDISP:
633 		com = VT_RELDISP;
634 		break;
635 	case LINUX_VT_ACTIVATE:
636 		com = VT_ACTIVATE;
637 		break;
638 	case LINUX_VT_WAITACTIVE:
639 		com = VT_WAITACTIVE;
640 		break;
641 #endif
642 #if (NWSDISPLAY > 0)
643 	case LINUX_VT_GETSTATE:
644 		com = VT_GETSTATE;
645 		break;
646 #ifdef XSERVER
647 	case LINUX_KDGKBTYPE:
648 		/* This is what Linux does. */
649 		return (subyte(SCARG(uap, data), KB_101));
650 	case LINUX_KDGKBENT:
651 		/*
652 		 * The Linux KDGKBENT ioctl is different from the
653 		 * SYSV original. So we handle it in machdep code.
654 		 * XXX We should use keyboard mapping information
655 		 * from wsdisplay, but this would be expensive.
656 		 */
657 		if ((error = copyin(SCARG(uap, data), &kbe,
658 				    sizeof(struct kbentry))))
659 			return (error);
660 		if (kbe.kb_table >= sizeof(linux_keytabs) / sizeof(u_short *)
661 		    || kbe.kb_index >= NR_KEYS)
662 			return (EINVAL);
663 		kbe.kb_value = linux_keytabs[kbe.kb_table][kbe.kb_index];
664 		return (copyout(&kbe, SCARG(uap, data),
665 				sizeof(struct kbentry)));
666 #endif
667 #endif
668 	default:
669 		printf("linux_machdepioctl: invalid ioctl %08lx\n", com);
670 		return EINVAL;
671 	}
672 	SCARG(&bia, com) = com;
673 	return sys_ioctl(p, &bia, retval);
674 }
675 
676 /*
677  * Set I/O permissions for a process. Just set the maximum level
678  * right away (ignoring the argument), otherwise we would have
679  * to rely on I/O permission maps, which are not implemented.
680  */
681 int
682 linux_sys_iopl(p, v, retval)
683 	struct proc *p;
684 	void *v;
685 	register_t *retval;
686 {
687 #if 0
688 	struct linux_sys_iopl_args /* {
689 		syscallarg(int) level;
690 	} */ *uap = v;
691 #endif
692 	struct trapframe *fp = p->p_md.md_regs;
693 
694 	if (suser(p->p_ucred, &p->p_acflag) != 0)
695 		return EPERM;
696 	fp->tf_eflags |= PSL_IOPL;
697 	*retval = 0;
698 	return 0;
699 }
700 
701 /*
702  * See above. If a root process tries to set access to an I/O port,
703  * just let it have the whole range.
704  */
705 int
706 linux_sys_ioperm(p, v, retval)
707 	struct proc *p;
708 	void *v;
709 	register_t *retval;
710 {
711 	struct linux_sys_ioperm_args /* {
712 		syscallarg(unsigned int) lo;
713 		syscallarg(unsigned int) hi;
714 		syscallarg(int) val;
715 	} */ *uap = v;
716 	struct trapframe *fp = p->p_md.md_regs;
717 
718 	if (suser(p->p_ucred, &p->p_acflag) != 0)
719 		return EPERM;
720 	if (SCARG(uap, val))
721 		fp->tf_eflags |= PSL_IOPL;
722 	*retval = 0;
723 	return 0;
724 }
725