1/*- 2 * Copyright (c) 2002 Doug Rabson 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 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#include <sys/sysproto.h> 58 59#include <machine/frame.h> 60#include <machine/md_var.h> 61#include <machine/pcb.h> 62 63#include <vm/vm.h> 64#include <vm/vm_kern.h> 65#include <vm/vm_param.h> 66#include <vm/pmap.h> 67#include <vm/vm_map.h> 68#include <vm/vm_object.h> 69#include <vm/vm_extern.h> 70 71#include <compat/freebsd32/freebsd32_signal.h> 72#include <compat/freebsd32/freebsd32_util.h> 73#include <compat/freebsd32/freebsd32_proto.h> 74#include <compat/ia32/ia32_signal.h> 75#include <x86/include/psl.h> 76#include <x86/include/segments.h> 77#include <x86/include/specialreg.h> 78 79char ia32_sigcode[] = { 80 0xff, 0x54, 0x24, 0x10, /* call *SIGF_HANDLER(%esp) */ 81 0x8d, 0x44, 0x24, 0x14, /* lea SIGF_UC(%esp),%eax */ 82 0x50, /* pushl %eax */ 83 0xf7, 0x40, 0x54, 0x00, 0x00, 0x02, 0x02, /* testl $PSL_VM,UC_EFLAGS(%ea 84x) */ 85 0x75, 0x03, /* jne 9f */ 86 0x8e, 0x68, 0x14, /* movl UC_GS(%eax),%gs */ 87 0xb8, 0x57, 0x01, 0x00, 0x00, /* 9: movl $SYS_sigreturn,%eax */ 88 0x50, /* pushl %eax */ 89 0xcd, 0x80, /* int $0x80 */ 90 0xeb, 0xfe, /* 0: jmp 0b */ 91 0 92}; 93int sz_ia32_sigcode = sizeof(ia32_sigcode); 94 95#ifdef COMPAT_43 96int 97ofreebsd32_sigreturn(struct thread *td, struct ofreebsd32_sigreturn_args *uap) 98{ 99 100 return (EOPNOTSUPP); 101} 102#endif 103 104/* 105 * Signal sending has not been implemented on ia64. This causes 106 * the sigtramp code to not understand the arguments and the application 107 * will generally crash if it tries to handle a signal. Calling 108 * sendsig() means that at least untrapped signals will work. 109 */ 110void 111ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask) 112{ 113 sendsig(catcher, ksi, mask); 114} 115 116#ifdef COMPAT_FREEBSD4 117int 118freebsd4_freebsd32_sigreturn(struct thread *td, struct freebsd4_freebsd32_sigreturn_args *uap) 119{ 120 return (sys_sigreturn(td, (struct sigreturn_args *)uap)); 121} 122#endif 123 124int 125freebsd32_sigreturn(struct thread *td, struct freebsd32_sigreturn_args *uap) 126{ 127 return (sys_sigreturn(td, (struct sigreturn_args *)uap)); 128} 129 130 131void 132ia32_setregs(struct thread *td, struct image_params *imgp, u_long stack) 133{ 134 struct trapframe *tf = td->td_frame; 135 vm_offset_t gdt, ldt; 136 u_int64_t codesel, datasel, ldtsel; 137 u_int64_t codeseg, dataseg, gdtseg, ldtseg; 138 struct segment_descriptor desc; 139 struct vmspace *vmspace = td->td_proc->p_vmspace; 140 struct sysentvec *sv; 141 142 sv = td->td_proc->p_sysent; 143 exec_setregs(td, imgp, stack); 144 145 /* Non-syscall frames are cleared by exec_setregs() */ 146 if (tf->tf_flags & FRAME_SYSCALL) { 147 bzero(&tf->tf_scratch, sizeof(tf->tf_scratch)); 148 bzero(&tf->tf_scratch_fp, sizeof(tf->tf_scratch_fp)); 149 } else 150 tf->tf_special.ndirty = 0; 151 152 tf->tf_special.psr |= IA64_PSR_IS; 153 tf->tf_special.sp = stack; 154 155 /* Point the RSE backstore to something harmless. */ 156 tf->tf_special.bspstore = (sv->sv_psstrings - sz_ia32_sigcode - 157 SPARE_USRSPACE + 15) & ~15; 158 159 codesel = LSEL(LUCODE_SEL, SEL_UPL); 160 datasel = LSEL(LUDATA_SEL, SEL_UPL); 161 ldtsel = GSEL(GLDT_SEL, SEL_UPL); 162 163 /* Setup ia32 segment registers. */ 164 tf->tf_scratch.gr16 = (datasel << 48) | (datasel << 32) | 165 (datasel << 16) | datasel; 166 tf->tf_scratch.gr17 = (ldtsel << 32) | (datasel << 16) | codesel; 167 168 /* 169 * Build the GDT and LDT. 170 */ 171 gdt = sv->sv_usrstack; 172 vm_map_find(&vmspace->vm_map, NULL, 0, &gdt, IA32_PAGE_SIZE << 1, 0, 173 VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0); 174 ldt = gdt + IA32_PAGE_SIZE; 175 176 desc.sd_lolimit = 8*NLDT-1; 177 desc.sd_lobase = ldt & 0xffffff; 178 desc.sd_type = SDT_SYSLDT; 179 desc.sd_dpl = SEL_UPL; 180 desc.sd_p = 1; 181 desc.sd_hilimit = 0; 182 desc.sd_def32 = 0; 183 desc.sd_gran = 0; 184 desc.sd_hibase = ldt >> 24; 185 copyout(&desc, (caddr_t) gdt + 8*GLDT_SEL, sizeof(desc)); 186 187 desc.sd_lolimit = ((sv->sv_usrstack >> 12) - 1) & 0xffff; 188 desc.sd_lobase = 0; 189 desc.sd_type = SDT_MEMERA; 190 desc.sd_dpl = SEL_UPL; 191 desc.sd_p = 1; 192 desc.sd_hilimit = ((sv->sv_usrstack >> 12) - 1) >> 16; 193 desc.sd_def32 = 1; 194 desc.sd_gran = 1; 195 desc.sd_hibase = 0; 196 copyout(&desc, (caddr_t) ldt + 8*LUCODE_SEL, sizeof(desc)); 197 desc.sd_type = SDT_MEMRWA; 198 copyout(&desc, (caddr_t) ldt + 8*LUDATA_SEL, sizeof(desc)); 199 200 codeseg = 0 /* base */ 201 + (((sv->sv_usrstack >> 12) - 1) << 32) /* limit */ 202 + ((long)SDT_MEMERA << 52) 203 + ((long)SEL_UPL << 57) 204 + (1L << 59) /* present */ 205 + (1L << 62) /* 32 bits */ 206 + (1L << 63); /* page granularity */ 207 dataseg = 0 /* base */ 208 + (((sv->sv_usrstack >> 12) - 1) << 32) /* limit */ 209 + ((long)SDT_MEMRWA << 52) 210 + ((long)SEL_UPL << 57) 211 + (1L << 59) /* present */ 212 + (1L << 62) /* 32 bits */ 213 + (1L << 63); /* page granularity */ 214 215 tf->tf_scratch.csd = codeseg; 216 tf->tf_scratch.ssd = dataseg; 217 tf->tf_scratch.gr24 = dataseg; /* ESD */ 218 tf->tf_scratch.gr27 = dataseg; /* DSD */ 219 tf->tf_scratch.gr28 = dataseg; /* FSD */ 220 tf->tf_scratch.gr29 = dataseg; /* GSD */ 221 222 gdtseg = gdt /* base */ 223 + ((8L*NGDT - 1) << 32) /* limit */ 224 + ((long)SDT_SYSNULL << 52) 225 + ((long)SEL_UPL << 57) 226 + (1L << 59) /* present */ 227 + (0L << 62) /* 16 bits */ 228 + (0L << 63); /* byte granularity */ 229 ldtseg = ldt /* base */ 230 + ((8L*NLDT - 1) << 32) /* limit */ 231 + ((long)SDT_SYSLDT << 52) 232 + ((long)SEL_UPL << 57) 233 + (1L << 59) /* present */ 234 + (0L << 62) /* 16 bits */ 235 + (0L << 63); /* byte granularity */ 236 237 tf->tf_scratch.gr30 = ldtseg; /* LDTD */ 238 tf->tf_scratch.gr31 = gdtseg; /* GDTD */ 239 240 /* Set ia32 control registers on this processor. */ 241 ia64_set_cflg(CR0_PE | CR0_PG | ((long)(CR4_XMM | CR4_FXSR) << 32)); 242 ia64_set_eflag(PSL_USER); 243 244 /* PS_STRINGS value for BSD/OS binaries. It is 0 for non-BSD/OS. */ 245 tf->tf_scratch.gr11 = td->td_proc->p_sysent->sv_psstrings; 246 247 /* 248 * XXX - Linux emulator 249 * Make sure sure edx is 0x0 on entry. Linux binaries depend 250 * on it. 251 */ 252 td->td_retval[1] = 0; 253} 254 255void 256ia32_restorectx(struct pcb *pcb) 257{ 258 259 ia64_set_cflg(pcb->pcb_ia32_cflg); 260 ia64_set_eflag(pcb->pcb_ia32_eflag); 261 ia64_set_fcr(pcb->pcb_ia32_fcr); 262 ia64_set_fdr(pcb->pcb_ia32_fdr); 263 ia64_set_fir(pcb->pcb_ia32_fir); 264 ia64_set_fsr(pcb->pcb_ia32_fsr); 265} 266 267void 268ia32_savectx(struct pcb *pcb) 269{ 270 271 pcb->pcb_ia32_cflg = ia64_get_cflg(); 272 pcb->pcb_ia32_eflag = ia64_get_eflag(); 273 pcb->pcb_ia32_fcr = ia64_get_fcr(); 274 pcb->pcb_ia32_fdr = ia64_get_fdr(); 275 pcb->pcb_ia32_fir = ia64_get_fir(); 276 pcb->pcb_ia32_fsr = ia64_get_fsr(); 277} 278 279int 280freebsd32_getcontext(struct thread *td, struct freebsd32_getcontext_args *uap) 281{ 282 283 return (nosys(td, NULL)); 284} 285 286int 287freebsd32_setcontext(struct thread *td, struct freebsd32_setcontext_args *uap) 288{ 289 290 return (nosys(td, NULL)); 291} 292 293int 294freebsd32_swapcontext(struct thread *td, struct freebsd32_swapcontext_args *uap) 295{ 296 297 return (nosys(td, NULL)); 298} 299