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