svr4_machdep.c revision 49270
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 * $Id$ 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)); 81extern int bsd_to_svr4_sig[]; 82 83#if !defined(__NetBSD__) 84 /* taken from /sys/arch/i386/include/psl.h on NetBSD-1.3 */ 85# define PSL_MBZ 0xffc08028 86# define PSL_USERSTATIC (PSL_USER | PSL_MBZ | PSL_IOPL | PSL_NT | PSL_VM | PSL_VIF | PSL_VIP) 87# define USERMODE(c, f) (ISPL(c) == SEL_UPL) 88#endif 89 90#if defined(__NetBSD__) 91void 92svr4_setregs(p, epp, stack) 93 struct proc *p; 94 struct exec_package *epp; 95 u_long stack; 96{ 97 register struct pcb *pcb = &p->p_addr->u_pcb; 98 99 pcb->pcb_savefpu.sv_env.en_cw = __SVR4_NPXCW__; 100 setregs(p, epp, stack, 0UL); 101} 102#endif /* __NetBSD__ */ 103 104void 105svr4_getcontext(p, uc, mask, oonstack) 106 struct proc *p; 107 struct svr4_ucontext *uc; 108 int mask, 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 int 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 & ~sigcantmask; 280 } 281 282 return 0; /*EJUSTRETURN;*/ 283} 284 285 286static void 287svr4_getsiginfo(si, sig, code, addr) 288 union svr4_siginfo *si; 289 int sig; 290 u_long code; 291 caddr_t addr; 292{ 293 si->si_signo = bsd_to_svr4_sig[sig]; 294 si->si_errno = 0; 295 si->si_addr = addr; 296 297 switch (code) { 298 case T_PRIVINFLT: 299 si->si_code = SVR4_ILL_PRVOPC; 300 si->si_trap = SVR4_T_PRIVINFLT; 301 break; 302 303 case T_BPTFLT: 304 si->si_code = SVR4_TRAP_BRKPT; 305 si->si_trap = SVR4_T_BPTFLT; 306 break; 307 308 case T_ARITHTRAP: 309 si->si_code = SVR4_FPE_INTOVF; 310 si->si_trap = SVR4_T_DIVIDE; 311 break; 312 313 case T_PROTFLT: 314 si->si_code = SVR4_SEGV_ACCERR; 315 si->si_trap = SVR4_T_PROTFLT; 316 break; 317 318 case T_TRCTRAP: 319 si->si_code = SVR4_TRAP_TRACE; 320 si->si_trap = SVR4_T_TRCTRAP; 321 break; 322 323 case T_PAGEFLT: 324 si->si_code = SVR4_SEGV_ACCERR; 325 si->si_trap = SVR4_T_PAGEFLT; 326 break; 327 328 case T_ALIGNFLT: 329 si->si_code = SVR4_BUS_ADRALN; 330 si->si_trap = SVR4_T_ALIGNFLT; 331 break; 332 333 case T_DIVIDE: 334 si->si_code = SVR4_FPE_FLTDIV; 335 si->si_trap = SVR4_T_DIVIDE; 336 break; 337 338 case T_OFLOW: 339 si->si_code = SVR4_FPE_FLTOVF; 340 si->si_trap = SVR4_T_DIVIDE; 341 break; 342 343 case T_BOUND: 344 si->si_code = SVR4_FPE_FLTSUB; 345 si->si_trap = SVR4_T_BOUND; 346 break; 347 348 case T_DNA: 349 si->si_code = SVR4_FPE_FLTINV; 350 si->si_trap = SVR4_T_DNA; 351 break; 352 353 case T_FPOPFLT: 354 si->si_code = SVR4_FPE_FLTINV; 355 si->si_trap = SVR4_T_FPOPFLT; 356 break; 357 358 case T_SEGNPFLT: 359 si->si_code = SVR4_SEGV_MAPERR; 360 si->si_trap = SVR4_T_SEGNPFLT; 361 break; 362 363 case T_STKFLT: 364 si->si_code = SVR4_ILL_BADSTK; 365 si->si_trap = SVR4_T_STKFLT; 366 break; 367 368 default: 369 si->si_code = 0; 370 si->si_trap = 0; 371#ifdef DIAGNOSTIC 372 printf("sig %d code %ld\n", sig, code); 373 panic("svr4_getsiginfo"); 374#endif 375 break; 376 } 377} 378 379 380/* 381 * Send an interrupt to process. 382 * 383 * Stack is set up to allow sigcode stored 384 * in u. to call routine. After the handler is 385 * done svr4 will call setcontext for us 386 * with the user context we just set up, and we 387 * will return to the user pc, psl. 388 */ 389void 390svr4_sendsig(catcher, sig, mask, code) 391 sig_t catcher; 392 int sig, mask; 393 u_long code; 394{ 395 register struct proc *p = curproc; 396 register struct trapframe *tf; 397 struct svr4_sigframe *fp, frame; 398 struct sigacts *psp = p->p_sigacts; 399 int oonstack; 400 401 tf = p->p_md.md_regs; 402 oonstack = psp->ps_sigstk.ss_flags & SS_ONSTACK; 403 404 /* 405 * Allocate space for the signal handler context. 406 */ 407 if ((psp->ps_flags & SAS_ALTSTACK) && !oonstack && 408 (psp->ps_sigonstack & sigmask(sig))) { 409 fp = (struct svr4_sigframe *)((caddr_t)psp->ps_sigstk.ss_sp + 410 psp->ps_sigstk.ss_size - sizeof(struct svr4_sigframe)); 411 psp->ps_sigstk.ss_flags |= SS_ONSTACK; 412 } else { 413 fp = (struct svr4_sigframe *)tf->tf_esp - 1; 414 } 415 416 /* 417 * Build the argument list for the signal handler. 418 * Notes: 419 * - we always build the whole argument list, even when we 420 * don't need to [when SA_SIGINFO is not set, we don't need 421 * to pass all sf_si and sf_uc] 422 * - we don't pass the correct signal address [we need to 423 * modify many kernel files to enable that] 424 */ 425 426 svr4_getcontext(p, &frame.sf_uc, mask, oonstack); 427 DPRINTF(("obtained ucontext\n")); 428 svr4_getsiginfo(&frame.sf_si, sig, code, (caddr_t) tf->tf_eip); 429 DPRINTF(("obtained siginfo\n")); 430 frame.sf_signum = frame.sf_si.si_signo; 431 frame.sf_sip = &fp->sf_si; 432 frame.sf_ucp = &fp->sf_uc; 433 frame.sf_handler = catcher; 434#ifdef DEBUG_SVR4 435 printf("sig = %d, sip %p, ucp = %p, handler = %p\n", 436 frame.sf_signum, frame.sf_sip, frame.sf_ucp, frame.sf_handler); 437#endif 438 439 if (copyout(&frame, fp, sizeof(frame)) != 0) { 440 /* 441 * Process has trashed its stack; give it an illegal 442 * instruction to halt it in its tracks. 443 */ 444 sigexit(p, SIGILL); 445 /* NOTREACHED */ 446 } 447#if defined(__NetBSD__) 448 /* 449 * Build context to run handler in. 450 */ 451 tf->tf_es = GSEL(GUSERLDT_SEL, SEL_UPL); 452 tf->tf_ds = GSEL(GUSERLDT_SEL, SEL_UPL); 453 tf->tf_eip = (int)(((char *)PS_STRINGS) - 454 svr4_szsigcode); 455 tf->tf_cs = GSEL(GUSERLDT_SEL, SEL_UPL); 456 457 tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC); 458 tf->tf_esp = (int)fp; 459 tf->tf_ss = GSEL(GUSERLDT_SEL, SEL_UPL); 460#else 461 tf->tf_esp = (int)fp; 462 tf->tf_eip = (int)(((char *)PS_STRINGS) - *(p->p_sysent->sv_szsigcode)); 463 tf->tf_cs = _ucodesel; 464 tf->tf_ds = _udatasel; 465 tf->tf_es = _udatasel; 466 tf->tf_fs = _udatasel; 467 tf->tf_ss = _udatasel; 468#endif 469} 470 471 472 473int 474svr4_sys_sysarch(p, v) 475 struct proc *p; 476 struct svr4_sys_sysarch_args *v; 477{ 478 struct svr4_sys_sysarch_args *uap = v; 479#ifdef USER_LDT 480 caddr_t sg = stackgap_init(p->p_emul); 481 int error; 482#endif 483 switch (uap->op) { 484 case SVR4_SYSARCH_FPHW: 485 return 0; 486 487 case SVR4_SYSARCH_DSCR: 488#ifdef USER_LDT 489 { 490 struct i386_set_ldt_args sa, *sap; 491 struct sys_sysarch_args ua; 492 493 struct svr4_ssd ssd; 494 union descriptor bsd; 495 496 if ((error = copyin(SCARG(uap, a1), &ssd, 497 sizeof(ssd))) != 0) { 498 printf("Cannot copy arg1\n"); 499 return error; 500 } 501 502 printf("s=%x, b=%x, l=%x, a1=%x a2=%x\n", 503 ssd.selector, ssd.base, ssd.limit, 504 ssd.access1, ssd.access2); 505 506 /* We can only set ldt's for now. */ 507 if (!ISLDT(ssd.selector)) { 508 printf("Not an ldt\n"); 509 return EPERM; 510 } 511 512 /* Oh, well we don't cleanup either */ 513 if (ssd.access1 == 0) 514 return 0; 515 516 bsd.sd.sd_lobase = ssd.base & 0xffffff; 517 bsd.sd.sd_hibase = (ssd.base >> 24) & 0xff; 518 519 bsd.sd.sd_lolimit = ssd.limit & 0xffff; 520 bsd.sd.sd_hilimit = (ssd.limit >> 16) & 0xf; 521 522 bsd.sd.sd_type = ssd.access1 & 0x1f; 523 bsd.sd.sd_dpl = (ssd.access1 >> 5) & 0x3; 524 bsd.sd.sd_p = (ssd.access1 >> 7) & 0x1; 525 526 bsd.sd.sd_xx = ssd.access2 & 0x3; 527 bsd.sd.sd_def32 = (ssd.access2 >> 2) & 0x1; 528 bsd.sd.sd_gran = (ssd.access2 >> 3)& 0x1; 529 530 sa.start = IDXSEL(ssd.selector); 531 sa.desc = stackgap_alloc(&sg, sizeof(union descriptor)); 532 sa.num = 1; 533 sap = stackgap_alloc(&sg, 534 sizeof(struct i386_set_ldt_args)); 535 536 if ((error = copyout(&sa, sap, sizeof(sa))) != 0) { 537 printf("Cannot copyout args\n"); 538 return error; 539 } 540 541 SCARG(&ua, op) = I386_SET_LDT; 542 SCARG(&ua, parms) = (char *) sap; 543 544 if ((error = copyout(&bsd, sa.desc, sizeof(bsd))) != 0) { 545 printf("Cannot copyout desc\n"); 546 return error; 547 } 548 549 return sys_sysarch(p, &ua, retval); 550 } 551#endif 552 553 default: 554 printf("svr4_sysarch(%d), a1 %p\n", uap->op, 555 uap->a1); 556 return 0; 557 } 558} 559