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