1 /* $NetBSD: netbsd32_machdep.c,v 1.143 2026/07/10 15:11:25 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.143 2026/07/10 15:11:25 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 static int cpu_getmcontext32_xsave(struct lwp *, mcontext32_t *, unsigned *, 115 const struct xsave_header *, size_t, struct xsave_header *); 116 117 #ifdef EXEC_AOUT 118 /* 119 * There is no native a.out -- this function is required 120 * for i386 a.out emulation (COMPAT_NETBSD32+EXEC_AOUT). 121 */ 122 int 123 cpu_exec_aout_makecmds(struct lwp *p, struct exec_package *e) 124 { 125 126 return ENOEXEC; 127 } 128 #endif 129 130 void 131 netbsd32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) 132 { 133 struct pcb *pcb; 134 struct trapframe *tf; 135 struct proc *p = l->l_proc; 136 137 pcb = lwp_getpcb(l); 138 139 #if defined(USER_LDT) 140 pmap_ldt_cleanup(l); 141 #endif 142 143 netbsd32_adjust_limits(p); 144 145 fpu_clear(l, pack->ep_osversion >= 699002600 146 ? __NetBSD_NPXCW__ : __NetBSD_COMPAT_NPXCW__); 147 x86_dbregs_clear(l); 148 149 kpreempt_disable(); 150 pcb->pcb_flags = PCB_COMPAT32; 151 p->p_flag |= PK_32; 152 l->l_md.md_flags = MDL_COMPAT32; /* force iret not sysret */ 153 cpu_segregs32_zero(l); 154 cpu_fsgs_reload(l, LSEL(LUDATA32_SEL, SEL_UPL), 155 LSEL(LUDATA32_SEL, SEL_UPL)); 156 kpreempt_enable(); 157 158 tf = l->l_md.md_regs; 159 tf->tf_ds = LSEL(LUDATA32_SEL, SEL_UPL); 160 tf->tf_es = LSEL(LUDATA32_SEL, SEL_UPL); 161 tf->tf_rdi = 0; 162 tf->tf_rsi = 0; 163 tf->tf_rbp = 0; 164 tf->tf_rbx = (uint32_t)p->p_psstrp; 165 tf->tf_rdx = 0; 166 tf->tf_rcx = 0; 167 tf->tf_rax = 0; 168 tf->tf_rip = pack->ep_entry; 169 tf->tf_cs = LSEL(LUCODE32_SEL, SEL_UPL); 170 tf->tf_rflags = PSL_USERSET; 171 tf->tf_rsp = stack; 172 tf->tf_ss = LSEL(LUDATA32_SEL, SEL_UPL); 173 } 174 175 void 176 netbsd32_buildcontext(struct lwp *l, struct trapframe *tf, void *fp, 177 sig_t catcher, int onstack) 178 { 179 /* 180 * Build context to run handler in. 181 */ 182 tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL); 183 tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); 184 #if 0 185 tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL); 186 tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL); 187 #endif 188 189 /* Ensure FP state is sane. */ 190 fpu_sigreset(l); 191 192 tf->tf_rip = (uint64_t)catcher; 193 tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); 194 tf->tf_rflags &= ~PSL_CLEARSIG; 195 tf->tf_rsp = (uint64_t)fp; 196 tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); 197 198 /* Remember that we're now on the signal stack. */ 199 if (onstack) 200 l->l_sigstk.ss_flags |= SS_ONSTACK; 201 if ((vaddr_t)catcher >= VM_MAXUSER_ADDRESS32) { 202 /* 203 * process has given an invalid address for the 204 * handler. Stop it, but do not do it before so 205 * we can return the right info to userland (or in core dump) 206 */ 207 sigexit(l, SIGILL); 208 /* NOTREACHED */ 209 } 210 } 211 212 void 213 netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) 214 { 215 struct lwp *l = curlwp; 216 struct proc *p = l->l_proc; 217 struct sigacts *ps = p->p_sigacts; 218 int onstack, error; 219 int sig = ksi->ksi_signo; 220 struct netbsd32_sigframe_siginfo *fp, frame; 221 const struct sigaction *sa = &SIGACTION(p, sig); 222 sig_t catcher = sa->sa_handler; 223 struct trapframe *tf = l->l_md.md_regs; 224 stack_t * const ss = &l->l_sigstk; 225 const struct xsave_header *xsavebuf = NULL; 226 size_t xsavelen = 0; 227 struct xsave_header *user_xsave = NULL; 228 char *sp; 229 230 /* Do we need to jump onto the signal stack? */ 231 onstack = 232 (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && 233 (sa->sa_flags & SA_ONSTACK) != 0; 234 235 /* Allocate space for the signal handler context. */ 236 if (onstack) { 237 KASSERT(ss->ss_size >= MINSIGSTKSZ); 238 sp = (char *)ss->ss_sp + ss->ss_size; 239 } else { 240 sp = (char *)tf->tf_rsp; 241 } 242 243 /* 244 * The maximum amount of space we might use, including padding 245 * for alignment, had better fit in MINSIGSTKSZ. 246 * 247 * If this changes because you have increased XSAVE_MAX_BYTES, 248 * you need to work out the ABI change for MINSIGSTKSZ. 249 */ 250 __CTASSERT(STACK_ALIGNBYTES32 + 251 sizeof(struct netbsd32_sigframe_siginfo) + 252 (XSAVE_ALIGN - 1) + XSAVE_MAX_BYTES <= MINSIGSTKSZ); 253 254 /* 255 * Find whether we need to allocate a separate XSAVE area, 256 * because the user program has used extended CPU state beyond 257 * the x87/SSE registers, or whether we can get by with just an 258 * FXSAVE area. 259 */ 260 if (process_xsave_needed_p(l)) { 261 process_read_xsave(l, &xsavebuf, &xsavelen); 262 KASSERT(xsavebuf != NULL); 263 KASSERT(xsavelen <= XSAVE_MAX_BYTES); 264 265 KASSERT(!onstack || sp >= (char *)ss->ss_sp); 266 KASSERT(!onstack || 267 (size_t)(sp - (char *)ss->ss_sp) >= xsavelen); 268 sp -= xsavelen; 269 270 KASSERT(!onstack || sp >= (char *)ss->ss_sp); 271 KASSERT(!onstack || (size_t)(sp - (char *)ss->ss_sp) >= 272 XSAVE_ALIGN - 1); 273 sp = (char *)((uintptr_t)sp & ~(XSAVE_ALIGN - 1)); 274 275 KASSERT(!onstack || sp >= (char *)ss->ss_sp); 276 KASSERT(((uintptr_t)sp & (XSAVE_ALIGN - 1)) == 0); 277 user_xsave = (void *)sp; 278 } 279 280 KASSERT(!onstack || sp >= (char *)ss->ss_sp); 281 KASSERT(!onstack || (size_t)(sp - (char *)ss->ss_sp) >= 282 STACK_ALIGNBYTES32 + sizeof(struct netbsd32_sigframe_siginfo)); 283 fp = (struct netbsd32_sigframe_siginfo *)sp; 284 fp--; 285 fp = (struct netbsd32_sigframe_siginfo *)((uintptr_t)fp & 286 ~STACK_ALIGNBYTES32); 287 KASSERT(!onstack || (char *)fp >= (char *)ss->ss_sp); 288 KASSERT(((uintptr_t)fp & STACK_ALIGNBYTES32) == 0); 289 290 /* Build stack frame for signal trampoline. */ 291 switch (ps->sa_sigdesc[sig].sd_vers) { 292 case __SIGTRAMP_SIGCODE_VERSION: /* handled by sendsig_sigcontext */ 293 case __SIGTRAMP_SIGCONTEXT_VERSION: /* handled by sendsig_sigcontext */ 294 default: /* unknown version */ 295 printf("nsendsig: bad version %d\n", 296 ps->sa_sigdesc[sig].sd_vers); 297 sigexit(l, SIGILL); 298 case __SIGTRAMP_SIGINFO_VERSION: 299 break; 300 } 301 302 memset(&frame, 0, sizeof(frame)); 303 frame.sf_ra = (uint32_t)(uintptr_t)ps->sa_sigdesc[sig].sd_tramp; 304 frame.sf_signum = sig; 305 frame.sf_sip = (uint32_t)(uintptr_t)&fp->sf_si; 306 frame.sf_ucp = (uint32_t)(uintptr_t)&fp->sf_uc; 307 netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info); 308 frame.sf_uc.uc_flags = _UC_SIGMASK; 309 frame.sf_uc.uc_sigmask = *mask; 310 frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink; 311 frame.sf_uc.uc_flags |= (ss->ss_flags & SS_ONSTACK) 312 ? _UC_SETSTACK : _UC_CLRSTACK; 313 sendsig_reset(l, sig); 314 315 mutex_exit(p->p_lock); 316 cpu_getmcontext32(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); 317 318 /* 319 * If we have to use XSAVE, copy out that area separately -- 320 * and be ready to bail if it failed. 321 */ 322 if (xsavebuf) { 323 error = cpu_getmcontext32_xsave(l, &frame.sf_uc.uc_mcontext, 324 &frame.sf_uc.uc_flags, xsavebuf, xsavelen, user_xsave); 325 if (error != 0) 326 goto relock; 327 } 328 329 error = copyout(&frame, fp, sizeof(frame)); 330 relock: 331 mutex_enter(p->p_lock); 332 333 if (error != 0) { 334 /* 335 * Process has trashed its stack; give it an illegal 336 * instruction to halt it in its tracks. 337 */ 338 sigexit(l, SIGILL); 339 /* NOTREACHED */ 340 } 341 342 netbsd32_buildcontext(l, tf, fp, catcher, onstack); 343 } 344 345 /* 346 * Dump the machine specific segment at the start of a core dump. 347 */ 348 struct md_core32 { 349 struct reg32 intreg; 350 struct fpreg32 freg; 351 }; 352 353 int 354 cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie, 355 struct core32 *chdr) 356 { 357 struct md_core32 md_core; 358 struct coreseg cseg; 359 int error; 360 361 if (iocookie == NULL) { 362 CORE_SETMAGIC(*chdr, COREMAGIC, MID_I386, 0); 363 chdr->c_hdrsize = ALIGN32(sizeof(*chdr)); 364 chdr->c_seghdrsize = ALIGN32(sizeof(cseg)); 365 chdr->c_cpusize = sizeof(md_core); 366 chdr->c_nseg++; 367 return 0; 368 } 369 370 /* Save integer registers. */ 371 error = netbsd32_process_read_regs(l, &md_core.intreg); 372 if (error) 373 return error; 374 375 /* Save floating point registers. */ 376 error = netbsd32_process_read_fpregs(l, &md_core.freg, NULL); 377 if (error) 378 return error; 379 380 CORE_SETMAGIC(cseg, CORESEGMAGIC, MID_I386, CORE_CPU); 381 cseg.c_addr = 0; 382 cseg.c_size = chdr->c_cpusize; 383 384 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &cseg, 385 chdr->c_seghdrsize), ENOSYS, error); 386 if (error) 387 return error; 388 389 MODULE_HOOK_CALL(coredump_write_hook, (iocookie, UIO_SYSSPACE, &md_core, 390 sizeof(md_core)), ENOSYS, error); 391 392 return error; 393 } 394 395 int 396 netbsd32_ptrace_translate_request(int req) 397 { 398 399 switch (req) 400 { 401 case 0 ... PT_FIRSTMACH - 1: return req; 402 case PT32_STEP: return PT_STEP; 403 case PT32_GETREGS: return PT_GETREGS; 404 case PT32_SETREGS: return PT_SETREGS; 405 case PT32_GETFPREGS: return PT_GETFPREGS; 406 case PT32_SETFPREGS: return PT_SETFPREGS; 407 case PT32_GETXMMREGS: return PT_GETXMMREGS; 408 case PT32_SETXMMREGS: return PT_SETXMMREGS; 409 case PT32_GETDBREGS: return PT_GETDBREGS; 410 case PT32_SETDBREGS: return PT_SETDBREGS; 411 case PT32_SETSTEP: return PT_SETSTEP; 412 case PT32_CLEARSTEP: return PT_CLEARSTEP; 413 case PT32_GETXSTATE: return PT_GETXSTATE; 414 case PT32_SETXSTATE: return PT_SETXSTATE; 415 default: return -1; 416 } 417 } 418 419 int 420 netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs) 421 { 422 struct trapframe *tf = l->l_md.md_regs; 423 424 /* XXX avoid sign extension problems with unknown upper bits? */ 425 regs->r_gs = tf->tf_gs & 0xffff; 426 regs->r_fs = tf->tf_fs & 0xffff; 427 regs->r_es = tf->tf_es & 0xffff; 428 regs->r_ds = tf->tf_ds & 0xffff; 429 regs->r_eflags = tf->tf_rflags; 430 regs->r_edi = tf->tf_rdi & 0xffffffff; 431 regs->r_esi = tf->tf_rsi & 0xffffffff; 432 regs->r_ebp = tf->tf_rbp & 0xffffffff; 433 regs->r_ebx = tf->tf_rbx & 0xffffffff; 434 regs->r_edx = tf->tf_rdx & 0xffffffff; 435 regs->r_ecx = tf->tf_rcx & 0xffffffff; 436 regs->r_eax = tf->tf_rax & 0xffffffff; 437 regs->r_eip = tf->tf_rip & 0xffffffff; 438 regs->r_cs = tf->tf_cs & 0xffff; 439 regs->r_esp = tf->tf_rsp & 0xffffffff; 440 regs->r_ss = tf->tf_ss & 0xffff; 441 442 return 0; 443 } 444 445 int 446 netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz) 447 { 448 449 __CTASSERT(sizeof(*regs) == sizeof(struct save87)); 450 process_read_fpregs_s87(l, (struct save87 *)regs); 451 return 0; 452 } 453 454 int 455 netbsd32_process_read_dbregs(struct lwp *l, struct dbreg32 *regs, size_t *sz) 456 { 457 struct dbreg regs64; 458 459 x86_dbregs_read(l, ®s64); 460 memset(regs, 0, sizeof(*regs)); 461 regs->dr[0] = regs64.dr[0] & 0xffffffff; 462 regs->dr[1] = regs64.dr[1] & 0xffffffff; 463 regs->dr[2] = regs64.dr[2] & 0xffffffff; 464 regs->dr[3] = regs64.dr[3] & 0xffffffff; 465 466 regs->dr[6] = regs64.dr[6] & 0xffffffff; 467 regs->dr[7] = regs64.dr[7] & 0xffffffff; 468 469 return 0; 470 } 471 472 int 473 netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs) 474 { 475 struct trapframe *tf; 476 struct pcb *pcb; 477 478 tf = l->l_md.md_regs; 479 pcb = lwp_getpcb(l); 480 481 /* 482 * Check for security violations. 483 */ 484 if (((regs->r_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) 485 return EINVAL; 486 if (!VALID_USER_CSEL32(regs->r_cs)) 487 return EINVAL; 488 if (regs->r_fs != 0 && !VALID_USER_DSEL32(regs->r_fs) && 489 !(VALID_USER_FSEL32(regs->r_fs) && pcb->pcb_fs != 0)) 490 return EINVAL; 491 if (regs->r_gs != 0 && !VALID_USER_DSEL32(regs->r_gs) && 492 !(VALID_USER_GSEL32(regs->r_gs) && pcb->pcb_gs != 0)) 493 return EINVAL; 494 if (regs->r_es != 0 && !VALID_USER_DSEL32(regs->r_es)) 495 return EINVAL; 496 if (!VALID_USER_DSEL32(regs->r_ds) || 497 !VALID_USER_DSEL32(regs->r_ss)) 498 return EINVAL; 499 if ((u_int)regs->r_eip >= VM_MAXUSER_ADDRESS32) 500 return EINVAL; 501 502 tf->tf_rax = regs->r_eax; 503 tf->tf_rcx = regs->r_ecx; 504 tf->tf_rdx = regs->r_edx; 505 tf->tf_rbx = regs->r_ebx; 506 tf->tf_rsp = regs->r_esp; 507 tf->tf_rbp = regs->r_ebp; 508 tf->tf_rsi = regs->r_esi; 509 tf->tf_rdi = regs->r_edi; 510 tf->tf_rip = regs->r_eip; 511 tf->tf_rflags = regs->r_eflags; 512 tf->tf_cs = regs->r_cs & 0xFFFF; 513 tf->tf_ss = regs->r_ss & 0xFFFF; 514 tf->tf_ds = regs->r_ds & 0xFFFF; 515 tf->tf_es = regs->r_es & 0xFFFF; 516 tf->tf_fs = regs->r_fs & 0xFFFF; 517 tf->tf_gs = regs->r_gs & 0xFFFF; 518 519 return 0; 520 } 521 522 int 523 netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs, 524 size_t sz) 525 { 526 527 __CTASSERT(sizeof(*regs) == sizeof(struct save87)); 528 process_write_fpregs_s87(l, (const struct save87 *)regs); 529 return 0; 530 } 531 532 int 533 netbsd32_process_write_dbregs(struct lwp *l, const struct dbreg32 *regs, 534 size_t sz) 535 { 536 size_t i; 537 struct dbreg regs64; 538 539 /* Check that DR0-DR3 contain user-space address */ 540 for (i = 0; i < X86_DBREGS; i++) { 541 if ((u_int)regs->dr[i] >= VM_MAXUSER_ADDRESS32) 542 return EINVAL; 543 } 544 545 if (regs->dr[7] & X86_DR7_GENERAL_DETECT_ENABLE) { 546 return EINVAL; 547 } 548 549 memset(®s64, 0, sizeof(regs64)); 550 551 regs64.dr[0] = (u_int)regs->dr[0]; 552 regs64.dr[1] = (u_int)regs->dr[1]; 553 regs64.dr[2] = (u_int)regs->dr[2]; 554 regs64.dr[3] = (u_int)regs->dr[3]; 555 556 regs64.dr[6] = (u_int)regs->dr[6]; 557 regs64.dr[7] = (u_int)regs->dr[7]; 558 559 x86_dbregs_write(l, ®s64); 560 return 0; 561 } 562 563 static int 564 netbsd32_process_doxmmregs(struct lwp *curl, struct lwp *l, void *addr, 565 bool write) 566 /* curl: tracer */ 567 /* l: traced */ 568 { 569 struct uio uio; 570 struct iovec iov; 571 struct vmspace *vm; 572 int error; 573 574 if ((curl->l_proc->p_flag & PK_32) == 0 || 575 (l->l_proc->p_flag & PK_32) == 0) 576 return EINVAL; 577 578 if (!process_machdep_validfpu(l->l_proc)) 579 return EINVAL; 580 581 error = proc_vmspace_getref(curl->l_proc, &vm); 582 if (error) 583 return error; 584 585 iov.iov_base = addr; 586 iov.iov_len = sizeof(struct xmmregs32); 587 uio.uio_iov = &iov; 588 uio.uio_iovcnt = 1; 589 uio.uio_offset = 0; 590 uio.uio_resid = sizeof(struct xmmregs32); 591 uio.uio_rw = write ? UIO_WRITE : UIO_READ; 592 uio.uio_vmspace = vm; 593 594 error = netbsd32_process_xmmregio(curl, l, &uio); 595 uvmspace_free(vm); 596 return error; 597 } 598 599 static int 600 netbsd32_process_xmmregio(struct lwp *curl, struct lwp *l, struct uio *uio) 601 /* curl: tracer */ 602 /* l: traced */ 603 { 604 struct xmmregs32 regs; 605 int error; 606 char *kv; 607 size_t kl; 608 609 kl = sizeof(regs); 610 kv = (char *)®s; 611 612 if (uio->uio_offset < 0 || uio->uio_offset > (off_t)kl) 613 return EINVAL; 614 615 kv += uio->uio_offset; 616 kl -= uio->uio_offset; 617 618 if (kl > uio->uio_resid) 619 kl = uio->uio_resid; 620 621 process_read_fpregs_xmm(l, ®s.fxstate); 622 error = uiomove(kv, kl, uio); 623 if (error == 0 && uio->uio_rw == UIO_WRITE) { 624 if (l->l_proc->p_stat != SSTOP) 625 error = EBUSY; 626 else 627 process_write_fpregs_xmm(l, ®s.fxstate); 628 } 629 630 uio->uio_offset = 0; 631 return error; 632 } 633 634 int 635 netbsd32_sysarch(struct lwp *l, const struct netbsd32_sysarch_args *uap, register_t *retval) 636 { 637 /* { 638 syscallarg(int) op; 639 syscallarg(netbsd32_voidp) parms; 640 } */ 641 int error; 642 643 switch (SCARG(uap, op)) { 644 case X86_IOPL: 645 error = x86_iopl(l, 646 NETBSD32PTR64(SCARG(uap, parms)), retval); 647 break; 648 case X86_GET_LDT: 649 error = x86_64_get_ldt32(l, 650 NETBSD32PTR64(SCARG(uap, parms)), retval); 651 break; 652 case X86_SET_LDT: 653 error = x86_64_set_ldt32(l, 654 NETBSD32PTR64(SCARG(uap, parms)), retval); 655 break; 656 case X86_GET_MTRR: 657 error = x86_64_get_mtrr32(l, 658 NETBSD32PTR64(SCARG(uap, parms)), retval); 659 break; 660 case X86_SET_MTRR: 661 error = x86_64_set_mtrr32(l, 662 NETBSD32PTR64(SCARG(uap, parms)), retval); 663 break; 664 default: 665 error = EINVAL; 666 break; 667 } 668 return error; 669 } 670 671 #ifdef USER_LDT 672 static int 673 x86_64_set_ldt32(struct lwp *l, void *args, register_t *retval) 674 { 675 struct x86_set_ldt_args32 ua32; 676 struct x86_set_ldt_args ua; 677 union descriptor *descv; 678 int error; 679 680 if ((error = copyin(args, &ua32, sizeof(ua32))) != 0) 681 return error; 682 683 ua.start = ua32.start; 684 ua.num = ua32.num; 685 686 if (ua.num < 0 || ua.num > MAX_USERLDT_SLOTS) 687 return EINVAL; 688 689 const size_t alloc_size = sizeof(*descv) * ua.num; 690 691 descv = kmem_alloc(alloc_size, KM_SLEEP); 692 error = copyin((void *)(uintptr_t)ua32.desc, descv, 693 sizeof(*descv) * ua.num); 694 if (error == 0) 695 error = x86_set_ldt1(l, &ua, descv); 696 *retval = ua.start; 697 698 kmem_free(descv, alloc_size); 699 return error; 700 } 701 702 static int 703 x86_64_get_ldt32(struct lwp *l, void *args, register_t *retval) 704 { 705 struct x86_get_ldt_args32 ua32; 706 struct x86_get_ldt_args ua; 707 union descriptor *cp; 708 int error; 709 710 if ((error = copyin(args, &ua32, sizeof(ua32))) != 0) 711 return error; 712 713 ua.start = ua32.start; 714 ua.num = ua32.num; 715 716 if (ua.num < 0 || ua.num > MAX_USERLDT_SLOTS) 717 return EINVAL; 718 719 const size_t alloc_size = ua.num * sizeof(union descriptor); 720 721 cp = kmem_alloc(alloc_size, KM_SLEEP); 722 error = x86_get_ldt1(l, &ua, cp); 723 *retval = ua.num; 724 if (error == 0) 725 error = copyout(cp, (void *)(uintptr_t)ua32.desc, 726 ua.num * sizeof(*cp)); 727 728 kmem_free(cp, alloc_size); 729 return error; 730 } 731 #endif 732 733 #ifdef MTRR 734 static int 735 x86_64_get_mtrr32(struct lwp *l, void *args, register_t *retval) 736 { 737 struct x86_64_get_mtrr_args32 args32; 738 int error, i; 739 int32_t n; 740 struct mtrr32 *m32p, m32; 741 struct mtrr *m64p, *mp; 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_GET, 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 if (args32.mtrrp == 0) { 759 n = (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX); 760 return copyout(&n, (void *)(uintptr_t)args32.n, sizeof(n)); 761 } 762 763 error = copyin((void *)(uintptr_t)args32.n, &n, sizeof(n)); 764 if (error != 0) 765 return error; 766 767 if (n <= 0 || n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX)) 768 return EINVAL; 769 770 size = n * sizeof(struct mtrr); 771 m64p = kmem_zalloc(size, KM_SLEEP); 772 error = mtrr_get(m64p, &n, l->l_proc, 0); 773 if (error != 0) 774 goto fail; 775 m32p = (struct mtrr32 *)(uintptr_t)args32.mtrrp; 776 mp = m64p; 777 for (i = 0; i < n; i++) { 778 m32.base = mp->base; 779 m32.len = mp->len; 780 m32.type = mp->type; 781 m32.flags = mp->flags; 782 m32.owner = mp->owner; 783 error = copyout(&m32, m32p, sizeof(m32)); 784 if (error != 0) 785 break; 786 mp++; 787 m32p++; 788 } 789 fail: 790 if (m64p != NULL) 791 kmem_free(m64p, size); 792 if (error != 0) 793 n = 0; 794 copyout(&n, (void *)(uintptr_t)args32.n, sizeof(n)); 795 return error; 796 } 797 798 static int 799 x86_64_set_mtrr32(struct lwp *l, void *args, register_t *retval) 800 { 801 struct x86_64_set_mtrr_args32 args32; 802 struct mtrr32 *m32p, m32; 803 struct mtrr *m64p, *mp; 804 int error, i; 805 int32_t n; 806 size_t size; 807 808 m64p = NULL; 809 810 if (mtrr_funcs == NULL) 811 return ENOSYS; 812 813 error = kauth_authorize_machdep(l->l_cred, KAUTH_MACHDEP_MTRR_SET, 814 NULL, NULL, NULL, NULL); 815 if (error) 816 return error; 817 818 error = copyin(args, &args32, sizeof(args32)); 819 if (error != 0) 820 return error; 821 822 error = copyin((void *)(uintptr_t)args32.n, &n, sizeof(n)); 823 if (error != 0) 824 return error; 825 826 if (n <= 0 || n > (MTRR_I686_NFIXED_SOFT + MTRR_I686_NVAR_MAX)) { 827 error = EINVAL; 828 goto fail; 829 } 830 831 size = n * sizeof(struct mtrr); 832 m64p = kmem_zalloc(size, KM_SLEEP); 833 m32p = (struct mtrr32 *)(uintptr_t)args32.mtrrp; 834 mp = m64p; 835 for (i = 0; i < n; i++) { 836 error = copyin(m32p, &m32, sizeof(m32)); 837 if (error != 0) 838 goto fail; 839 mp->base = m32.base; 840 mp->len = m32.len; 841 mp->type = m32.type; 842 mp->flags = m32.flags; 843 mp->owner = m32.owner; 844 m32p++; 845 mp++; 846 } 847 848 error = mtrr_set(m64p, &n, l->l_proc, 0); 849 fail: 850 if (m64p != NULL) 851 kmem_free(m64p, size); 852 if (error != 0) 853 n = 0; 854 copyout(&n, (void *)(uintptr_t)args32.n, sizeof(n)); 855 return error; 856 } 857 #endif 858 859 int 860 cpu_setmcontext32(struct lwp *l, const mcontext32_t *mcp, unsigned int flags) 861 { 862 struct trapframe *tf = l->l_md.md_regs; 863 const __greg32_t *gr = mcp->__gregs; 864 struct proc *p = l->l_proc; 865 struct xsave_header *xsavebuf = NULL; 866 size_t xsavelen = 0; 867 int error; 868 869 /* 870 * If there's an external XSAVE area, copy it in and validate 871 * it before we irreversibly modify the trapframe. 872 * 873 * We could check the length against the state components 874 * included, but we currently don't: if it's truncated, it will 875 * be as if the truncated part were zero-filled -- this is 876 * implemented in process_write_xsave, called a little below. 877 */ 878 if ((flags & _UC_XSAVE) != 0) { 879 const __greg32_t xsaveptr = 880 mcp->__fpregs.__fp_reg_set.__xsave.__xsaveptr; 881 882 xsavelen = mcp->__fpregs.__fp_reg_set.__xsave.__xsavelen; 883 error = process_verify_xsavelen(l, xsavelen); 884 if (error != 0) 885 goto out; 886 xsavebuf = kmem_alloc(xsavelen, KM_SLEEP); 887 error = copyin((const void *)(uintptr_t)xsaveptr, xsavebuf, 888 xsavelen); 889 if (error != 0) 890 goto out; 891 error = process_verify_xsave(l, xsavebuf, xsavelen); 892 if (error != 0) 893 goto out; 894 } 895 896 /* Restore register context, if any. */ 897 if ((flags & _UC_CPU) != 0) { 898 /* 899 * Check for security violations. 900 */ 901 error = cpu_mcontext32_validate(l, mcp); 902 if (error != 0) 903 return error; 904 905 cpu_fsgs_reload(l, gr[_REG32_FS], gr[_REG32_GS]); 906 tf->tf_es = gr[_REG32_ES] & 0xFFFF; 907 tf->tf_ds = gr[_REG32_DS] & 0xFFFF; 908 /* Only change the user-alterable part of eflags */ 909 tf->tf_rflags &= ~PSL_USER; 910 tf->tf_rflags |= (gr[_REG32_EFL] & PSL_USER); 911 tf->tf_rdi = gr[_REG32_EDI]; 912 tf->tf_rsi = gr[_REG32_ESI]; 913 tf->tf_rbp = gr[_REG32_EBP]; 914 tf->tf_rbx = gr[_REG32_EBX]; 915 tf->tf_rdx = gr[_REG32_EDX]; 916 tf->tf_rcx = gr[_REG32_ECX]; 917 tf->tf_rax = gr[_REG32_EAX]; 918 tf->tf_rip = gr[_REG32_EIP]; 919 tf->tf_cs = gr[_REG32_CS] & 0xFFFF; 920 tf->tf_rsp = gr[_REG32_UESP]; 921 tf->tf_ss = gr[_REG32_SS] & 0xFFFF; 922 } 923 924 if ((flags & _UC_TLSBASE) != 0) 925 lwp_setprivate(l, (void *)(uintptr_t)mcp->_mc_tlsbase); 926 927 /* Restore floating point register context, if any. */ 928 if ((flags & _UC_XSAVE) != 0) { 929 KASSERT(xsavebuf != NULL); 930 process_write_xsave(l, xsavebuf, xsavelen); 931 } else if ((flags & _UC_FPU) != 0) { 932 /* Assume fxsave context */ 933 process_write_fpregs_xmm(l, (const struct fxsave *) 934 &mcp->__fpregs.__fp_reg_set.__fp_xmm_state); 935 } 936 937 mutex_enter(p->p_lock); 938 if (flags & _UC_SETSTACK) 939 l->l_sigstk.ss_flags |= SS_ONSTACK; 940 if (flags & _UC_CLRSTACK) 941 l->l_sigstk.ss_flags &= ~SS_ONSTACK; 942 mutex_exit(p->p_lock); 943 944 /* Success! */ 945 error = 0; 946 947 out: if (xsavebuf) 948 kmem_free(xsavebuf, xsavelen); 949 return error; 950 } 951 952 void 953 cpu_getmcontext32(struct lwp *l, mcontext32_t *mcp, unsigned int *flags) 954 { 955 const struct trapframe *tf = l->l_md.md_regs; 956 __greg32_t *gr = mcp->__gregs; 957 __greg32_t ras_eip; 958 959 /* Save register context. */ 960 gr[_REG32_GS] = tf->tf_gs & 0xFFFF; 961 gr[_REG32_FS] = tf->tf_fs & 0xFFFF; 962 gr[_REG32_ES] = tf->tf_es & 0xFFFF; 963 gr[_REG32_DS] = tf->tf_ds & 0xFFFF; 964 gr[_REG32_EFL] = tf->tf_rflags; 965 gr[_REG32_EDI] = tf->tf_rdi; 966 gr[_REG32_ESI] = tf->tf_rsi; 967 gr[_REG32_EBP] = tf->tf_rbp; 968 gr[_REG32_EBX] = tf->tf_rbx; 969 gr[_REG32_EDX] = tf->tf_rdx; 970 gr[_REG32_ECX] = tf->tf_rcx; 971 gr[_REG32_EAX] = tf->tf_rax; 972 gr[_REG32_EIP] = tf->tf_rip; 973 gr[_REG32_CS] = tf->tf_cs & 0xFFFF; 974 gr[_REG32_ESP] = tf->tf_rsp; 975 gr[_REG32_UESP] = tf->tf_rsp; 976 gr[_REG32_SS] = tf->tf_ss & 0xFFFF; 977 gr[_REG32_TRAPNO] = tf->tf_trapno; 978 gr[_REG32_ERR] = tf->tf_err; 979 980 if ((ras_eip = (__greg32_t)(uintptr_t)ras_lookup(l->l_proc, 981 (void *) (uintptr_t)gr[_REG32_EIP])) != (__greg32_t)-1) 982 gr[_REG32_EIP] = ras_eip; 983 984 *flags |= _UC_CPU; 985 986 mcp->_mc_tlsbase = (uint32_t)(uintptr_t)l->l_private; 987 *flags |= _UC_TLSBASE; 988 989 /* Save floating point register context. */ 990 process_read_fpregs_xmm(l, (struct fxsave *) 991 &mcp->__fpregs.__fp_reg_set.__fp_xmm_state); 992 memset(&mcp->__fpregs.__fp_pad, 0, sizeof(mcp->__fpregs.__fp_pad)); 993 *flags |= _UC_FXSAVE | _UC_FPU; 994 } 995 996 /* 997 * cpu_getmcontext32_xsave(l, mcp, flags, xsavebuf, xsavelen, user_xsave) 998 * 999 * Copy out xsavebuf[0..xsavelen) to user_xsave, set mcp to point 1000 * there, and set _UC_XSAVE in flags. Caller must have already 1001 * used cpu_getmcontext32 to initialize mcp's FXSAVE area. 1002 * 1003 * May fail if the copyout fails. 1004 */ 1005 static int 1006 cpu_getmcontext32_xsave(struct lwp *l, mcontext32_t *mcp, unsigned int *flags, 1007 const struct xsave_header *xsavebuf, size_t xsavelen, 1008 struct xsave_header *user_xsave) 1009 { 1010 int error; 1011 1012 KASSERT(*flags & _UC_FPU); 1013 KASSERT(*flags & _UC_FXSAVE); 1014 KASSERT((uintptr_t)user_xsave == (__greg32_t)(uintptr_t)user_xsave); 1015 KASSERT(xsavelen == (__greg32_t)xsavelen); 1016 __CTASSERT(XSAVE_MAX_BYTES <= ~(__greg32_t)0); 1017 1018 /* 1019 * Copy out the XSAVE area. 1020 */ 1021 error = copyout(xsavebuf, user_xsave, xsavelen); 1022 if (error != 0) 1023 return error; 1024 1025 /* 1026 * Record a pointer to the real XSAVE area in the 1027 * architecturally unused bits mcontext_t's FXSAVE area. 1028 */ 1029 mcp->__fpregs.__fp_reg_set.__xsave.__xsaveptr = 1030 (__greg32_t)(uintptr_t)user_xsave; 1031 mcp->__fpregs.__fp_reg_set.__xsave.__xsavelen = 1032 (__greg32_t)xsavelen; 1033 1034 /* 1035 * Set the _UC_XSAVE flag so cpu_setmcontext will be able to 1036 * restore the full state from the XSAVE area. 1037 */ 1038 *flags |= _UC_XSAVE; 1039 1040 /* Success! */ 1041 return 0; 1042 } 1043 1044 void 1045 startlwp32(void *arg) 1046 { 1047 ucontext32_t *uc = arg; 1048 lwp_t *l = curlwp; 1049 int error __diagused; 1050 1051 error = cpu_setmcontext32(l, &uc->uc_mcontext, uc->uc_flags); 1052 KASSERT(error == 0); 1053 1054 /* Note: we are freeing ucontext_t, not ucontext32_t. */ 1055 kmem_free(uc, sizeof(ucontext_t)); 1056 userret(l); 1057 } 1058 1059 int 1060 check_sigcontext32(struct lwp *l, const struct netbsd32_sigcontext *scp) 1061 { 1062 struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap; 1063 struct trapframe *tf; 1064 struct pcb *pcb; 1065 1066 tf = l->l_md.md_regs; 1067 pcb = lwp_getpcb(curlwp); 1068 1069 if (((scp->sc_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) 1070 return EINVAL; 1071 1072 if (__predict_false(pmap->pm_ldt != NULL)) { 1073 /* Allow unfamiliar segment register values (USER_LDT). */ 1074 if (!USERMODE(scp->sc_cs)) 1075 return EINVAL; 1076 } else { 1077 if (!VALID_USER_CSEL32(scp->sc_cs)) 1078 return EINVAL; 1079 if (scp->sc_fs != 0 && !VALID_USER_DSEL32(scp->sc_fs) && 1080 !(VALID_USER_FSEL32(scp->sc_fs) && pcb->pcb_fs != 0)) 1081 return EINVAL; 1082 if (scp->sc_gs != 0 && !VALID_USER_DSEL32(scp->sc_gs) && 1083 !(VALID_USER_GSEL32(scp->sc_gs) && pcb->pcb_gs != 0)) 1084 return EINVAL; 1085 if (scp->sc_es != 0 && !VALID_USER_DSEL32(scp->sc_es)) 1086 return EINVAL; 1087 if (!VALID_USER_DSEL32(scp->sc_ds) || 1088 !VALID_USER_DSEL32(scp->sc_ss)) 1089 return EINVAL; 1090 } 1091 1092 if (scp->sc_eip >= VM_MAXUSER_ADDRESS32) 1093 return EINVAL; 1094 1095 return 0; 1096 } 1097 1098 int 1099 cpu_mcontext32_validate(struct lwp *l, const mcontext32_t *mcp) 1100 { 1101 struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap; 1102 const __greg32_t *gr; 1103 struct trapframe *tf; 1104 struct pcb *pcb; 1105 1106 gr = mcp->__gregs; 1107 tf = l->l_md.md_regs; 1108 pcb = lwp_getpcb(l); 1109 1110 if (((gr[_REG32_EFL] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0) 1111 return EINVAL; 1112 1113 if (__predict_false(pmap->pm_ldt != NULL)) { 1114 /* Allow unfamiliar segment register values (USER_LDT). */ 1115 if (!USERMODE(gr[_REG32_CS])) 1116 return EINVAL; 1117 } else { 1118 if (!VALID_USER_CSEL32(gr[_REG32_CS])) 1119 return EINVAL; 1120 if (gr[_REG32_FS] != 0 && !VALID_USER_DSEL32(gr[_REG32_FS]) && 1121 !(VALID_USER_FSEL32(gr[_REG32_FS]) && pcb->pcb_fs != 0)) 1122 return EINVAL; 1123 if (gr[_REG32_GS] != 0 && !VALID_USER_DSEL32(gr[_REG32_GS]) && 1124 !(VALID_USER_GSEL32(gr[_REG32_GS]) && pcb->pcb_gs != 0)) 1125 return EINVAL; 1126 if (gr[_REG32_ES] != 0 && !VALID_USER_DSEL32(gr[_REG32_ES])) 1127 return EINVAL; 1128 if (!VALID_USER_DSEL32(gr[_REG32_DS]) || 1129 !VALID_USER_DSEL32(gr[_REG32_SS])) 1130 return EINVAL; 1131 } 1132 1133 if (gr[_REG32_EIP] >= VM_MAXUSER_ADDRESS32) 1134 return EINVAL; 1135 1136 return 0; 1137 } 1138 1139 static int 1140 cpu_mcontext32from64_validate(struct lwp *l, const struct reg *regp) 1141 { 1142 mcontext32_t mc; 1143 __greg32_t *gr32 = mc.__gregs; 1144 const __greg_t *gr = regp->regs; 1145 1146 memset(&mc, 0, sizeof(mc)); 1147 gr32[_REG32_EFL] = gr[_REG_RFLAGS]; 1148 gr32[_REG32_EIP] = gr[_REG_RIP]; 1149 gr32[_REG32_CS] = gr[_REG_CS]; 1150 gr32[_REG32_DS] = gr[_REG_DS]; 1151 gr32[_REG32_ES] = gr[_REG_ES]; 1152 gr32[_REG32_FS] = gr[_REG_FS]; 1153 gr32[_REG32_GS] = gr[_REG_GS]; 1154 gr32[_REG32_SS] = gr[_REG_SS]; 1155 return cpu_mcontext32_validate(l, &mc); 1156 } 1157 1158 vaddr_t 1159 netbsd32_vm_default_addr(struct proc *p, vaddr_t base, vsize_t sz, 1160 int topdown) 1161 { 1162 if (topdown) 1163 return VM_DEFAULT_ADDRESS32_TOPDOWN(base, sz); 1164 else 1165 return VM_DEFAULT_ADDRESS32_BOTTOMUP(base, sz); 1166 } 1167 1168 static const char * 1169 netbsd32_machine32(void) 1170 { 1171 1172 return machine32; 1173 } 1174 1175 void 1176 netbsd32_machdep_md_init(void) 1177 { 1178 1179 MODULE_HOOK_SET(netbsd32_machine32_hook, netbsd32_machine32); 1180 MODULE_HOOK_SET(netbsd32_reg_validate_hook, 1181 cpu_mcontext32from64_validate); 1182 MODULE_HOOK_SET(netbsd32_process_doxmmregs_hook, 1183 netbsd32_process_doxmmregs); 1184 } 1185 1186 void 1187 netbsd32_machdep_md_fini(void) 1188 { 1189 1190 MODULE_HOOK_UNSET(netbsd32_machine32_hook); 1191 MODULE_HOOK_UNSET(netbsd32_reg_validate_hook); 1192 MODULE_HOOK_UNSET(netbsd32_process_doxmmregs_hook); 1193 } 1194