1 /* $NetBSD: netbsd32_machdep.c,v 1.142 2025/04/24 23:51:03 riastradh Exp $ */ 2 3 /* 4 * Copyright (c) 2001 Wasabi Systems, Inc. 5 * All rights reserved. 6 * 7 * Written by Frank van der Linden for Wasabi Systems, Inc. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed for the NetBSD Project by 20 * Wasabi Systems, Inc. 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22 * or promote products derived from this software without specific prior 23 * written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.142 2025/04/24 23:51:03 riastradh Exp $"); 40 41 #ifdef _KERNEL_OPT 42 #include "opt_compat_netbsd.h" 43 #include "opt_compat_netbsd32.h" 44 #include "opt_execfmt.h" 45 #include "opt_user_ldt.h" 46 #include "opt_mtrr.h" 47 #endif 48 49 #include <sys/param.h> 50 #include <sys/exec.h> 51 #include <sys/exec_aout.h> 52 #include <sys/kmem.h> 53 #include <sys/kmem.h> 54 #include <sys/proc.h> 55 #include <sys/signalvar.h> 56 #include <sys/systm.h> 57 #include <sys/core.h> 58 #include <sys/mount.h> 59 #include <sys/buf.h> 60 #include <sys/vnode.h> 61 #include <sys/ras.h> 62 #include <sys/ptrace.h> 63 #include <sys/kauth.h> 64 #include <sys/compat_stub.h> 65 66 #include <x86/fpu.h> 67 #include <x86/dbregs.h> 68 #include <machine/frame.h> 69 #include <machine/reg.h> 70 #include <machine/vmparam.h> 71 #ifdef MTRR 72 #include <machine/mtrr.h> 73 #endif 74 #include <machine/netbsd32_machdep.h> 75 #include <machine/sysarch.h> 76 #include <machine/userret.h> 77 #include <machine/gdt.h> 78 #include <machine/pmap_private.h> 79 80 #include <compat/netbsd32/netbsd32.h> 81 #include <compat/netbsd32/netbsd32_exec.h> 82 #include <compat/netbsd32/netbsd32_syscallargs.h> 83 84 #include <compat/sys/signal.h> 85 #include <compat/sys/signalvar.h> 86 87 /* Provide a the name of the architecture we're emulating */ 88 const char machine32[] = "i386"; 89 const char machine_arch32[] = "i386"; 90 91 static int netbsd32_process_doxmmregs(struct lwp *, struct lwp *, void *, bool); 92 static int netbsd32_process_xmmregio(struct lwp *, struct lwp *, struct uio *); 93 94 #ifdef USER_LDT 95 static int x86_64_get_ldt32(struct lwp *, void *, register_t *); 96 static int x86_64_set_ldt32(struct lwp *, void *, register_t *); 97 #else 98 #define x86_64_get_ldt32(x, y, z) ENOSYS 99 #define x86_64_set_ldt32(x, y, z) ENOSYS 100 #endif 101 102 #ifdef MTRR 103 static int x86_64_get_mtrr32(struct lwp *, void *, register_t *); 104 static int x86_64_set_mtrr32(struct lwp *, void *, register_t *); 105 #else 106 #define x86_64_get_mtrr32(x, y, z) ENOSYS 107 #define x86_64_set_mtrr32(x, y, z) ENOSYS 108 #endif 109 110 int check_sigcontext32(struct lwp *, const struct netbsd32_sigcontext *); 111 void netbsd32_buildcontext(struct lwp *, struct trapframe *, void *, 112 sig_t, int); 113 114 #ifdef EXEC_AOUT 115 /* 116 * There is no native a.out -- this function is required 117 * for i386 a.out emulation (COMPAT_NETBSD32+EXEC_AOUT). 118 */ 119 int 120 cpu_exec_aout_makecmds(struct lwp *p, struct exec_package *e) 121 { 122 123 return ENOEXEC; 124 } 125 #endif 126 127 void 128 netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 129 { 130 struct pcb *pcb; 131 struct trapframe *tf; 132 struct proc *p = l->l_proc; 133 134 pcb = lwp_getpcb(l); 135 136 #if defined(USER_LDT) 137 pmap_ldt_cleanup(l); 138 #endif 139 140 netbsd32_adjust_limits(p); 141 142 fpu_clear(l, pack->ep_osversion >= 699002600 143 ? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__); 144 x86_dbregs_clear(l); 145 146 kpreempt_disable(); 147 pcb->pcb_flags = PCB_COMPAT32; 148 p->p_flag |= PK_32; 149 l->l_md.md_flags = MDL_COMPAT32; /* force iret not sysret */ 150 cpu_segregs32_zero(l); 151 cpu_fsgs_reload(l, LSEL(LUDATA32_SEL, SEL_UPL), 152 LSEL(LUDATA32_SEL, SEL_UPL)); 153 kpreempt_enable(); 154 155 tf = l->l_md.md_regs; 156 tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL); 157 tf->tf_es = LSEL(LUDATA32_SEL, SEL_UPL); 158 tf->tf_rdi = 0; 159 tf->tf_rsi = 0; 160 tf->tf_rbp = 0; 161 tf->tf_rbx = (uint32_t)p->p_psstrp; 162 tf->tf_rdx = 0; 163 tf->tf_rcx = 0; 164 tf->tf_rax = 0; 165 tf->tf_rip = pack->ep_entry; 166 tf->tf_cs = LSEL(LUCODE32_SEL, SEL_UPL); 167 tf->tf_rflags = PSL_USERSET; 168 tf->tf_rsp = stack; 169 tf->tf_ss = LSEL(LUDATA32_SEL, SEL_UPL); 170 } 171 172 void 173 netbsd32_buildcontext(struct lwp *l, struct trapframe *tf, void *fp, 174 sig_t catcher, int onstack) 175 { 176 /* 177 * Build context to run handler in. 178 */ 179 tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL); 180 tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); 181 #if 0 182 tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL); 183 tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL); 184 #endif 185 186 /* Ensure FP state is sane. */ 187 fpu_sigreset(l); 188 189 tf->tf_rip = (uint64_t)catcher; 190 tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); 191 tf->tf_rflags &= ~PSL_CLEARSIG; 192 tf->tf_rsp = (uint64_t)fp; 193 tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); 194 195 /* Remember that we're now on the signal stack. */ 196 if (onstack) 197 l->l_sigstk.ss_flags |= SS_ONSTACK; 198 if ((vaddr_t)catcher >= VM_MAXUSER_ADDRESS32) { 199 /* 200 * process has given an invalid address for the 201 * handler. Stop it, but do not do it before so 202 * we can return the right info to userland (or in core dump) 203 */ 204 sigexit(l, SIGILL); 205 /* NOTREACHED */ 206 } 207 } 208 209 void 210 netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 211 { 212 struct lwp *l = curlwp; 213 struct proc *p = l->l_proc; 214 struct sigacts *ps = p->p_sigacts; 215 int onstack, error; 216 int sig = ksi->ksi_signo; 217 struct netbsd32_sigframe_siginfo *fp, frame; 218 const struct sigaction *sa = &SIGACTION(p, sig); 219 sig_t catcher = sa->sa_handler; 220 struct trapframe *tf = l->l_md.md_regs; 221 stack_t * const ss = &l->l_sigstk; 222 223 /* Do we need to jump onto the signal stack? */ 224 onstack = 225 (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 226 (sa->sa_flags & SA_ONSTACK) != 0; 227 228 /* Allocate space for the signal handler context. */ 229 if (onstack) 230 fp = (struct netbsd32_sigframe_siginfo *) 231 ((char *)ss->ss_sp + ss->ss_size); 232 else 233 fp = (struct netbsd32_sigframe_siginfo *)tf->tf_rsp; 234 235 fp--; 236 fp = (struct netbsd32_sigframe_siginfo *)((uintptr_t)fp & 237 ~STACK_ALIGNBYTES32); 238 239 /* Build stack frame for signal trampoline. */ 240 switch (ps->sa_sigdesc[sig].sd_vers) { 241 case __SIGTRAMP_SIGCODE_VERSION: /* handled by sendsig_sigcontext */ 242 case __SIGTRAMP_SIGCONTEXT_VERSION: /* handled by sendsig_sigcontext */ 243 default: /* unknown version */ 244 printf("nsendsig: bad version %d\n", 245 ps->sa_sigdesc[sig].sd_vers); 246 sigexit(l, SIGILL); 247 case __SIGTRAMP_SIGINFO_VERSION: 248 break; 249 } 250 251 memset(&frame, 0, sizeof(frame)); 252 frame.sf_ra = (uint32_t)(uintptr_t)ps->sa_sigdesc[sig].sd_tramp; 253 frame.sf_signum = sig; 254 frame.sf_sip = (uint32_t)(uintptr_t)&fp->sf_si; 255 frame.sf_ucp = (uint32_t)(uintptr_t)&fp->sf_uc; 256 netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info); 257 frame.sf_uc.uc_flags = _UC_SIGMASK; 258 frame.sf_uc.uc_sigmask = *mask; 259 frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; 260 frame.sf_uc.uc_flags |= (ss->ss_flags & SS_ONSTACK) 261 ? _UC_SETSTACK : _UC_CLRSTACK; 262 sendsig_reset(l, sig); 263 264 mutex_exit(p->p_lock); 265 cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); 266 error = copyout(&frame, fp, sizeof(frame)); 267 mutex_enter(p->p_lock); 268 269 if (error != 0) { 270 /* 271 * Process has trashed its stack; give it an illegal 272 * instruction to halt it in its tracks. 273 */ 274 sigexit(l, SIGILL); 275 /* NOTREACHED */ 276 } 277 278 netbsd32_buildcontext(l, tf, fp, catcher, onstack); 279 } 280 281 /* 282 * Dump the machine specific segment at the start of a core dump. 283 */ 284 struct md_core32 { 285 struct reg32 intreg; 286 struct fpreg32 freg; 287 }; 288 289 int 290 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, 291 struct core32 *chdr) 292 { 293 struct md_core32 md_core; 294 struct coreseg cseg; 295 int error; 296 297 if (iocookie == NULL) { 298 CORE_SETMAGIC(*chdr, COREMAGIC, MID_I386, 0); 299 chdr->c_hdrsize = ALIGN32(sizeof(*chdr)); 300 chdr->c_seghdrsize = ALIGN32(sizeof(cseg)); 301 chdr->c_cpusize = sizeof(md_core); 302 chdr->c_nseg++; 303 return 0; 304 } 305 306 /* Save integer registers. */ 307 error = netbsd32_process_read_regs(l, &md_core.intreg); 308 if (error) 309 return error; 310 311 /* Save floating point registers. */ 312 error = netbsd32_process_read_fpregs(l, &md_core.freg, NULL); 313 if (error) 314 return error; 315 316 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_I386, CORE_CPU); 317 cseg.c_addr = 0; 318 cseg.c_size = chdr->c_cpusize; 319 320 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &cseg, 321 chdr->c_seghdrsize), ENOSYS, error); 322 if (error) 323 return error; 324 325 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &md_core, 326 sizeof(md_core)), ENOSYS, error); 327 328 return error; 329 } 330 331 int 332 netbsd32_ptrace_translate_request(int req) 333 { 334 335 switch (req) 336 { 337 case 0 ... PT_FIRSTMACH - 1: return req; 338 case PT32_STEP: return PT_STEP; 339 case PT32_GETREGS: return PT_GETREGS; 340 case PT32_SETREGS: return PT_SETREGS; 341 case PT32_GETFPREGS: return PT_GETFPREGS; 342 case PT32_SETFPREGS: return PT_SETFPREGS; 343 case PT32_GETXMMREGS: return PT_GETXMMREGS; 344 case PT32_SETXMMREGS: return PT_SETXMMREGS; 345 case PT32_GETDBREGS: return PT_GETDBREGS; 346 case PT32_SETDBREGS: return PT_SETDBREGS; 347 case PT32_SETSTEP: return PT_SETSTEP; 348 case PT32_CLEARSTEP: return PT_CLEARSTEP; 349 case PT32_GETXSTATE: return PT_GETXSTATE; 350 case PT32_SETXSTATE: return PT_SETXSTATE; 351 default: return -1; 352 } 353 } 354 355 int 356 netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) 357 { 358 struct trapframe *tf = l->l_md.md_regs; 359 360 /* XXX avoid sign extension problems with unknown upper bits? */ 361 regs->r_gs = tf->tf_gs & 0xffff; 362 regs->r_fs = tf->tf_fs & 0xffff; 363 regs->r_es = tf->tf_es & 0xffff; 364 regs->r_ds = tf->tf_ds & 0xffff; 365 regs->r_eflags = tf->tf_rflags; 366 regs->r_edi = tf->tf_rdi & 0xffffffff; 367 regs->r_esi = tf->tf_rsi & 0xffffffff; 368 regs->r_ebp = tf->tf_rbp & 0xffffffff; 369 regs->r_ebx = tf->tf_rbx & 0xffffffff; 370 regs->r_edx = tf->tf_rdx & 0xffffffff; 371 regs->r_ecx = tf->tf_rcx & 0xffffffff; 372 regs->r_eax = tf->tf_rax & 0xffffffff; 373 regs->r_eip = tf->tf_rip & 0xffffffff; 374 regs->r_cs = tf->tf_cs & 0xffff; 375 regs->r_esp = tf->tf_rsp & 0xffffffff; 376 regs->r_ss = tf->tf_ss & 0xffff; 377 378 return 0; 379 } 380 381 int 382 netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz) 383 { 384 385 __CTASSERT(sizeof(*regs) == sizeof(struct save87)); 386 process_read_fpregs_s87(l, (struct save87 *)regs); 387 return 0; 388 } 389 390 int 391 netbsd32_process_read_dbregs(struct lwp *l, struct dbreg32 *regs, size_t *sz) 392 { 393 struct dbreg regs64; 394 395 x86_dbregs_read(l, ®s64); 396 memset(regs, 0, sizeof(*regs)); 397 regs->dr[0] = regs64.dr[0] & 0xffffffff; 398 regs->dr[1] = regs64.dr[1] & 0xffffffff; 399 regs->dr[2] = regs64.dr[2] & 0xffffffff; 400 regs->dr[3] = regs64.dr[3] & 0xffffffff; 401 402 regs->dr[6] = regs64.dr[6] & 0xffffffff; 403 regs->dr[7] = regs64.dr[7] & 0xffffffff; 404 405 return 0; 406 } 407 408 int 409 netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) 410 { 411 struct trapframe *tf; 412 struct pcb *pcb; 413 414 tf = l->l_md.md_regs; 415 pcb = lwp_getpcb(l); 416 417 /* 418 * Check for security violations. 419 */ 420 if (((regs->r_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) 421 return EINVAL; 422 if (!VALID_USER_CSEL32(regs->r_cs)) 423 return EINVAL; 424 if (regs->r_fs != 0 && !VALID_USER_DSEL32(regs->r_fs) && 425 !(VALID_USER_FSEL32(regs->r_fs) && pcb->pcb_fs != 0)) 426 return EINVAL; 427 if (regs->r_gs != 0 && !VALID_USER_DSEL32(regs->r_gs) && 428 !(VALID_USER_GSEL32(regs->r_gs) && pcb->pcb_gs != 0)) 429 return EINVAL; 430 if (regs->r_es != 0 && !VALID_USER_DSEL32(regs->r_es)) 431 return EINVAL; 432 if (!VALID_USER_DSEL32(regs->r_ds) || 433 !VALID_USER_DSEL32(regs->r_ss)) 434 return EINVAL; 435 if ((u_int)regs->r_eip >= VM_MAXUSER_ADDRESS32) 436 return EINVAL; 437 438 tf->tf_rax = regs->r_eax; 439 tf->tf_rcx = regs->r_ecx; 440 tf->tf_rdx = regs->r_edx; 441 tf->tf_rbx = regs->r_ebx; 442 tf->tf_rsp = regs->r_esp; 443 tf->tf_rbp = regs->r_ebp; 444 tf->tf_rsi = regs->r_esi; 445 tf->tf_rdi = regs->r_edi; 446 tf->tf_rip = regs->r_eip; 447 tf->tf_rflags = regs->r_eflags; 448 tf->tf_cs = regs->r_cs & 0xFFFF; 449 tf->tf_ss = regs->r_ss & 0xFFFF; 450 tf->tf_ds = regs->r_ds & 0xFFFF; 451 tf->tf_es = regs->r_es & 0xFFFF; 452 tf->tf_fs = regs->r_fs & 0xFFFF; 453 tf->tf_gs = regs->r_gs & 0xFFFF; 454 455 return 0; 456 } 457 458 int 459 netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs, 460 size_t sz) 461 { 462 463 __CTASSERT(sizeof(*regs) == sizeof(struct save87)); 464 process_write_fpregs_s87(l, (const struct save87 *)regs); 465 return 0; 466 } 467 468 int 469 netbsd32_process_write_dbregs(struct lwp *l, const struct dbreg32 *regs, 470 size_t sz) 471 { 472 size_t i; 473 struct dbreg regs64; 474 475 /* Check that DR0-DR3 contain user-space address */ 476 for (i = 0; i < X86_DBREGS; i++) { 477 if ((u_int)regs->dr[i] >= VM_MAXUSER_ADDRESS32) 478 return EINVAL; 479 } 480 481 if (regs->dr[7] & X86_DR7_GENERAL_DETECT_ENABLE) { 482 return EINVAL; 483 } 484 485 memset(®s64, 0, sizeof(regs64)); 486 487 regs64.dr[0] = (u_int)regs->dr[0]; 488 regs64.dr[1] = (u_int)regs->dr[1]; 489 regs64.dr[2] = (u_int)regs->dr[2]; 490 regs64.dr[3] = (u_int)regs->dr[3]; 491 492 regs64.dr[6] = (u_int)regs->dr[6]; 493 regs64.dr[7] = (u_int)regs->dr[7]; 494 495 x86_dbregs_write(l, ®s64); 496 return 0; 497 } 498 499 static int 500 netbsd32_process_doxmmregs(struct lwp *curl, struct lwp *l, void *addr, 501 bool write) 502 /* curl: tracer */ 503 /* l: traced */ 504 { 505 struct uio uio; 506 struct iovec iov; 507 struct vmspace *vm; 508 int error; 509 510 if ((curl->l_proc->p_flag & PK_32) == 0 || 511 (l->l_proc->p_flag & PK_32) == 0) 512 return EINVAL; 513 514 if (!process_machdep_validfpu(l->l_proc)) 515 return EINVAL; 516 517 error = proc_vmspace_getref(curl->l_proc, &vm); 518 if (error) 519 return error; 520 521 iov.iov_base = addr; 522 iov.iov_len = sizeof(struct xmmregs32); 523 uio.uio_iov = &iov; 524 uio.uio_iovcnt = 1; 525 uio.uio_offset = 0; 526 uio.uio_resid = sizeof(struct xmmregs32); 527 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 528 uio.uio_vmspace = vm; 529 530 error = netbsd32_process_xmmregio(curl, l, &uio); 531 uvmspace_free(vm); 532 return error; 533 } 534 535 static int 536 netbsd32_process_xmmregio(struct lwp *curl, struct lwp *l, struct uio *uio) 537 /* curl: tracer */ 538 /* l: traced */ 539 { 540 struct xmmregs32 regs; 541 int error; 542 char *kv; 543 size_t kl; 544 545 kl = sizeof(regs); 546 kv = (char *)®s; 547 548 if (uio->uio_offset < 0 || uio->uio_offset > (off_t)kl) 549 return EINVAL; 550 551 kv += uio->uio_offset; 552 kl -= uio->uio_offset; 553 554 if (kl > uio->uio_resid) 555 kl = uio->uio_resid; 556 557 process_read_fpregs_xmm(l, ®s.fxstate); 558 error = uiomove(kv, kl, uio); 559 if (error == 0 && uio->uio_rw == UIO_WRITE) { 560 if (l->l_proc->p_stat != SSTOP) 561 error = EBUSY; 562 else 563 process_write_fpregs_xmm(l, ®s.fxstate); 564 } 565 566 uio->uio_offset = 0; 567 return error; 568 } 569 570 int 571 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) 572 { 573 /* { 574 syscallarg(int) op; 575 syscallarg(netbsd32_voidp) parms; 576 } */ 577 int error; 578 579 switch (SCARG(uap, op)) { 580 case X86_IOPL: 581 error = x86_iopl(l, 582 NETBSD32PTR64(SCARG(uap, parms)), retval); 583 break; 584 case X86_GET_LDT: 585 error = x86_64_get_ldt32(l, 586 NETBSD32PTR64(SCARG(uap, parms)), retval); 587 break; 588 case X86_SET_LDT: 589 error = x86_64_set_ldt32(l, 590 NETBSD32PTR64(SCARG(uap, parms)), retval); 591 break; 592 case X86_GET_MTRR: 593 error = x86_64_get_mtrr32(l, 594 NETBSD32PTR64(SCARG(uap, parms)), retval); 595 break; 596 case X86_SET_MTRR: 597 error = x86_64_set_mtrr32(l, 598 NETBSD32PTR64(SCARG(uap, parms)), retval); 599 break; 600 default: 601 error = EINVAL; 602 break; 603 } 604 return error; 605 } 606 607 #ifdef USER_LDT 608 static int 609 x86_64_set_ldt32(struct lwp *l, void *args, register_t *retval) 610 { 611 struct x86_set_ldt_args32 ua32; 612 struct x86_set_ldt_args ua; 613 union descriptor *descv; 614 int error; 615 616 if ((error = copyin(args, &ua32, sizeof(ua32))) != 0) 617 return error; 618 619 ua.start = ua32.start; 620 ua.num = ua32.num; 621 622 if (ua.num < 0 || ua.num > MAX_USERLDT_SLOTS) 623 return EINVAL; 624 625 const size_t alloc_size = sizeof(*descv) * ua.num; 626 627 descv = kmem_alloc(alloc_size, KM_SLEEP); 628 error = copyin((void *)(uintptr_t)ua32.desc, descv, 629 sizeof(*descv) * ua.num); 630 if (error == 0) 631 error = x86_set_ldt1(l, &ua, descv); 632 *retval = ua.start; 633 634 kmem_free(descv, alloc_size); 635 return error; 636 } 637 638 static int 639 x86_64_get_ldt32(struct lwp *l, void *args, register_t *retval) 640 { 641 struct x86_get_ldt_args32 ua32; 642 struct x86_get_ldt_args ua; 643 union descriptor *cp; 644 int error; 645 646 if ((error = copyin(args, &ua32, sizeof(ua32))) != 0) 647 return error; 648 649 ua.start = ua32.start; 650 ua.num = ua32.num; 651 652 if (ua.num < 0 || ua.num > MAX_USERLDT_SLOTS) 653 return EINVAL; 654 655 const size_t alloc_size = ua.num * sizeof(union descriptor); 656 657 cp = kmem_alloc(alloc_size, KM_SLEEP); 658 error = x86_get_ldt1(l, &ua, cp); 659 *retval = ua.num; 660 if (error == 0) 661 error = copyout(cp, (void *)(uintptr_t)ua32.desc, 662 ua.num * sizeof(*cp)); 663 664 kmem_free(cp, alloc_size); 665 return error; 666 } 667 #endif 668 669 #ifdef MTRR 670 static int 671 x86_64_get_mtrr32(struct lwp *l, void *args, register_t *retval) 672 { 673 struct x86_64_get_mtrr_args32 args32; 674 int error, i; 675 int32_t n; 676 struct mtrr32 *m32p, m32; 677 struct mtrr *m64p, *mp; 678 size_t size; 679 680 m64p = NULL; 681 682 if (mtrr_funcs == NULL) 683 return ENOSYS; 684 685 error = kauth_authorize_machdep(l->l_cred, KAUTH_MACHDEP_MTRR_GET, 686 NULL, NULL, NULL, NULL); 687 if (error) 688 return error; 689 690 error = copyin(args, &args32, sizeof(args32)); 691 if (error != 0) 692 return error; 693 694 if (args32.mtrrp == 0) { 695 n = (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX); 696 return copyout(&n, (void *)(uintptr_t)args32.n, sizeof(n)); 697 } 698 699 error = copyin((void *)(uintptr_t)args32.n, &n, sizeof(n)); 700 if (error != 0) 701 return error; 702 703 if (n <= 0 || n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX)) 704 return EINVAL; 705 706 size = n * sizeof(struct mtrr); 707 m64p = kmem_zalloc(size, KM_SLEEP); 708 error = mtrr_get(m64p, &n, l->l_proc, 0); 709 if (error != 0) 710 goto fail; 711 m32p = (struct mtrr32 *)(uintptr_t)args32.mtrrp; 712 mp = m64p; 713 for (i = 0; i < n; i++) { 714 m32.base = mp->base; 715 m32.len = mp->len; 716 m32.type = mp->type; 717 m32.flags = mp->flags; 718 m32.owner = mp->owner; 719 error = copyout(&m32, m32p, sizeof(m32)); 720 if (error != 0) 721 break; 722 mp++; 723 m32p++; 724 } 725 fail: 726 if (m64p != NULL) 727 kmem_free(m64p, size); 728 if (error != 0) 729 n = 0; 730 copyout(&n, (void *)(uintptr_t)args32.n, sizeof(n)); 731 return error; 732 } 733 734 static int 735 x86_64_set_mtrr32(struct lwp *l, void *args, register_t *retval) 736 { 737 struct x86_64_set_mtrr_args32 args32; 738 struct mtrr32 *m32p, m32; 739 struct mtrr *m64p, *mp; 740 int error, i; 741 int32_t n; 742 size_t size; 743 744 m64p = NULL; 745 746 if (mtrr_funcs == NULL) 747 return ENOSYS; 748 749 error = kauth_authorize_machdep(l->l_cred, KAUTH_MACHDEP_MTRR_SET, 750 NULL, NULL, NULL, NULL); 751 if (error) 752 return error; 753 754 error = copyin(args, &args32, sizeof(args32)); 755 if (error != 0) 756 return error; 757 758 error = copyin((void *)(uintptr_t)args32.n, &n, sizeof(n)); 759 if (error != 0) 760 return error; 761 762 if (n <= 0 || n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX)) { 763 error = EINVAL; 764 goto fail; 765 } 766 767 size = n * sizeof(struct mtrr); 768 m64p = kmem_zalloc(size, KM_SLEEP); 769 m32p = (struct mtrr32 *)(uintptr_t)args32.mtrrp; 770 mp = m64p; 771 for (i = 0; i < n; i++) { 772 error = copyin(m32p, &m32, sizeof(m32)); 773 if (error != 0) 774 goto fail; 775 mp->base = m32.base; 776 mp->len = m32.len; 777 mp->type = m32.type; 778 mp->flags = m32.flags; 779 mp->owner = m32.owner; 780 m32p++; 781 mp++; 782 } 783 784 error = mtrr_set(m64p, &n, l->l_proc, 0); 785 fail: 786 if (m64p != NULL) 787 kmem_free(m64p, size); 788 if (error != 0) 789 n = 0; 790 copyout(&n, (void *)(uintptr_t)args32.n, sizeof(n)); 791 return error; 792 } 793 #endif 794 795 int 796 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) 797 { 798 struct trapframe *tf = l->l_md.md_regs; 799 const __greg32_t *gr = mcp->__gregs; 800 struct proc *p = l->l_proc; 801 int error; 802 803 /* Restore register context, if any. */ 804 if ((flags & _UC_CPU) != 0) { 805 /* 806 * Check for security violations. 807 */ 808 error = cpu_mcontext32_validate(l, mcp); 809 if (error != 0) 810 return error; 811 812 cpu_fsgs_reload(l, gr[_REG32_FS], gr[_REG32_GS]); 813 tf->tf_es = gr[_REG32_ES] & 0xFFFF; 814 tf->tf_ds = gr[_REG32_DS] & 0xFFFF; 815 /* Only change the user-alterable part of eflags */ 816 tf->tf_rflags &= ~PSL_USER; 817 tf->tf_rflags |= (gr[_REG32_EFL] & PSL_USER); 818 tf->tf_rdi = gr[_REG32_EDI]; 819 tf->tf_rsi = gr[_REG32_ESI]; 820 tf->tf_rbp = gr[_REG32_EBP]; 821 tf->tf_rbx = gr[_REG32_EBX]; 822 tf->tf_rdx = gr[_REG32_EDX]; 823 tf->tf_rcx = gr[_REG32_ECX]; 824 tf->tf_rax = gr[_REG32_EAX]; 825 tf->tf_rip = gr[_REG32_EIP]; 826 tf->tf_cs = gr[_REG32_CS] & 0xFFFF; 827 tf->tf_rsp = gr[_REG32_UESP]; 828 tf->tf_ss = gr[_REG32_SS] & 0xFFFF; 829 } 830 831 if ((flags & _UC_TLSBASE) != 0) 832 lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase); 833 834 /* Restore floating point register context, if any. */ 835 if ((flags & _UC_FPU) != 0) { 836 /* Assume fxsave context */ 837 process_write_fpregs_xmm(l, (const struct fxsave *) 838 &mcp->__fpregs.__fp_reg_set.__fp_xmm_state); 839 } 840 841 mutex_enter(p->p_lock); 842 if (flags & _UC_SETSTACK) 843 l->l_sigstk.ss_flags |= SS_ONSTACK; 844 if (flags & _UC_CLRSTACK) 845 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 846 mutex_exit(p->p_lock); 847 848 return 0; 849 } 850 851 void 852 cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flags) 853 { 854 const struct trapframe *tf = l->l_md.md_regs; 855 __greg32_t *gr = mcp->__gregs; 856 __greg32_t ras_eip; 857 858 /* Save register context. */ 859 gr[_REG32_GS] = tf->tf_gs & 0xFFFF; 860 gr[_REG32_FS] = tf->tf_fs & 0xFFFF; 861 gr[_REG32_ES] = tf->tf_es & 0xFFFF; 862 gr[_REG32_DS] = tf->tf_ds & 0xFFFF; 863 gr[_REG32_EFL] = tf->tf_rflags; 864 gr[_REG32_EDI] = tf->tf_rdi; 865 gr[_REG32_ESI] = tf->tf_rsi; 866 gr[_REG32_EBP] = tf->tf_rbp; 867 gr[_REG32_EBX] = tf->tf_rbx; 868 gr[_REG32_EDX] = tf->tf_rdx; 869 gr[_REG32_ECX] = tf->tf_rcx; 870 gr[_REG32_EAX] = tf->tf_rax; 871 gr[_REG32_EIP] = tf->tf_rip; 872 gr[_REG32_CS] = tf->tf_cs & 0xFFFF; 873 gr[_REG32_ESP] = tf->tf_rsp; 874 gr[_REG32_UESP] = tf->tf_rsp; 875 gr[_REG32_SS] = tf->tf_ss & 0xFFFF; 876 gr[_REG32_TRAPNO] = tf->tf_trapno; 877 gr[_REG32_ERR] = tf->tf_err; 878 879 if ((ras_eip = (__greg32_t)(uintptr_t)ras_lookup(l->l_proc, 880 (void *) (uintptr_t)gr[_REG32_EIP])) != (__greg32_t)-1) 881 gr[_REG32_EIP] = ras_eip; 882 883 *flags |= _UC_CPU; 884 885 mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private; 886 *flags |= _UC_TLSBASE; 887 888 /* Save floating point register context. */ 889 process_read_fpregs_xmm(l, (struct fxsave *) 890 &mcp->__fpregs.__fp_reg_set.__fp_xmm_state); 891 memset(&mcp->__fpregs.__fp_pad, 0, sizeof(mcp->__fpregs.__fp_pad)); 892 *flags |= _UC_FXSAVE | _UC_FPU; 893 } 894 895 void 896 startlwp32(void *arg) 897 { 898 ucontext32_t *uc = arg; 899 lwp_t *l = curlwp; 900 int error __diagused; 901 902 error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); 903 KASSERT(error == 0); 904 905 /* Note: we are freeing ucontext_t, not ucontext32_t. */ 906 kmem_free(uc, sizeof(ucontext_t)); 907 userret(l); 908 } 909 910 int 911 check_sigcontext32(struct lwp *l, const struct netbsd32_sigcontext *scp) 912 { 913 struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap; 914 struct trapframe *tf; 915 struct pcb *pcb; 916 917 tf = l->l_md.md_regs; 918 pcb = lwp_getpcb(curlwp); 919 920 if (((scp->sc_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) 921 return EINVAL; 922 923 if (__predict_false(pmap->pm_ldt != NULL)) { 924 /* Allow unfamiliar segment register values (USER_LDT). */ 925 if (!USERMODE(scp->sc_cs)) 926 return EINVAL; 927 } else { 928 if (!VALID_USER_CSEL32(scp->sc_cs)) 929 return EINVAL; 930 if (scp->sc_fs != 0 && !VALID_USER_DSEL32(scp->sc_fs) && 931 !(VALID_USER_FSEL32(scp->sc_fs) && pcb->pcb_fs != 0)) 932 return EINVAL; 933 if (scp->sc_gs != 0 && !VALID_USER_DSEL32(scp->sc_gs) && 934 !(VALID_USER_GSEL32(scp->sc_gs) && pcb->pcb_gs != 0)) 935 return EINVAL; 936 if (scp->sc_es != 0 && !VALID_USER_DSEL32(scp->sc_es)) 937 return EINVAL; 938 if (!VALID_USER_DSEL32(scp->sc_ds) || 939 !VALID_USER_DSEL32(scp->sc_ss)) 940 return EINVAL; 941 } 942 943 if (scp->sc_eip >= VM_MAXUSER_ADDRESS32) 944 return EINVAL; 945 946 return 0; 947 } 948 949 int 950 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp) 951 { 952 struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap; 953 const __greg32_t *gr; 954 struct trapframe *tf; 955 struct pcb *pcb; 956 957 gr = mcp->__gregs; 958 tf = l->l_md.md_regs; 959 pcb = lwp_getpcb(l); 960 961 if (((gr[_REG32_EFL] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) 962 return EINVAL; 963 964 if (__predict_false(pmap->pm_ldt != NULL)) { 965 /* Allow unfamiliar segment register values (USER_LDT). */ 966 if (!USERMODE(gr[_REG32_CS])) 967 return EINVAL; 968 } else { 969 if (!VALID_USER_CSEL32(gr[_REG32_CS])) 970 return EINVAL; 971 if (gr[_REG32_FS] != 0 && !VALID_USER_DSEL32(gr[_REG32_FS]) && 972 !(VALID_USER_FSEL32(gr[_REG32_FS]) && pcb->pcb_fs != 0)) 973 return EINVAL; 974 if (gr[_REG32_GS] != 0 && !VALID_USER_DSEL32(gr[_REG32_GS]) && 975 !(VALID_USER_GSEL32(gr[_REG32_GS]) && pcb->pcb_gs != 0)) 976 return EINVAL; 977 if (gr[_REG32_ES] != 0 && !VALID_USER_DSEL32(gr[_REG32_ES])) 978 return EINVAL; 979 if (!VALID_USER_DSEL32(gr[_REG32_DS]) || 980 !VALID_USER_DSEL32(gr[_REG32_SS])) 981 return EINVAL; 982 } 983 984 if (gr[_REG32_EIP] >= VM_MAXUSER_ADDRESS32) 985 return EINVAL; 986 987 return 0; 988 } 989 990 static int 991 cpu_mcontext32from64_validate(struct lwp *l, const struct reg *regp) 992 { 993 mcontext32_t mc; 994 __greg32_t *gr32 = mc.__gregs; 995 const __greg_t *gr = regp->regs; 996 997 memset(&mc, 0, sizeof(mc)); 998 gr32[_REG32_EFL] = gr[_REG_RFLAGS]; 999 gr32[_REG32_EIP] = gr[_REG_RIP]; 1000 gr32[_REG32_CS] = gr[_REG_CS]; 1001 gr32[_REG32_DS] = gr[_REG_DS]; 1002 gr32[_REG32_ES] = gr[_REG_ES]; 1003 gr32[_REG32_FS] = gr[_REG_FS]; 1004 gr32[_REG32_GS] = gr[_REG_GS]; 1005 gr32[_REG32_SS] = gr[_REG_SS]; 1006 return cpu_mcontext32_validate(l, &mc); 1007 } 1008 1009 vaddr_t 1010 netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t sz, 1011 int topdown) 1012 { 1013 if (topdown) 1014 return VM_DEFAULT_ADDRESS32_TOPDOWN(base, sz); 1015 else 1016 return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, sz); 1017 } 1018 1019 static const char * 1020 netbsd32_machine32(void) 1021 { 1022 1023 return machine32; 1024 } 1025 1026 void 1027 netbsd32_machdep_md_init(void) 1028 { 1029 1030 MODULE_HOOK_SET(netbsd32_machine32_hook, netbsd32_machine32); 1031 MODULE_HOOK_SET(netbsd32_reg_validate_hook, 1032 cpu_mcontext32from64_validate); 1033 MODULE_HOOK_SET(netbsd32_process_doxmmregs_hook, 1034 netbsd32_process_doxmmregs); 1035 } 1036 1037 void 1038 netbsd32_machdep_md_fini(void) 1039 { 1040 1041 MODULE_HOOK_UNSET(netbsd32_machine32_hook); 1042 MODULE_HOOK_UNSET(netbsd32_reg_validate_hook); 1043 MODULE_HOOK_UNSET(netbsd32_process_doxmmregs_hook); 1044 } 1045