1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 #include <sys/param.h> 35 #include <sys/types.h> 36 #include <sys/vmparam.h> 37 #include <sys/systm.h> 38 #include <sys/signal.h> 39 #include <sys/stack.h> 40 #include <sys/frame.h> 41 #include <sys/proc.h> 42 #include <sys/ucontext.h> 43 #include <sys/asm_linkage.h> 44 #include <sys/kmem.h> 45 #include <sys/errno.h> 46 #include <sys/archsystm.h> 47 #include <sys/fpu/fpusystm.h> 48 #include <sys/debug.h> 49 #include <sys/model.h> 50 #include <sys/cmn_err.h> 51 #include <sys/sysmacros.h> 52 #include <sys/privregs.h> 53 #include <sys/schedctl.h> 54 55 56 /* 57 * Save user context. 58 */ 59 void 60 savecontext(ucontext_t *ucp, k_sigset_t mask) 61 { 62 proc_t *p = ttoproc(curthread); 63 klwp_t *lwp = ttolwp(curthread); 64 65 /* 66 * We assign to every field through uc_mcontext.fpregs.fpu_en, 67 * but we have to bzero() everything after that. 68 */ 69 bzero(&ucp->uc_mcontext.fpregs.fpu_en, sizeof (ucontext_t) - 70 offsetof(ucontext_t, uc_mcontext.fpregs.fpu_en)); 71 /* 72 * There are unused holes in the ucontext_t structure, zero-fill 73 * them so that we don't expose kernel data to the user. 74 */ 75 (&ucp->uc_flags)[1] = 0; 76 (&ucp->uc_stack.ss_flags)[1] = 0; 77 78 /* 79 * Flushing the user windows isn't strictly necessary; we do 80 * it to maintain backward compatibility. 81 */ 82 (void) flush_user_windows_to_stack(NULL); 83 84 ucp->uc_flags = UC_ALL; 85 ucp->uc_link = (ucontext_t *)lwp->lwp_oldcontext; 86 87 /* 88 * Try to copyin() the ustack if one is registered. If the stack 89 * has zero size, this indicates that stack bounds checking has 90 * been disabled for this LWP. If stack bounds checking is disabled 91 * or the copyin() fails, we fall back to the legacy behavior. 92 */ 93 if (lwp->lwp_ustack == NULL || 94 copyin((void *)lwp->lwp_ustack, &ucp->uc_stack, 95 sizeof (ucp->uc_stack)) != 0 || 96 ucp->uc_stack.ss_size == 0) { 97 98 if (lwp->lwp_sigaltstack.ss_flags == SS_ONSTACK) { 99 ucp->uc_stack = lwp->lwp_sigaltstack; 100 } else { 101 ucp->uc_stack.ss_sp = p->p_usrstack - p->p_stksize; 102 ucp->uc_stack.ss_size = p->p_stksize; 103 ucp->uc_stack.ss_flags = 0; 104 } 105 } 106 107 getgregs(lwp, ucp->uc_mcontext.gregs); 108 getasrs(lwp, ucp->uc_mcontext.asrs); 109 110 getfpregs(lwp, &ucp->uc_mcontext.fpregs); 111 getfpasrs(lwp, ucp->uc_mcontext.asrs); 112 if (ucp->uc_mcontext.fpregs.fpu_en == 0) 113 ucp->uc_flags &= ~UC_FPU; 114 ucp->uc_mcontext.gwins = (gwindows_t *)NULL; 115 116 /* 117 * Save signal mask. 118 */ 119 sigktou(&mask, &ucp->uc_sigmask); 120 } 121 122 123 void 124 restorecontext(ucontext_t *ucp) 125 { 126 kthread_t *t = curthread; 127 klwp_t *lwp = ttolwp(t); 128 mcontext_t *mcp = &ucp->uc_mcontext; 129 model_t model = lwp_getdatamodel(lwp); 130 131 (void) flush_user_windows_to_stack(NULL); 132 if (lwp->lwp_pcb.pcb_xregstat != XREGNONE) 133 xregrestore(lwp, 0); 134 135 lwp->lwp_oldcontext = (uintptr_t)ucp->uc_link; 136 137 if (ucp->uc_flags & UC_STACK) { 138 if (ucp->uc_stack.ss_flags == SS_ONSTACK) 139 lwp->lwp_sigaltstack = ucp->uc_stack; 140 else 141 lwp->lwp_sigaltstack.ss_flags &= ~SS_ONSTACK; 142 } 143 144 if (ucp->uc_flags & UC_CPU) { 145 if (mcp->gwins != 0) 146 setgwins(lwp, mcp->gwins); 147 setgregs(lwp, mcp->gregs); 148 if (model == DATAMODEL_LP64) 149 setasrs(lwp, mcp->asrs); 150 else 151 xregs_setgregs(lwp, xregs_getptr(lwp, ucp)); 152 } 153 154 if (ucp->uc_flags & UC_FPU) { 155 fpregset_t *fp = &ucp->uc_mcontext.fpregs; 156 157 setfpregs(lwp, fp); 158 if (model == DATAMODEL_LP64) 159 setfpasrs(lwp, mcp->asrs); 160 else 161 xregs_setfpregs(lwp, xregs_getptr(lwp, ucp)); 162 run_fpq(lwp, fp); 163 } 164 165 if (ucp->uc_flags & UC_SIGMASK) { 166 proc_t *p = ttoproc(t); 167 168 mutex_enter(&p->p_lock); 169 schedctl_finish_sigblock(t); 170 sigutok(&ucp->uc_sigmask, &t->t_hold); 171 if (sigcheck(p, t)) 172 t->t_sig_check = 1; 173 mutex_exit(&p->p_lock); 174 } 175 } 176 177 178 int 179 getsetcontext(int flag, void *arg) 180 { 181 ucontext_t uc; 182 struct fq fpu_q[MAXFPQ]; /* to hold floating queue */ 183 fpregset_t *fpp; 184 gwindows_t *gwin = NULL; /* to hold windows */ 185 caddr_t xregs = NULL; 186 int xregs_size = 0; 187 extern int nwindows; 188 ucontext_t *ucp; 189 klwp_t *lwp = ttolwp(curthread); 190 stack_t dummy_stk; 191 192 /* 193 * In future releases, when the ucontext structure grows, 194 * getcontext should be modified to only return the fields 195 * specified in the uc_flags. That way, the structure can grow 196 * and still be binary compatible will all .o's which will only 197 * have old fields defined in uc_flags 198 */ 199 200 switch (flag) { 201 default: 202 return (set_errno(EINVAL)); 203 204 case GETCONTEXT: 205 if (schedctl_sigblock(curthread)) { 206 proc_t *p = ttoproc(curthread); 207 mutex_enter(&p->p_lock); 208 schedctl_finish_sigblock(curthread); 209 mutex_exit(&p->p_lock); 210 } 211 savecontext(&uc, curthread->t_hold); 212 /* 213 * When using floating point it should not be possible to 214 * get here with a fpu_qcnt other than zero since we go 215 * to great pains to handle all outstanding FP exceptions 216 * before any system call code gets executed. However we 217 * clear fpu_q and fpu_qcnt here before copyout anyway - 218 * this will prevent us from interpreting the garbage we 219 * get back (when FP is not enabled) as valid queue data on 220 * a later setcontext(2). 221 */ 222 uc.uc_mcontext.fpregs.fpu_qcnt = 0; 223 uc.uc_mcontext.fpregs.fpu_q = (struct fq *)NULL; 224 225 if (copyout(&uc, arg, sizeof (ucontext_t))) 226 return (set_errno(EFAULT)); 227 return (0); 228 229 case SETCONTEXT: 230 ucp = arg; 231 if (ucp == NULL) 232 exit(CLD_EXITED, 0); 233 /* 234 * Don't copyin filler or floating state unless we need it. 235 * The ucontext_t struct and fields are specified in the ABI. 236 */ 237 if (copyin(ucp, &uc, sizeof (ucontext_t) - 238 sizeof (uc.uc_filler) - 239 sizeof (uc.uc_mcontext.fpregs) - 240 sizeof (uc.uc_mcontext.xrs) - 241 sizeof (uc.uc_mcontext.asrs) - 242 sizeof (uc.uc_mcontext.filler))) { 243 return (set_errno(EFAULT)); 244 } 245 if (copyin(&ucp->uc_mcontext.xrs, &uc.uc_mcontext.xrs, 246 sizeof (uc.uc_mcontext.xrs))) { 247 return (set_errno(EFAULT)); 248 } 249 fpp = &uc.uc_mcontext.fpregs; 250 if (uc.uc_flags & UC_FPU) { 251 /* 252 * Need to copyin floating point state 253 */ 254 if (copyin(&ucp->uc_mcontext.fpregs, 255 &uc.uc_mcontext.fpregs, 256 sizeof (uc.uc_mcontext.fpregs))) 257 return (set_errno(EFAULT)); 258 /* if floating queue not empty */ 259 if ((fpp->fpu_q) && (fpp->fpu_qcnt)) { 260 if (fpp->fpu_qcnt > MAXFPQ || 261 fpp->fpu_q_entrysize <= 0 || 262 fpp->fpu_q_entrysize > sizeof (struct fq)) 263 return (set_errno(EINVAL)); 264 if (copyin(fpp->fpu_q, fpu_q, 265 fpp->fpu_qcnt * fpp->fpu_q_entrysize)) 266 return (set_errno(EFAULT)); 267 fpp->fpu_q = fpu_q; 268 } else { 269 fpp->fpu_qcnt = 0; /* avoid confusion later */ 270 } 271 } else { 272 fpp->fpu_qcnt = 0; 273 } 274 if (uc.uc_mcontext.gwins) { /* if windows in context */ 275 size_t gwin_size; 276 277 /* 278 * We do the same computation here to determine 279 * how many bytes of gwindows_t to copy in that 280 * is also done in sendsig() to decide how many 281 * bytes to copy out. We just *know* that wbcnt 282 * is the first element of the structure. 283 */ 284 gwin = kmem_zalloc(sizeof (gwindows_t), KM_SLEEP); 285 if (copyin(uc.uc_mcontext.gwins, 286 &gwin->wbcnt, sizeof (gwin->wbcnt))) { 287 kmem_free(gwin, sizeof (gwindows_t)); 288 return (set_errno(EFAULT)); 289 } 290 if (gwin->wbcnt < 0 || gwin->wbcnt > nwindows) { 291 kmem_free(gwin, sizeof (gwindows_t)); 292 return (set_errno(EINVAL)); 293 } 294 gwin_size = gwin->wbcnt * sizeof (struct rwindow) + 295 SPARC_MAXREGWINDOW * sizeof (int *) + sizeof (long); 296 if (gwin_size > sizeof (gwindows_t) || 297 copyin(uc.uc_mcontext.gwins, gwin, gwin_size)) { 298 kmem_free(gwin, sizeof (gwindows_t)); 299 return (set_errno(EFAULT)); 300 } 301 uc.uc_mcontext.gwins = gwin; 302 } 303 304 /* 305 * get extra register state or asrs if any exists 306 * there is no extra register state for _LP64 user programs 307 */ 308 xregs_clrptr(lwp, &uc); 309 if (copyin(&ucp->uc_mcontext.asrs, &uc.uc_mcontext.asrs, 310 sizeof (asrset_t))) { 311 /* Free up gwin structure if used */ 312 if (gwin) 313 kmem_free(gwin, sizeof (gwindows_t)); 314 return (set_errno(EFAULT)); 315 } 316 317 restorecontext(&uc); 318 319 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0)) { 320 (void) copyout(&uc.uc_stack, (stack_t *)lwp->lwp_ustack, 321 sizeof (stack_t)); 322 } 323 324 /* 325 * free extra register state area 326 */ 327 if (xregs_size) 328 kmem_free(xregs, xregs_size); 329 330 if (gwin) 331 kmem_free(gwin, sizeof (gwindows_t)); 332 333 return (0); 334 335 case GETUSTACK: 336 if (copyout(&lwp->lwp_ustack, arg, sizeof (caddr_t))) 337 return (set_errno(EFAULT)); 338 339 return (0); 340 341 case SETUSTACK: 342 if (copyin(arg, &dummy_stk, sizeof (dummy_stk))) 343 return (set_errno(EFAULT)); 344 345 lwp->lwp_ustack = (uintptr_t)arg; 346 347 return (0); 348 } 349 } 350 351 352 #ifdef _SYSCALL32_IMPL 353 354 /* 355 * Save user context for 32-bit processes. 356 */ 357 void 358 savecontext32(ucontext32_t *ucp, k_sigset_t mask, struct fq32 *dfq) 359 { 360 proc_t *p = ttoproc(curthread); 361 klwp_t *lwp = ttolwp(curthread); 362 fpregset_t fpregs; 363 364 /* 365 * We assign to every field through uc_mcontext.fpregs.fpu_en, 366 * but we have to bzero() everything after that. 367 */ 368 bzero(&ucp->uc_mcontext.fpregs.fpu_en, sizeof (ucontext32_t) - 369 offsetof(ucontext32_t, uc_mcontext.fpregs.fpu_en)); 370 /* 371 * There is an unused hole in the ucontext32_t structure; zero-fill 372 * it so that we don't expose kernel data to the user. 373 */ 374 (&ucp->uc_stack.ss_flags)[1] = 0; 375 376 /* 377 * Flushing the user windows isn't strictly necessary; we do 378 * it to maintain backward compatibility. 379 */ 380 (void) flush_user_windows_to_stack(NULL); 381 382 ucp->uc_flags = UC_ALL; 383 ucp->uc_link = (caddr32_t)lwp->lwp_oldcontext; 384 385 /* 386 * Try to copyin() the ustack if one is registered. If the stack 387 * has zero size, this indicates that stack bounds checking has 388 * been disabled for this LWP. If stack bounds checking is disabled 389 * or the copyin() fails, we fall back to the legacy behavior. 390 */ 391 if (lwp->lwp_ustack == NULL || 392 copyin((void *)lwp->lwp_ustack, &ucp->uc_stack, 393 sizeof (ucp->uc_stack)) != 0 || 394 ucp->uc_stack.ss_size == 0) { 395 396 if (lwp->lwp_sigaltstack.ss_flags == SS_ONSTACK) { 397 ucp->uc_stack.ss_sp = 398 (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp; 399 ucp->uc_stack.ss_size = 400 (size32_t)lwp->lwp_sigaltstack.ss_size; 401 ucp->uc_stack.ss_flags = SS_ONSTACK; 402 } else { 403 ucp->uc_stack.ss_sp = 404 (caddr32_t)(uintptr_t)p->p_usrstack - p->p_stksize; 405 ucp->uc_stack.ss_size = 406 (size32_t)p->p_stksize; 407 ucp->uc_stack.ss_flags = 0; 408 } 409 } 410 411 getgregs32(lwp, ucp->uc_mcontext.gregs); 412 getfpregs(lwp, &fpregs); 413 fpuregset_nto32(&fpregs, &ucp->uc_mcontext.fpregs, dfq); 414 415 if (ucp->uc_mcontext.fpregs.fpu_en == 0) 416 ucp->uc_flags &= ~UC_FPU; 417 ucp->uc_mcontext.gwins = (caddr32_t)NULL; 418 419 /* 420 * Save signal mask (the 32- and 64-bit sigset_t structures are 421 * identical). 422 */ 423 sigktou(&mask, (sigset_t *)&ucp->uc_sigmask); 424 } 425 426 int 427 getsetcontext32(int flag, void *arg) 428 { 429 ucontext32_t uc; 430 ucontext_t ucnat; 431 struct fq fpu_qnat[MAXFPQ]; /* to hold "native" floating queue */ 432 struct fq32 fpu_q[MAXFPQ]; /* to hold 32 bit floating queue */ 433 fpregset32_t *fpp; 434 gwindows32_t *gwin = NULL; /* to hold windows */ 435 caddr_t xregs; 436 int xregs_size = 0; 437 extern int nwindows; 438 klwp_t *lwp = ttolwp(curthread); 439 ucontext32_t *ucp; 440 uint32_t ustack32; 441 stack32_t dummy_stk32; 442 443 /* 444 * In future releases, when the ucontext structure grows, 445 * getcontext should be modified to only return the fields 446 * specified in the uc_flags. That way, the structure can grow 447 * and still be binary compatible will all .o's which will only 448 * have old fields defined in uc_flags 449 */ 450 451 switch (flag) { 452 default: 453 return (set_errno(EINVAL)); 454 455 case GETCONTEXT: 456 if (schedctl_sigblock(curthread)) { 457 proc_t *p = ttoproc(curthread); 458 mutex_enter(&p->p_lock); 459 schedctl_finish_sigblock(curthread); 460 mutex_exit(&p->p_lock); 461 } 462 savecontext32(&uc, curthread->t_hold, NULL); 463 /* 464 * When using floating point it should not be possible to 465 * get here with a fpu_qcnt other than zero since we go 466 * to great pains to handle all outstanding FP exceptions 467 * before any system call code gets executed. However we 468 * clear fpu_q and fpu_qcnt here before copyout anyway - 469 * this will prevent us from interpreting the garbage we 470 * get back (when FP is not enabled) as valid queue data on 471 * a later setcontext(2). 472 */ 473 uc.uc_mcontext.fpregs.fpu_qcnt = 0; 474 uc.uc_mcontext.fpregs.fpu_q = (caddr32_t)NULL; 475 476 if (copyout(&uc, arg, sizeof (ucontext32_t))) 477 return (set_errno(EFAULT)); 478 return (0); 479 480 case SETCONTEXT: 481 ucp = arg; 482 if (ucp == NULL) 483 exit(CLD_EXITED, 0); 484 /* 485 * Don't copyin filler or floating state unless we need it. 486 * The ucontext_t struct and fields are specified in the ABI. 487 */ 488 if (copyin(ucp, &uc, sizeof (uc) - sizeof (uc.uc_filler) - 489 sizeof (uc.uc_mcontext.fpregs) - 490 sizeof (uc.uc_mcontext.xrs) - 491 sizeof (uc.uc_mcontext.filler))) { 492 return (set_errno(EFAULT)); 493 } 494 if (copyin(&ucp->uc_mcontext.xrs, &uc.uc_mcontext.xrs, 495 sizeof (uc.uc_mcontext.xrs))) { 496 return (set_errno(EFAULT)); 497 } 498 fpp = &uc.uc_mcontext.fpregs; 499 if (uc.uc_flags & UC_FPU) { 500 /* 501 * Need to copyin floating point state 502 */ 503 if (copyin(&ucp->uc_mcontext.fpregs, 504 &uc.uc_mcontext.fpregs, 505 sizeof (uc.uc_mcontext.fpregs))) 506 return (set_errno(EFAULT)); 507 /* if floating queue not empty */ 508 if ((fpp->fpu_q) && (fpp->fpu_qcnt)) { 509 if (fpp->fpu_qcnt > MAXFPQ || 510 fpp->fpu_q_entrysize <= 0 || 511 fpp->fpu_q_entrysize > sizeof (struct fq32)) 512 return (set_errno(EINVAL)); 513 if (copyin((void *)(uintptr_t)fpp->fpu_q, fpu_q, 514 fpp->fpu_qcnt * fpp->fpu_q_entrysize)) 515 return (set_errno(EFAULT)); 516 } else { 517 fpp->fpu_qcnt = 0; /* avoid confusion later */ 518 } 519 } else { 520 fpp->fpu_qcnt = 0; 521 } 522 523 if (uc.uc_mcontext.gwins) { /* if windows in context */ 524 size_t gwin_size; 525 526 /* 527 * We do the same computation here to determine 528 * how many bytes of gwindows_t to copy in that 529 * is also done in sendsig() to decide how many 530 * bytes to copy out. We just *know* that wbcnt 531 * is the first element of the structure. 532 */ 533 gwin = kmem_zalloc(sizeof (gwindows32_t), 534 KM_SLEEP); 535 if (copyin((void *)(uintptr_t)uc.uc_mcontext.gwins, 536 &gwin->wbcnt, sizeof (gwin->wbcnt))) { 537 kmem_free(gwin, sizeof (gwindows32_t)); 538 return (set_errno(EFAULT)); 539 } 540 if (gwin->wbcnt < 0 || gwin->wbcnt > nwindows) { 541 kmem_free(gwin, sizeof (gwindows32_t)); 542 return (set_errno(EINVAL)); 543 } 544 gwin_size = gwin->wbcnt * sizeof (struct rwindow32) + 545 SPARC_MAXREGWINDOW * sizeof (caddr32_t) + 546 sizeof (int32_t); 547 if (gwin_size > sizeof (gwindows32_t) || 548 copyin((void *)(uintptr_t)uc.uc_mcontext.gwins, 549 gwin, gwin_size)) { 550 kmem_free(gwin, sizeof (gwindows32_t)); 551 return (set_errno(EFAULT)); 552 } 553 /* restorecontext() should ignore this */ 554 uc.uc_mcontext.gwins = (caddr32_t)0; 555 } 556 557 ucontext_32ton(&uc, &ucnat, fpu_q, fpu_qnat); 558 559 /* 560 * get extra register state if any exists 561 */ 562 if (xregs_hasptr32(lwp, &uc) && 563 ((xregs_size = xregs_getsize(curproc)) > 0)) { 564 xregs = kmem_zalloc(xregs_size, KM_SLEEP); 565 if (copyin((void *)(uintptr_t)xregs_getptr32(lwp, &uc), 566 xregs, xregs_size)) { 567 kmem_free(xregs, xregs_size); 568 if (gwin) 569 kmem_free(gwin, sizeof (gwindows32_t)); 570 return (set_errno(EFAULT)); 571 } 572 xregs_setptr(lwp, &ucnat, xregs); 573 } else { 574 xregs_clrptr(lwp, &ucnat); 575 } 576 577 restorecontext(&ucnat); 578 579 if ((uc.uc_flags & UC_STACK) && (lwp->lwp_ustack != 0)) { 580 (void) copyout(&uc.uc_stack, 581 (stack32_t *)lwp->lwp_ustack, sizeof (stack32_t)); 582 } 583 584 if (gwin) 585 setgwins32(lwp, gwin); 586 587 /* 588 * free extra register state area 589 */ 590 if (xregs_size) 591 kmem_free(xregs, xregs_size); 592 593 if (gwin) 594 kmem_free(gwin, sizeof (gwindows32_t)); 595 596 return (0); 597 598 case GETUSTACK: 599 ustack32 = (uint32_t)lwp->lwp_ustack; 600 if (copyout(&ustack32, arg, sizeof (caddr32_t))) 601 return (set_errno(EFAULT)); 602 603 return (0); 604 605 case SETUSTACK: 606 if (copyin(arg, &dummy_stk32, sizeof (dummy_stk32))) 607 return (set_errno(EFAULT)); 608 609 lwp->lwp_ustack = (uintptr_t)arg; 610 611 return (0); 612 } 613 } 614 615 #endif /* _SYSCALL32_IMPL */ 616