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