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