Print this page
manifest


  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  26 /*        All Rights Reserved   */
  27 /*
  28  * Copyright (c) 2018, Joyent, Inc.
  29  * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  30  * Copyright 2022 Oxide Computer Company
  31  */
  32 
  33 #include <sys/param.h>
  34 #include <sys/types.h>
  35 #include <sys/vmparam.h>
  36 #include <sys/systm.h>
  37 #include <sys/signal.h>
  38 #include <sys/stack.h>
  39 #include <sys/regset.h>
  40 #include <sys/privregs.h>
  41 #include <sys/frame.h>
  42 #include <sys/proc.h>
  43 #include <sys/psw.h>
  44 #include <sys/siginfo.h>
  45 #include <sys/cpuvar.h>
  46 #include <sys/asm_linkage.h>
  47 #include <sys/kmem.h>
  48 #include <sys/errno.h>
  49 #include <sys/bootconf.h>
  50 #include <sys/archsystm.h>


 222             src->fp_reg_set.fpchip_state.xstatus;
 223 }
 224 
 225 static void
 226 fpregset_32ton(const fpregset32_t *src, fpregset_t *dst)
 227 {
 228         fpregset32_to_fxsave(src, (struct fxsave_state *)dst);
 229         dst->fp_reg_set.fpchip_state.status =
 230             src->fp_reg_set.fpchip_state.status;
 231         dst->fp_reg_set.fpchip_state.xstatus =
 232             src->fp_reg_set.fpchip_state.xstatus;
 233 }
 234 #endif
 235 
 236 /*
 237  * Set floating-point registers from a native fpregset_t.
 238  */
 239 void
 240 setfpregs(klwp_t *lwp, fpregset_t *fp)
 241 {
 242         struct fpu_ctx *fpu = &lwp->lwp_pcb.pcb_fpu;
 243 
 244         if (fpu->fpu_flags & FPU_EN) {
 245                 if (!(fpu->fpu_flags & FPU_VALID)) {
 246                         /*
 247                          * FPU context is still active, release the
 248                          * ownership.
 249                          */
 250                         fp_free(fpu);
 251                 }
 252         }
 253         /*
 254          * Else: if we are trying to change the FPU state of a thread which
 255          * hasn't yet initialized floating point, store the state in
 256          * the pcb and indicate that the state is valid.  When the
 257          * thread enables floating point, it will use this state instead
 258          * of the default state.
 259          */
 260 
 261         switch (fp_save_mech) {
 262         case FP_FXSAVE:
 263                 fpregset_to_fxsave(fp, fpu->fpu_regs.kfpu_u.kfpu_fx);
 264                 fpu->fpu_regs.kfpu_xstatus =
 265                     fp->fp_reg_set.fpchip_state.xstatus;
 266                 break;
 267 
 268         case FP_XSAVE:
 269                 fpregset_to_fxsave(fp,
 270                     &fpu->fpu_regs.kfpu_u.kfpu_xs->xs_fxsave);
 271                 fpu->fpu_regs.kfpu_xstatus =
 272                     fp->fp_reg_set.fpchip_state.xstatus;
 273                 fpu->fpu_regs.kfpu_u.kfpu_xs->xs_header.xsh_xstate_bv |=
 274                     (XFEATURE_LEGACY_FP | XFEATURE_SSE);
 275                 break;
 276         default:
 277                 panic("Invalid fp_save_mech");
 278                 /*NOTREACHED*/
 279         }
 280 
 281         fpu->fpu_regs.kfpu_status = fp->fp_reg_set.fpchip_state.status;
 282         fpu->fpu_flags |= FPU_VALID;
 283         PCB_SET_UPDATE_FPU(&lwp->lwp_pcb);
 284 }
 285 
 286 /*
 287  * Get floating-point registers into a native fpregset_t.
 288  */
 289 void
 290 getfpregs(klwp_t *lwp, fpregset_t *fp)
 291 {
 292         struct fpu_ctx *fpu = &lwp->lwp_pcb.pcb_fpu;
 293 
 294         kpreempt_disable();
 295         if (fpu->fpu_flags & FPU_EN) {
 296                 /*
 297                  * If we have FPU hw and the thread's pcb doesn't have
 298                  * a valid FPU state then get the state from the hw.
 299                  */
 300                 if (fpu_exists && ttolwp(curthread) == lwp &&
 301                     !(fpu->fpu_flags & FPU_VALID))
 302                         fp_save(fpu); /* get the current FPU state */
 303         }
 304 
 305         /*
 306          * There are 3 possible cases we have to be aware of here:
 307          *
 308          * 1. FPU is enabled.  FPU state is stored in the current LWP.
 309          *
 310          * 2. FPU is not enabled, and there have been no intervening /proc
 311          *    modifications.  Return initial FPU state.
 312          *
 313          * 3. FPU is not enabled, but a /proc consumer has modified FPU state.
 314          *    FPU state is stored in the current LWP.
 315          */
 316         if ((fpu->fpu_flags & FPU_EN) || (fpu->fpu_flags & FPU_VALID)) {
 317                 /*
 318                  * Cases 1 and 3.
 319                  */
 320                 switch (fp_save_mech) {
 321                 case FP_FXSAVE:
 322                         fxsave_to_fpregset(fpu->fpu_regs.kfpu_u.kfpu_fx, fp);
 323                         fp->fp_reg_set.fpchip_state.xstatus =
 324                             fpu->fpu_regs.kfpu_xstatus;
 325                         break;
 326                 case FP_XSAVE:
 327                         fxsave_to_fpregset(
 328                             &fpu->fpu_regs.kfpu_u.kfpu_xs->xs_fxsave, fp);
 329                         fp->fp_reg_set.fpchip_state.xstatus =
 330                             fpu->fpu_regs.kfpu_xstatus;
 331                         break;
 332                 default:
 333                         panic("Invalid fp_save_mech");
 334                         /*NOTREACHED*/
 335                 }
 336                 fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status;
 337         } else {
 338                 /*
 339                  * Case 2.
 340                  */
 341                 switch (fp_save_mech) {
 342                 case FP_FXSAVE:
 343                 case FP_XSAVE:
 344                         /*
 345                          * For now, we don't have any AVX specific field in ABI.
 346                          * If we add any in the future, we need to initial them
 347                          * as well.
 348                          */
 349                         fxsave_to_fpregset(&sse_initial, fp);
 350                         fp->fp_reg_set.fpchip_state.xstatus =
 351                             fpu->fpu_regs.kfpu_xstatus;
 352                         break;
 353                 default:
 354                         panic("Invalid fp_save_mech");
 355                         /*NOTREACHED*/
 356                 }
 357                 fp->fp_reg_set.fpchip_state.status = fpu->fpu_regs.kfpu_status;
 358         }
 359         kpreempt_enable();
 360 }
 361 
 362 #if defined(_SYSCALL32_IMPL)
 363 
 364 /*
 365  * Set floating-point registers from an fpregset32_t.
 366  */
 367 void
 368 setfpregs32(klwp_t *lwp, fpregset32_t *fp)
 369 {
 370         fpregset_t fpregs;
 371 
 372         fpregset_32ton(fp, &fpregs);
 373         setfpregs(lwp, &fpregs);
 374 }
 375 
 376 /*
 377  * Get floating-point registers into an fpregset32_t.
 378  */
 379 void


 511         dmc->gregs[REG_RIP] = (greg_t)(uint32_t)smc->gregs[EIP];
 512         dmc->gregs[REG_CS] = (greg_t)(uint32_t)smc->gregs[CS];
 513         dmc->gregs[REG_RFL] = (greg_t)(uint32_t)smc->gregs[EFL];
 514         dmc->gregs[REG_RSP] = (greg_t)(uint32_t)smc->gregs[UESP];
 515         dmc->gregs[REG_SS] = (greg_t)(uint32_t)smc->gregs[SS];
 516 
 517         /*
 518          * A valid fpregs is only copied in if uc.uc_flags has UC_FPU set
 519          * otherwise there is no guarantee that anything in fpregs is valid.
 520          */
 521         if (src->uc_flags & UC_FPU)
 522                 fpregset_32ton(&src->uc_mcontext.fpregs,
 523                     &dst->uc_mcontext.fpregs);
 524 
 525         /*
 526          * Copy the brand-private data:
 527          */
 528         dst->uc_brand_data[0] = (void *)(uintptr_t)src->uc_brand_data[0];
 529         dst->uc_brand_data[1] = (void *)(uintptr_t)src->uc_brand_data[1];
 530         dst->uc_brand_data[2] = (void *)(uintptr_t)src->uc_brand_data[2];






 531 }
 532 
 533 #endif  /* _SYSCALL32_IMPL */
 534 
 535 /*
 536  * Return the user-level PC.
 537  * If in a system call, return the address of the syscall trap.
 538  */
 539 greg_t
 540 getuserpc()
 541 {
 542         greg_t upc = lwptoregs(ttolwp(curthread))->r_pc;
 543         uint32_t insn;
 544 
 545         if (curthread->t_sysnum == 0)
 546                 return (upc);
 547 
 548         /*
 549          * We might've gotten here from sysenter (0xf 0x34),
 550          * syscall (0xf 0x5) or lcall (0x9a 0 0 0 0 0x27 0).
 551          *
 552          * Go peek at the binary to figure it out..
 553          */
 554         if (fuword32((void *)(upc - 2), &insn) != -1 &&
 555             (insn & 0xffff) == 0x340f || (insn & 0xffff) == 0x050f)
 556                 return (upc - 2);
 557         return (upc - 7);
 558 }
 559 
 560 /*




  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  26 /*        All Rights Reserved   */
  27 /*
  28  * Copyright (c) 2018, Joyent, Inc.
  29  * Copyright 2012 Nexenta Systems, Inc.  All rights reserved.
  30  * Copyright 2023 Oxide Computer Company
  31  */
  32 
  33 #include <sys/param.h>
  34 #include <sys/types.h>
  35 #include <sys/vmparam.h>
  36 #include <sys/systm.h>
  37 #include <sys/signal.h>
  38 #include <sys/stack.h>
  39 #include <sys/regset.h>
  40 #include <sys/privregs.h>
  41 #include <sys/frame.h>
  42 #include <sys/proc.h>
  43 #include <sys/psw.h>
  44 #include <sys/siginfo.h>
  45 #include <sys/cpuvar.h>
  46 #include <sys/asm_linkage.h>
  47 #include <sys/kmem.h>
  48 #include <sys/errno.h>
  49 #include <sys/bootconf.h>
  50 #include <sys/archsystm.h>


 222             src->fp_reg_set.fpchip_state.xstatus;
 223 }
 224 
 225 static void
 226 fpregset_32ton(const fpregset32_t *src, fpregset_t *dst)
 227 {
 228         fpregset32_to_fxsave(src, (struct fxsave_state *)dst);
 229         dst->fp_reg_set.fpchip_state.status =
 230             src->fp_reg_set.fpchip_state.status;
 231         dst->fp_reg_set.fpchip_state.xstatus =
 232             src->fp_reg_set.fpchip_state.xstatus;
 233 }
 234 #endif
 235 
 236 /*
 237  * Set floating-point registers from a native fpregset_t.
 238  */
 239 void
 240 setfpregs(klwp_t *lwp, fpregset_t *fp)
 241 {
 242         fpu_set_fpregset(lwp, fp);









































 243 }
 244 
 245 /*
 246  * Get floating-point registers into a native fpregset_t.
 247  */
 248 void
 249 getfpregs(klwp_t *lwp, fpregset_t *fp)
 250 {
 251         bzero(fp, sizeof (*fp));
 252         fpu_get_fpregset(lwp, fp);


































































 253 }
 254 
 255 #if defined(_SYSCALL32_IMPL)
 256 
 257 /*
 258  * Set floating-point registers from an fpregset32_t.
 259  */
 260 void
 261 setfpregs32(klwp_t *lwp, fpregset32_t *fp)
 262 {
 263         fpregset_t fpregs;
 264 
 265         fpregset_32ton(fp, &fpregs);
 266         setfpregs(lwp, &fpregs);
 267 }
 268 
 269 /*
 270  * Get floating-point registers into an fpregset32_t.
 271  */
 272 void


 404         dmc->gregs[REG_RIP] = (greg_t)(uint32_t)smc->gregs[EIP];
 405         dmc->gregs[REG_CS] = (greg_t)(uint32_t)smc->gregs[CS];
 406         dmc->gregs[REG_RFL] = (greg_t)(uint32_t)smc->gregs[EFL];
 407         dmc->gregs[REG_RSP] = (greg_t)(uint32_t)smc->gregs[UESP];
 408         dmc->gregs[REG_SS] = (greg_t)(uint32_t)smc->gregs[SS];
 409 
 410         /*
 411          * A valid fpregs is only copied in if uc.uc_flags has UC_FPU set
 412          * otherwise there is no guarantee that anything in fpregs is valid.
 413          */
 414         if (src->uc_flags & UC_FPU)
 415                 fpregset_32ton(&src->uc_mcontext.fpregs,
 416                     &dst->uc_mcontext.fpregs);
 417 
 418         /*
 419          * Copy the brand-private data:
 420          */
 421         dst->uc_brand_data[0] = (void *)(uintptr_t)src->uc_brand_data[0];
 422         dst->uc_brand_data[1] = (void *)(uintptr_t)src->uc_brand_data[1];
 423         dst->uc_brand_data[2] = (void *)(uintptr_t)src->uc_brand_data[2];
 424 
 425         if (src->uc_flags & UC_XSAVE) {
 426                 dst->uc_xsave = (long)(uint32_t)src->uc_xsave;
 427         } else {
 428                 dst->uc_xsave = 0;
 429         }
 430 }
 431 
 432 #endif  /* _SYSCALL32_IMPL */
 433 
 434 /*
 435  * Return the user-level PC.
 436  * If in a system call, return the address of the syscall trap.
 437  */
 438 greg_t
 439 getuserpc(void)
 440 {
 441         greg_t upc = lwptoregs(ttolwp(curthread))->r_pc;
 442         uint32_t insn;
 443 
 444         if (curthread->t_sysnum == 0)
 445                 return (upc);
 446 
 447         /*
 448          * We might've gotten here from sysenter (0xf 0x34),
 449          * syscall (0xf 0x5) or lcall (0x9a 0 0 0 0 0x27 0).
 450          *
 451          * Go peek at the binary to figure it out..
 452          */
 453         if (fuword32((void *)(upc - 2), &insn) != -1 &&
 454             (insn & 0xffff) == 0x340f || (insn & 0xffff) == 0x050f)
 455                 return (upc - 2);
 456         return (upc - 7);
 457 }
 458 
 459 /*