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