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