svr4_machdep.c revision 51793
1/* 2 * Copyright (c) 1998 Mark Newton 3 * Copyright (c) 1994 Christos Zoulas 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 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: head/sys/i386/svr4/svr4_machdep.c 51793 1999-09-29 15:12:18Z marcel $ 29 */ 30 31#include <sys/types.h> 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/namei.h> 35#include <sys/proc.h> 36#include <sys/exec.h> 37#include <sys/lock.h> 38#include <vm/vm.h> 39#include <vm/vm_kern.h> 40#include <vm/vm_param.h> 41#include <vm/pmap.h> 42#include <vm/vm_map.h> 43#include <vm/vm_prot.h> 44#include <vm/vm_extern.h> 45#include <sys/user.h> 46#include <sys/filedesc.h> 47#include <sys/kernel.h> 48#include <sys/signal.h> 49#include <sys/signalvar.h> 50#include <sys/malloc.h> 51#include <sys/mount.h> 52#include <sys/sysproto.h> 53#include <sys/elf32.h> 54 55#include <machine/cpu.h> 56#include <machine/cpufunc.h> 57#include <machine/psl.h> 58#include <machine/reg.h> 59#include <machine/specialreg.h> 60#include <machine/sysarch.h> 61#include <machine/vm86.h> 62#include <machine/vmparam.h> 63 64#include <svr4/svr4.h> 65#include <svr4/svr4_types.h> 66#include <svr4/svr4_signal.h> 67#include <i386/svr4/svr4_machdep.h> 68#include <svr4/svr4_ucontext.h> 69#include <svr4/svr4_proto.h> 70#include <svr4/svr4_util.h> 71#include <svr4/svr4_exec.h> 72 73#undef sigcode 74#undef szsigcode 75 76extern int svr4_szsigcode; 77extern char svr4_sigcode[]; 78extern int _udatasel, _ucodesel; 79 80static void svr4_getsiginfo __P((union svr4_siginfo *, int, u_long, caddr_t)); 81 82#if !defined(__NetBSD__) 83 /* taken from /sys/arch/i386/include/psl.h on NetBSD-1.3 */ 84# define PSL_MBZ 0xffc08028 85# define PSL_USERSTATIC (PSL_USER | PSL_MBZ | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP) 86# define USERMODE(c, f) (ISPL(c) == SEL_UPL) 87#endif 88 89#if defined(__NetBSD__) 90void 91svr4_setregs(p, epp, stack) 92 struct proc *p; 93 struct exec_package *epp; 94 u_long stack; 95{ 96 register struct pcb *pcb = &p->p_addr->u_pcb; 97 98 pcb->pcb_savefpu.sv_env.en_cw = __SVR4_NPXCW__; 99 setregs(p, epp, stack, 0UL); 100} 101#endif /* __NetBSD__ */ 102 103void 104svr4_getcontext(p, uc, mask, oonstack) 105 struct proc *p; 106 struct svr4_ucontext *uc; 107 sigset_t *mask; 108 int oonstack; 109{ 110 struct trapframe *tf = p->p_md.md_regs; 111 svr4_greg_t *r = uc->uc_mcontext.greg; 112 struct svr4_sigaltstack *s = &uc->uc_stack; 113#ifdef DONE_MORE_SIGALTSTACK_WORK 114 struct sigacts *psp = p->p_sigacts; 115 struct sigaltstack *sf = &psp->ps_sigstk; 116#endif 117 118 memset(uc, 0, sizeof(struct svr4_ucontext)); 119 120 uc->uc_link = p->p_emuldata; 121 /* 122 * Set the general purpose registers 123 */ 124#ifdef VM86 125 if (tf->tf_eflags & PSL_VM) { 126 r[SVR4_X86_GS] = tf->tf_vm86_gs; 127 r[SVR4_X86_FS] = tf->tf_vm86_fs; 128 r[SVR4_X86_ES] = tf->tf_vm86_es; 129 r[SVR4_X86_DS] = tf->tf_vm86_ds; 130 r[SVR4_X86_EFL] = get_vflags(p); 131 } else 132#endif 133 { 134#if defined(__NetBSD__) 135 __asm("movl %%gs,%w0" : "=r" (r[SVR4_X86_GS])); 136 __asm("movl %%fs,%w0" : "=r" (r[SVR4_X86_FS])); 137#else 138 r[SVR4_X86_GS] = rgs(); 139 r[SVR4_X86_FS] = tf->tf_fs; 140#endif 141 r[SVR4_X86_ES] = tf->tf_es; 142 r[SVR4_X86_DS] = tf->tf_ds; 143 r[SVR4_X86_EFL] = tf->tf_eflags; 144 } 145 r[SVR4_X86_EDI] = tf->tf_edi; 146 r[SVR4_X86_ESI] = tf->tf_esi; 147 r[SVR4_X86_EBP] = tf->tf_ebp; 148 r[SVR4_X86_ESP] = tf->tf_esp; 149 r[SVR4_X86_EBX] = tf->tf_ebx; 150 r[SVR4_X86_EDX] = tf->tf_edx; 151 r[SVR4_X86_ECX] = tf->tf_ecx; 152 r[SVR4_X86_EAX] = tf->tf_eax; 153 r[SVR4_X86_TRAPNO] = tf->tf_trapno; 154 r[SVR4_X86_ERR] = tf->tf_err; 155 r[SVR4_X86_EIP] = tf->tf_eip; 156 r[SVR4_X86_CS] = tf->tf_cs; 157 r[SVR4_X86_UESP] = 0; 158 r[SVR4_X86_SS] = tf->tf_ss; 159 160 /* 161 * Set the signal stack 162 */ 163#if DONE_MORE_SIGALTSTACK_WORK 164 bsd_to_svr4_sigaltstack(sf, s); 165#else 166 s->ss_sp = (void *)(((u_long) tf->tf_esp) & ~(16384 - 1)); 167 s->ss_size = 16384; 168 s->ss_flags = 0; 169#endif 170 171 /* 172 * Set the signal mask 173 */ 174 bsd_to_svr4_sigset(mask, &uc->uc_sigmask); 175 176 /* 177 * Set the flags 178 */ 179 uc->uc_flags = SVR4_UC_STACK|SVR4_UC_SIGMASK|SVR4_UC_CPU; 180} 181 182 183/* 184 * Set to ucontext specified. 185 * has been taken. Reset signal mask and 186 * stack state from context. 187 * Return to previous pc and psl as specified by 188 * context left by sendsig. Check carefully to 189 * make sure that the user has not modified the 190 * psl to gain improper privileges or to cause 191 * a machine fault. 192 */ 193int 194svr4_setcontext(p, uc) 195 struct proc *p; 196 struct svr4_ucontext *uc; 197{ 198 struct sigacts *psp = p->p_sigacts; 199 register struct trapframe *tf; 200 svr4_greg_t *r = uc->uc_mcontext.greg; 201 struct svr4_sigaltstack *s = &uc->uc_stack; 202 struct sigaltstack *sf = &psp->ps_sigstk; 203 sigset_t mask; 204 205 /* 206 * XXX: 207 * Should we check the value of flags to determine what to restore? 208 * What to do with uc_link? 209 * What to do with floating point stuff? 210 * Should we bother with the rest of the registers that we 211 * set to 0 right now? 212 */ 213 214 if ((uc->uc_flags & SVR4_UC_CPU) == 0) 215 return 0; 216 217 tf = p->p_md.md_regs; 218 219 /* 220 * Restore register context. 221 */ 222#ifdef VM86 223 if (r[SVR4_X86_EFL] & PSL_VM) { 224 tf->tf_vm86_gs = r[SVR4_X86_GS]; 225 tf->tf_vm86_fs = r[SVR4_X86_FS]; 226 tf->tf_vm86_es = r[SVR4_X86_ES]; 227 tf->tf_vm86_ds = r[SVR4_X86_DS]; 228 set_vflags(p, r[SVR4_X86_EFL]); 229 } else 230#endif 231 { 232 /* 233 * Check for security violations. If we're returning to 234 * protected mode, the CPU will validate the segment registers 235 * automatically and generate a trap on violations. We handle 236 * the trap, rather than doing all of the checking here. 237 */ 238 if (((r[SVR4_X86_EFL] ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 || 239 !USERMODE(r[SVR4_X86_CS], r[SVR4_X86_EFL])) 240 return (EINVAL); 241 242#if defined(__NetBSD__) 243 /* %fs and %gs were restored by the trampoline. */ 244#else 245 /* %gs was restored by the trampoline. */ 246 tf->tf_fs = r[SVR4_X86_FS]; 247#endif 248 tf->tf_es = r[SVR4_X86_ES]; 249 tf->tf_ds = r[SVR4_X86_DS]; 250 tf->tf_eflags = r[SVR4_X86_EFL]; 251 } 252 tf->tf_edi = r[SVR4_X86_EDI]; 253 tf->tf_esi = r[SVR4_X86_ESI]; 254 tf->tf_ebp = r[SVR4_X86_EBP]; 255 tf->tf_ebx = r[SVR4_X86_EBX]; 256 tf->tf_edx = r[SVR4_X86_EDX]; 257 tf->tf_ecx = r[SVR4_X86_ECX]; 258 tf->tf_eax = r[SVR4_X86_EAX]; 259 tf->tf_trapno = r[SVR4_X86_TRAPNO]; 260 tf->tf_err = r[SVR4_X86_ERR]; 261 tf->tf_eip = r[SVR4_X86_EIP]; 262 tf->tf_cs = r[SVR4_X86_CS]; 263 tf->tf_ss = r[SVR4_X86_SS]; 264 tf->tf_esp = r[SVR4_X86_ESP]; 265 266 p->p_emuldata = uc->uc_link; 267 /* 268 * restore signal stack 269 */ 270 if (uc->uc_flags & SVR4_UC_STACK) { 271 svr4_to_bsd_sigaltstack(s, sf); 272 } 273 274 /* 275 * restore signal mask 276 */ 277 if (uc->uc_flags & SVR4_UC_SIGMASK) { 278 svr4_to_bsd_sigset(&uc->uc_sigmask, &mask); 279 p->p_sigmask = mask; 280 SIG_CANTMASK(p->p_sigmask); 281 } 282 283 return 0; /*EJUSTRETURN;*/ 284} 285 286 287static void 288svr4_getsiginfo(si, sig, code, addr) 289 union svr4_siginfo *si; 290 int sig; 291 u_long code; 292 caddr_t addr; 293{ 294 si->si_signo = bsd_to_svr4_sig[sig]; 295 si->si_errno = 0; 296 si->si_addr = addr; 297 298 switch (code) { 299 case T_PRIVINFLT: 300 si->si_code = SVR4_ILL_PRVOPC; 301 si->si_trap = SVR4_T_PRIVINFLT; 302 break; 303 304 case T_BPTFLT: 305 si->si_code = SVR4_TRAP_BRKPT; 306 si->si_trap = SVR4_T_BPTFLT; 307 break; 308 309 case T_ARITHTRAP: 310 si->si_code = SVR4_FPE_INTOVF; 311 si->si_trap = SVR4_T_DIVIDE; 312 break; 313 314 case T_PROTFLT: 315 si->si_code = SVR4_SEGV_ACCERR; 316 si->si_trap = SVR4_T_PROTFLT; 317 break; 318 319 case T_TRCTRAP: 320 si->si_code = SVR4_TRAP_TRACE; 321 si->si_trap = SVR4_T_TRCTRAP; 322 break; 323 324 case T_PAGEFLT: 325 si->si_code = SVR4_SEGV_ACCERR; 326 si->si_trap = SVR4_T_PAGEFLT; 327 break; 328 329 case T_ALIGNFLT: 330 si->si_code = SVR4_BUS_ADRALN; 331 si->si_trap = SVR4_T_ALIGNFLT; 332 break; 333 334 case T_DIVIDE: 335 si->si_code = SVR4_FPE_FLTDIV; 336 si->si_trap = SVR4_T_DIVIDE; 337 break; 338 339 case T_OFLOW: 340 si->si_code = SVR4_FPE_FLTOVF; 341 si->si_trap = SVR4_T_DIVIDE; 342 break; 343 344 case T_BOUND: 345 si->si_code = SVR4_FPE_FLTSUB; 346 si->si_trap = SVR4_T_BOUND; 347 break; 348 349 case T_DNA: 350 si->si_code = SVR4_FPE_FLTINV; 351 si->si_trap = SVR4_T_DNA; 352 break; 353 354 case T_FPOPFLT: 355 si->si_code = SVR4_FPE_FLTINV; 356 si->si_trap = SVR4_T_FPOPFLT; 357 break; 358 359 case T_SEGNPFLT: 360 si->si_code = SVR4_SEGV_MAPERR; 361 si->si_trap = SVR4_T_SEGNPFLT; 362 break; 363 364 case T_STKFLT: 365 si->si_code = SVR4_ILL_BADSTK; 366 si->si_trap = SVR4_T_STKFLT; 367 break; 368 369 default: 370 si->si_code = 0; 371 si->si_trap = 0; 372#ifdef DIAGNOSTIC 373 printf("sig %d code %ld\n", sig, code); 374 panic("svr4_getsiginfo"); 375#endif 376 break; 377 } 378} 379 380 381/* 382 * Send an interrupt to process. 383 * 384 * Stack is set up to allow sigcode stored 385 * in u. to call routine. After the handler is 386 * done svr4 will call setcontext for us 387 * with the user context we just set up, and we 388 * will return to the user pc, psl. 389 */ 390void 391svr4_sendsig(catcher, sig, mask, code) 392 sig_t catcher; 393 int sig; 394 sigset_t *mask; 395 u_long code; 396{ 397 register struct proc *p = curproc; 398 register struct trapframe *tf; 399 struct svr4_sigframe *fp, frame; 400 struct sigacts *psp = p->p_sigacts; 401 int oonstack; 402 403 tf = p->p_md.md_regs; 404 oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; 405 406 /* 407 * Allocate space for the signal handler context. 408 */ 409 if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && 410 SIGISMEMBER(psp->ps_sigonstack, sig)) { 411 fp = (struct svr4_sigframe *)((caddr_t)psp->ps_sigstk.ss_sp + 412 psp->ps_sigstk.ss_size - sizeof(struct svr4_sigframe)); 413 psp->ps_sigstk.ss_flags |= SS_ONSTACK; 414 } else { 415 fp = (struct svr4_sigframe *)tf->tf_esp - 1; 416 } 417 418 /* 419 * Build the argument list for the signal handler. 420 * Notes: 421 * - we always build the whole argument list, even when we 422 * don't need to [when SA_SIGINFO is not set, we don't need 423 * to pass all sf_si and sf_uc] 424 * - we don't pass the correct signal address [we need to 425 * modify many kernel files to enable that] 426 */ 427 428 svr4_getcontext(p, &frame.sf_uc, mask, oonstack); 429 DPRINTF(("obtained ucontext\n")); 430 svr4_getsiginfo(&frame.sf_si, sig, code, (caddr_t) tf->tf_eip); 431 DPRINTF(("obtained siginfo\n")); 432 frame.sf_signum = frame.sf_si.si_signo; 433 frame.sf_sip = &fp->sf_si; 434 frame.sf_ucp = &fp->sf_uc; 435 frame.sf_handler = catcher; 436#ifdef DEBUG_SVR4 437 printf("sig = %d, sip %p, ucp = %p, handler = %p\n", 438 frame.sf_signum, frame.sf_sip, frame.sf_ucp, frame.sf_handler); 439#endif 440 441 if (copyout(&frame, fp, sizeof(frame)) != 0) { 442 /* 443 * Process has trashed its stack; give it an illegal 444 * instruction to halt it in its tracks. 445 */ 446 sigexit(p, SIGILL); 447 /* NOTREACHED */ 448 } 449#if defined(__NetBSD__) 450 /* 451 * Build context to run handler in. 452 */ 453 tf->tf_es = GSEL(GUSERLDT_SEL, SEL_UPL); 454 tf->tf_ds = GSEL(GUSERLDT_SEL, SEL_UPL); 455 tf->tf_eip = (int)(((char *)PS_STRINGS) - 456 svr4_szsigcode); 457 tf->tf_cs = GSEL(GUSERLDT_SEL, SEL_UPL); 458 459 tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC); 460 tf->tf_esp = (int)fp; 461 tf->tf_ss = GSEL(GUSERLDT_SEL, SEL_UPL); 462#else 463 tf->tf_esp = (int)fp; 464 tf->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); 465 tf->tf_cs = _ucodesel; 466 tf->tf_ds = _udatasel; 467 tf->tf_es = _udatasel; 468 tf->tf_fs = _udatasel; 469 tf->tf_ss = _udatasel; 470#endif 471} 472 473 474 475int 476svr4_sys_sysarch(p, v) 477 struct proc *p; 478 struct svr4_sys_sysarch_args *v; 479{ 480 struct svr4_sys_sysarch_args *uap = v; 481#ifdef USER_LDT 482 caddr_t sg = stackgap_init(p->p_emul); 483 int error; 484#endif 485 switch (uap->op) { 486 case SVR4_SYSARCH_FPHW: 487 return 0; 488 489 case SVR4_SYSARCH_DSCR: 490#ifdef USER_LDT 491 { 492 struct i386_set_ldt_args sa, *sap; 493 struct sys_sysarch_args ua; 494 495 struct svr4_ssd ssd; 496 union descriptor bsd; 497 498 if ((error = copyin(SCARG(uap, a1), &ssd, 499 sizeof(ssd))) != 0) { 500 printf("Cannot copy arg1\n"); 501 return error; 502 } 503 504 printf("s=%x, b=%x, l=%x, a1=%x a2=%x\n", 505 ssd.selector, ssd.base, ssd.limit, 506 ssd.access1, ssd.access2); 507 508 /* We can only set ldt's for now. */ 509 if (!ISLDT(ssd.selector)) { 510 printf("Not an ldt\n"); 511 return EPERM; 512 } 513 514 /* Oh, well we don't cleanup either */ 515 if (ssd.access1 == 0) 516 return 0; 517 518 bsd.sd.sd_lobase = ssd.base & 0xffffff; 519 bsd.sd.sd_hibase = (ssd.base >> 24) & 0xff; 520 521 bsd.sd.sd_lolimit = ssd.limit & 0xffff; 522 bsd.sd.sd_hilimit = (ssd.limit >> 16) & 0xf; 523 524 bsd.sd.sd_type = ssd.access1 & 0x1f; 525 bsd.sd.sd_dpl = (ssd.access1 >> 5) & 0x3; 526 bsd.sd.sd_p = (ssd.access1 >> 7) & 0x1; 527 528 bsd.sd.sd_xx = ssd.access2 & 0x3; 529 bsd.sd.sd_def32 = (ssd.access2 >> 2) & 0x1; 530 bsd.sd.sd_gran = (ssd.access2 >> 3)& 0x1; 531 532 sa.start = IDXSEL(ssd.selector); 533 sa.desc = stackgap_alloc(&sg, sizeof(union descriptor)); 534 sa.num = 1; 535 sap = stackgap_alloc(&sg, 536 sizeof(struct i386_set_ldt_args)); 537 538 if ((error = copyout(&sa, sap, sizeof(sa))) != 0) { 539 printf("Cannot copyout args\n"); 540 return error; 541 } 542 543 SCARG(&ua, op) = I386_SET_LDT; 544 SCARG(&ua, parms) = (char *) sap; 545 546 if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) { 547 printf("Cannot copyout desc\n"); 548 return error; 549 } 550 551 return sys_sysarch(p, &ua, retval); 552 } 553#endif 554 555 default: 556 printf("svr4_sysarch(%d), a1 %p\n", uap->op, 557 uap->a1); 558 return 0; 559 } 560} 561