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