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