ia32_sysvec.c revision 115006
1/*- 2 * Copyright (c) 2002 Doug Rabson 3 * Copyright (c) 2003 Peter Wemm 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD: head/sys/compat/ia32/ia32_sysvec.c 115006 2003-05-15 00:23:40Z peter $ 28 */ 29 30#include "opt_compat.h" 31 32#define __ELF_WORD_SIZE 32 33 34#include <sys/param.h> 35#include <sys/exec.h> 36#include <sys/fcntl.h> 37#include <sys/imgact.h> 38#include <sys/kernel.h> 39#include <sys/lock.h> 40#include <sys/malloc.h> 41#include <sys/mutex.h> 42#include <sys/mman.h> 43#include <sys/namei.h> 44#include <sys/pioctl.h> 45#include <sys/proc.h> 46#include <sys/procfs.h> 47#include <sys/resourcevar.h> 48#include <sys/systm.h> 49#include <sys/signalvar.h> 50#include <sys/stat.h> 51#include <sys/sx.h> 52#include <sys/syscall.h> 53#include <sys/sysctl.h> 54#include <sys/sysent.h> 55#include <sys/vnode.h> 56#include <sys/imgact_elf.h> 57 58#include <vm/vm.h> 59#include <vm/vm_kern.h> 60#include <vm/vm_param.h> 61#include <vm/pmap.h> 62#include <vm/vm_map.h> 63#include <vm/vm_object.h> 64#include <vm/vm_extern.h> 65 66#include <amd64/ia32/ia32_util.h> 67#include <amd64/ia32/ia32_proto.h> 68#include <amd64/ia32/ia32_signal.h> 69#include <machine/psl.h> 70#include <machine/segments.h> 71#include <machine/specialreg.h> 72#include <machine/frame.h> 73#include <machine/md_var.h> 74#include <machine/pcb.h> 75#include <machine/cpufunc.h> 76 77static register_t *ia32_copyout_strings(struct image_params *imgp); 78static void ia32_setregs(struct thread *td, u_long entry, u_long stack, 79 u_long ps_strings); 80 81extern struct sysent ia32_sysent[]; 82 83struct sysentvec ia32_freebsd_sysvec = { 84 SYS_MAXSYSCALL, 85 ia32_sysent, 86 0, 87 0, 88 NULL, 89 0, 90 NULL, 91 NULL, 92 elf32_freebsd_fixup, 93 ia32_sendsig, 94 ia32_sigcode, 95 &sz_ia32_sigcode, 96 NULL, 97 "FreeBSD ELF32", 98 elf32_coredump, 99 NULL, 100 MINSIGSTKSZ, 101 PAGE_SIZE, 102 0, 103 USRSTACK, 104 USRSTACK, 105 PS_STRINGS, 106 VM_PROT_ALL, 107 ia32_copyout_strings, 108 ia32_setregs 109}; 110 111 112 113static Elf32_Brandinfo ia32_brand_info = { 114 ELFOSABI_FREEBSD, 115 EM_386, 116 "FreeBSD", 117 "/compat/ia32", 118 "/usr/libexec/ld-elf.so.1", 119 &ia32_freebsd_sysvec 120 }; 121 122SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY, 123 (sysinit_cfunc_t) elf32_insert_brand_entry, 124 &ia32_brand_info); 125 126extern int _ucode32sel, _udatasel; 127 128static register_t * 129ia32_copyout_strings(struct image_params *imgp) 130{ 131 int argc, envc; 132 u_int32_t *vectp; 133 char *stringp, *destp; 134 u_int32_t *stack_base; 135 struct ia32_ps_strings *arginfo; 136 int szsigcode; 137 138 /* 139 * Calculate string base and vector table pointers. 140 * Also deal with signal trampoline code for this exec type. 141 */ 142 arginfo = (struct ia32_ps_strings *)PS_STRINGS; 143 szsigcode = *(imgp->proc->p_sysent->sv_szsigcode); 144 destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE - 145 roundup((ARG_MAX - imgp->stringspace), sizeof(char *)); 146 147 /* 148 * install sigcode 149 */ 150 if (szsigcode) 151 copyout(imgp->proc->p_sysent->sv_sigcode, 152 ((caddr_t)arginfo - szsigcode), szsigcode); 153 154 /* 155 * If we have a valid auxargs ptr, prepare some room 156 * on the stack. 157 */ 158 if (imgp->auxargs) { 159 /* 160 * 'AT_COUNT*2' is size for the ELF Auxargs data. This is for 161 * lower compatibility. 162 */ 163 imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size 164 : (AT_COUNT * 2); 165 /* 166 * The '+ 2' is for the null pointers at the end of each of 167 * the arg and env vector sets,and imgp->auxarg_size is room 168 * for argument of Runtime loader. 169 */ 170 vectp = (u_int32_t *) (destp - (imgp->argc + imgp->envc + 2 + 171 imgp->auxarg_size) * sizeof(u_int32_t)); 172 173 } else 174 /* 175 * The '+ 2' is for the null pointers at the end of each of 176 * the arg and env vector sets 177 */ 178 vectp = (u_int32_t *) 179 (destp - (imgp->argc + imgp->envc + 2) * sizeof(u_int32_t)); 180 181 /* 182 * vectp also becomes our initial stack base 183 */ 184 stack_base = vectp; 185 186 stringp = imgp->stringbase; 187 argc = imgp->argc; 188 envc = imgp->envc; 189 /* 190 * Copy out strings - arguments and environment. 191 */ 192 copyout(stringp, destp, ARG_MAX - imgp->stringspace); 193 194 /* 195 * Fill in "ps_strings" struct for ps, w, etc. 196 */ 197 suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp); 198 suword32(&arginfo->ps_nargvstr, argc); 199 200 /* 201 * Fill in argument portion of vector table. 202 */ 203 for (; argc > 0; --argc) { 204 suword32(vectp++, (u_int32_t)(intptr_t)destp); 205 while (*stringp++ != 0) 206 destp++; 207 destp++; 208 } 209 210 /* a null vector table pointer separates the argp's from the envp's */ 211 suword32(vectp++, 0); 212 213 suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp); 214 suword32(&arginfo->ps_nenvstr, envc); 215 216 /* 217 * Fill in environment portion of vector table. 218 */ 219 for (; envc > 0; --envc) { 220 suword32(vectp++, (u_int32_t)(intptr_t)destp); 221 while (*stringp++ != 0) 222 destp++; 223 destp++; 224 } 225 226 /* end of vector table is a null pointer */ 227 suword32(vectp, 0); 228 229 return ((register_t *)stack_base); 230} 231 232/* 233 * Clear registers on exec 234 */ 235void 236ia32_setregs(td, entry, stack, ps_strings) 237 struct thread *td; 238 u_long entry; 239 u_long stack; 240 u_long ps_strings; 241{ 242 struct trapframe *regs = td->td_frame; 243 struct pcb *pcb = td->td_pcb; 244 245 wrmsr(MSR_FSBASE, 0); 246 wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */ 247 pcb->pcb_fsbase = 0; 248 pcb->pcb_gsbase = 0; 249 load_ds(_udatasel); 250 load_es(_udatasel); 251 load_fs(_udatasel); 252 load_gs(_udatasel); 253 pcb->pcb_ds = _udatasel; 254 pcb->pcb_es = _udatasel; 255 pcb->pcb_fs = _udatasel; 256 pcb->pcb_gs = _udatasel; 257 258 bzero((char *)regs, sizeof(struct trapframe)); 259 regs->tf_rip = entry; 260 regs->tf_rsp = stack; 261 regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T); 262 regs->tf_ss = _udatasel; 263 regs->tf_cs = _ucode32sel; 264 regs->tf_rbx = ps_strings; 265 266 /* 267 * Arrange to trap the next npx or `fwait' instruction (see npx.c 268 * for why fwait must be trapped at least if there is an npx or an 269 * emulator). This is mainly to handle the case where npx0 is not 270 * configured, since the npx routines normally set up the trap 271 * otherwise. It should be done only at boot time, but doing it 272 * here allows modifying `npx_exists' for testing the emulator on 273 * systems with an npx. 274 */ 275 load_cr0(rcr0() | CR0_MP | CR0_TS); 276 277 fpstate_drop(td); 278 279 /* Return via doreti so that we can change to a different %cs */ 280 pcb->pcb_flags |= PCB_FULLCTX; 281 td->td_retval[1] = 0; 282} 283