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