ia32_sysvec.c revision 120422
1100384Speter/*- 2100384Speter * Copyright (c) 2002 Doug Rabson 3114987Speter * Copyright (c) 2003 Peter Wemm 4100384Speter * All rights reserved. 5100384Speter * 6100384Speter * Redistribution and use in source and binary forms, with or without 7100384Speter * modification, are permitted provided that the following conditions 8100384Speter * are met: 9100384Speter * 1. Redistributions of source code must retain the above copyright 10100384Speter * notice, this list of conditions and the following disclaimer. 11100384Speter * 2. Redistributions in binary form must reproduce the above copyright 12100384Speter * notice, this list of conditions and the following disclaimer in the 13100384Speter * documentation and/or other materials provided with the distribution. 14100384Speter * 15100384Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16100384Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17100384Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18100384Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19100384Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20100384Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21100384Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22100384Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23100384Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24100384Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25100384Speter * SUCH DAMAGE. 26100384Speter */ 27100384Speter 28118031Sobrien#include <sys/cdefs.h> 29118031Sobrien__FBSDID("$FreeBSD: head/sys/compat/ia32/ia32_sysvec.c 120422 2003-09-25 01:10:26Z peter $"); 30118031Sobrien 31114987Speter#include "opt_compat.h" 32114987Speter 33100384Speter#define __ELF_WORD_SIZE 32 34100384Speter 35100384Speter#include <sys/param.h> 36100384Speter#include <sys/exec.h> 37100384Speter#include <sys/fcntl.h> 38100384Speter#include <sys/imgact.h> 39100384Speter#include <sys/kernel.h> 40100384Speter#include <sys/lock.h> 41100384Speter#include <sys/malloc.h> 42100384Speter#include <sys/mutex.h> 43100384Speter#include <sys/mman.h> 44100384Speter#include <sys/namei.h> 45100384Speter#include <sys/pioctl.h> 46100384Speter#include <sys/proc.h> 47100384Speter#include <sys/procfs.h> 48100384Speter#include <sys/resourcevar.h> 49100384Speter#include <sys/systm.h> 50100384Speter#include <sys/signalvar.h> 51100384Speter#include <sys/stat.h> 52100384Speter#include <sys/sx.h> 53100384Speter#include <sys/syscall.h> 54100384Speter#include <sys/sysctl.h> 55100384Speter#include <sys/sysent.h> 56100384Speter#include <sys/vnode.h> 57100384Speter#include <sys/imgact_elf.h> 58100384Speter 59100384Speter#include <vm/vm.h> 60100384Speter#include <vm/vm_kern.h> 61100384Speter#include <vm/vm_param.h> 62100384Speter#include <vm/pmap.h> 63100384Speter#include <vm/vm_map.h> 64100384Speter#include <vm/vm_object.h> 65100384Speter#include <vm/vm_extern.h> 66100384Speter 67119336Speter#include <compat/freebsd32/freebsd32_util.h> 68119336Speter#include <compat/freebsd32/freebsd32_proto.h> 69119336Speter#include <compat/ia32/ia32_signal.h> 70114987Speter#include <machine/psl.h> 71114987Speter#include <machine/segments.h> 72114987Speter#include <machine/specialreg.h> 73100384Speter#include <machine/frame.h> 74100384Speter#include <machine/md_var.h> 75114987Speter#include <machine/pcb.h> 76114987Speter#include <machine/cpufunc.h> 77100384Speter 78100384Speterstatic register_t *ia32_copyout_strings(struct image_params *imgp); 79100384Speterstatic void ia32_setregs(struct thread *td, u_long entry, u_long stack, 80100384Speter u_long ps_strings); 81120422Speterstatic void ia32_fixlimits(struct image_params *imgp); 82100384Speter 83119334Speterextern struct sysent freebsd32_sysent[]; 84100384Speter 85120422SpeterSYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW, 0, "ia32 mode"); 86120422Speter 87100384Speterstruct sysentvec ia32_freebsd_sysvec = { 88100384Speter SYS_MAXSYSCALL, 89119334Speter freebsd32_sysent, 90100384Speter 0, 91100384Speter 0, 92102808Sjake NULL, 93100384Speter 0, 94102808Sjake NULL, 95102808Sjake NULL, 96100384Speter elf32_freebsd_fixup, 97114987Speter ia32_sendsig, 98100384Speter ia32_sigcode, 99114987Speter &sz_ia32_sigcode, 100102808Sjake NULL, 101114987Speter "FreeBSD ELF32", 102100384Speter elf32_coredump, 103100384Speter NULL, 104100384Speter MINSIGSTKSZ, 105114987Speter PAGE_SIZE, 106102808Sjake 0, 107119336Speter FREEBSD32_USRSTACK, 108119336Speter FREEBSD32_USRSTACK, 109119336Speter FREEBSD32_PS_STRINGS, 110102808Sjake VM_PROT_ALL, 111100384Speter ia32_copyout_strings, 112120422Speter ia32_setregs, 113120422Speter ia32_fixlimits 114100384Speter}; 115100384Speter 116114987Speter 117119336Speterconst char freebsd32_emul_path[] = "/compat/ia32"; 118114987Speter 119100384Speterstatic Elf32_Brandinfo ia32_brand_info = { 120100384Speter ELFOSABI_FREEBSD, 121100384Speter EM_386, 122100384Speter "FreeBSD", 123100384Speter "/compat/ia32", 124100384Speter "/usr/libexec/ld-elf.so.1", 125100384Speter &ia32_freebsd_sysvec 126100384Speter }; 127100384Speter 128100384SpeterSYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, 129100384Speter (sysinit_cfunc_t) elf32_insert_brand_entry, 130100384Speter &ia32_brand_info); 131100384Speter 132119334Speter/* XXX may be freebsd32 MI */ 133100384Speterstatic register_t * 134100384Speteria32_copyout_strings(struct image_params *imgp) 135100384Speter{ 136100384Speter int argc, envc; 137100384Speter u_int32_t *vectp; 138100384Speter char *stringp, *destp; 139100384Speter u_int32_t *stack_base; 140119336Speter struct freebsd32_ps_strings *arginfo; 141100384Speter int szsigcode; 142100384Speter 143100384Speter /* 144100384Speter * Calculate string base and vector table pointers. 145100384Speter * Also deal with signal trampoline code for this exec type. 146100384Speter */ 147119336Speter arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS; 148100384Speter szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); 149100384Speter destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - 150100384Speter roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); 151100384Speter 152100384Speter /* 153100384Speter * install sigcode 154100384Speter */ 155100384Speter if (szsigcode) 156100384Speter copyout(imgp->proc->p_sysent->sv_sigcode, 157100384Speter ((caddr_t)arginfo - szsigcode), szsigcode); 158100384Speter 159100384Speter /* 160100384Speter * If we have a valid auxargs ptr, prepare some room 161100384Speter * on the stack. 162100384Speter */ 163100384Speter if (imgp->auxargs) { 164100384Speter /* 165100384Speter * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for 166100384Speter * lower compatibility. 167100384Speter */ 168100384Speter imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size 169100384Speter : (AT_COUNT * 2); 170100384Speter /* 171100384Speter * The '+ 2' is for the null pointers at the end of each of 172100384Speter * the arg and env vector sets,and imgp->auxarg_size is room 173100384Speter * for argument of Runtime loader. 174100384Speter */ 175100384Speter vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + 176100384Speter imgp->auxarg_size) * sizeof(u_int32_t)); 177100384Speter 178100384Speter } else 179100384Speter /* 180100384Speter * The '+ 2' is for the null pointers at the end of each of 181100384Speter * the arg and env vector sets 182100384Speter */ 183100384Speter vectp = (u_int32_t *) 184100384Speter (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); 185100384Speter 186100384Speter /* 187100384Speter * vectp also becomes our initial stack base 188100384Speter */ 189100384Speter stack_base = vectp; 190100384Speter 191100384Speter stringp = imgp->stringbase; 192100384Speter argc = imgp->argc; 193100384Speter envc = imgp->envc; 194100384Speter /* 195100384Speter * Copy out strings - arguments and environment. 196100384Speter */ 197100384Speter copyout(stringp, destp, ARG_MAX - imgp->stringspace); 198100384Speter 199100384Speter /* 200100384Speter * Fill in "ps_strings" struct for ps, w, etc. 201100384Speter */ 202100384Speter suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); 203100384Speter suword32(&arginfo->ps_nargvstr, argc); 204100384Speter 205100384Speter /* 206100384Speter * Fill in argument portion of vector table. 207100384Speter */ 208100384Speter for (; argc > 0; --argc) { 209100384Speter suword32(vectp++, (u_int32_t)(intptr_t)destp); 210100384Speter while (*stringp++ != 0) 211100384Speter destp++; 212100384Speter destp++; 213100384Speter } 214100384Speter 215100384Speter /* a null vector table pointer separates the argp's from the envp's */ 216100384Speter suword32(vectp++, 0); 217100384Speter 218100384Speter suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); 219100384Speter suword32(&arginfo->ps_nenvstr, envc); 220100384Speter 221100384Speter /* 222100384Speter * Fill in environment portion of vector table. 223100384Speter */ 224100384Speter for (; envc > 0; --envc) { 225100384Speter suword32(vectp++, (u_int32_t)(intptr_t)destp); 226100384Speter while (*stringp++ != 0) 227100384Speter destp++; 228100384Speter destp++; 229100384Speter } 230100384Speter 231100384Speter /* end of vector table is a null pointer */ 232100384Speter suword32(vectp, 0); 233100384Speter 234100384Speter return ((register_t *)stack_base); 235100384Speter} 236100384Speter 237114987Speter/* 238114987Speter * Clear registers on exec 239119334Speter * XXX backend MD 240114987Speter */ 241119334Speterextern int _ucode32sel, _udatasel; 242114987Spetervoid 243114987Speteria32_setregs(td, entry, stack, ps_strings) 244114987Speter struct thread *td; 245114987Speter u_long entry; 246114987Speter u_long stack; 247114987Speter u_long ps_strings; 248100384Speter{ 249114987Speter struct trapframe *regs = td->td_frame; 250114987Speter struct pcb *pcb = td->td_pcb; 251114987Speter 252114987Speter wrmsr(MSR_FSBASE, 0); 253114987Speter wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */ 254114987Speter pcb->pcb_fsbase = 0; 255114987Speter pcb->pcb_gsbase = 0; 256114987Speter load_ds(_udatasel); 257114987Speter load_es(_udatasel); 258114987Speter load_fs(_udatasel); 259115006Speter load_gs(_udatasel); 260114987Speter pcb->pcb_ds = _udatasel; 261114987Speter pcb->pcb_es = _udatasel; 262114987Speter pcb->pcb_fs = _udatasel; 263114987Speter pcb->pcb_gs = _udatasel; 264100384Speter 265114987Speter bzero((char *)regs, sizeof(struct trapframe)); 266114987Speter regs->tf_rip = entry; 267114987Speter regs->tf_rsp = stack; 268114987Speter regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 269114987Speter regs->tf_ss = _udatasel; 270114987Speter regs->tf_cs = _ucode32sel; 271114987Speter regs->tf_rbx = ps_strings; 272100384Speter 273100384Speter /* 274114987Speter * Arrange to trap the next npx or `fwait' instruction (see npx.c 275114987Speter * for why fwait must be trapped at least if there is an npx or an 276114987Speter * emulator). This is mainly to handle the case where npx0 is not 277114987Speter * configured, since the npx routines normally set up the trap 278114987Speter * otherwise. It should be done only at boot time, but doing it 279114987Speter * here allows modifying `npx_exists' for testing the emulator on 280114987Speter * systems with an npx. 281100384Speter */ 282114987Speter load_cr0(rcr0() | CR0_MP | CR0_TS); 283100384Speter 284114987Speter fpstate_drop(td); 285100384Speter 286114987Speter /* Return via doreti so that we can change to a different %cs */ 287114987Speter pcb->pcb_flags |= PCB_FULLCTX; 288100384Speter td->td_retval[1] = 0; 289100384Speter} 290120422Speter 291120422Speterstatic u_long ia32_maxdsiz = IA32_MAXDSIZ; 292120422SpeterSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxdsiz, CTLFLAG_RW, &ia32_maxdsiz, 0, ""); 293120422Speterstatic u_long ia32_maxssiz = IA32_MAXSSIZ; 294120422SpeterSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxssiz, CTLFLAG_RW, &ia32_maxssiz, 0, ""); 295120422Speterstatic u_long ia32_maxvmem = IA32_MAXVMEM; 296120422SpeterSYSCTL_ULONG(_compat_ia32, OID_AUTO, maxvmem, CTLFLAG_RW, &ia32_maxvmem, 0, ""); 297120422Speter 298120422Speterstatic void 299120422Speteria32_fixlimits(struct image_params *imgp) 300120422Speter{ 301120422Speter struct proc *p = imgp->proc; 302120422Speter 303120422Speter if (ia32_maxdsiz != 0) { 304120422Speter if (p->p_rlimit[RLIMIT_DATA].rlim_cur > ia32_maxdsiz || 305120422Speter p->p_rlimit[RLIMIT_DATA].rlim_max > ia32_maxdsiz) { 306120422Speter if (p->p_limit->p_refcnt > 1) { 307120422Speter p->p_limit->p_refcnt--; 308120422Speter p->p_limit = limcopy(p->p_limit); 309120422Speter } 310120422Speter if (p->p_rlimit[RLIMIT_DATA].rlim_cur > ia32_maxdsiz) 311120422Speter p->p_rlimit[RLIMIT_DATA].rlim_cur = 312120422Speter ia32_maxdsiz; 313120422Speter if (p->p_rlimit[RLIMIT_DATA].rlim_max > ia32_maxdsiz) 314120422Speter p->p_rlimit[RLIMIT_DATA].rlim_max = 315120422Speter ia32_maxdsiz; 316120422Speter } 317120422Speter } 318120422Speter if (ia32_maxssiz != 0) { 319120422Speter if (p->p_rlimit[RLIMIT_STACK].rlim_cur > ia32_maxssiz || 320120422Speter p->p_rlimit[RLIMIT_STACK].rlim_max > ia32_maxssiz) { 321120422Speter if (p->p_limit->p_refcnt > 1) { 322120422Speter p->p_limit->p_refcnt--; 323120422Speter p->p_limit = limcopy(p->p_limit); 324120422Speter } 325120422Speter if (p->p_rlimit[RLIMIT_STACK].rlim_cur > ia32_maxssiz) 326120422Speter p->p_rlimit[RLIMIT_STACK].rlim_cur = 327120422Speter ia32_maxssiz; 328120422Speter if (p->p_rlimit[RLIMIT_STACK].rlim_max > ia32_maxssiz) 329120422Speter p->p_rlimit[RLIMIT_STACK].rlim_max = 330120422Speter ia32_maxssiz; 331120422Speter } 332120422Speter } 333120422Speter if (ia32_maxvmem != 0) { 334120422Speter if (p->p_rlimit[RLIMIT_VMEM].rlim_cur > ia32_maxvmem || 335120422Speter p->p_rlimit[RLIMIT_VMEM].rlim_max > ia32_maxvmem) { 336120422Speter if (p->p_limit->p_refcnt > 1) { 337120422Speter p->p_limit->p_refcnt--; 338120422Speter p->p_limit = limcopy(p->p_limit); 339120422Speter } 340120422Speter if (p->p_rlimit[RLIMIT_VMEM].rlim_cur > ia32_maxvmem) 341120422Speter p->p_rlimit[RLIMIT_VMEM].rlim_cur = 342120422Speter ia32_maxvmem; 343120422Speter if (p->p_rlimit[RLIMIT_VMEM].rlim_max > ia32_maxvmem) 344120422Speter p->p_rlimit[RLIMIT_VMEM].rlim_max = 345120422Speter ia32_maxvmem; 346120422Speter } 347120422Speter } 348120422Speter} 349