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