Home | History | Annotate | Line # | Download | only in amd64
      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, &regs64);
    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(&regs64, 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, &regs64);
    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 *)&regs;
    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, &regs.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, &regs.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