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