The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/osfmk/ppc/status.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
    7  * 
    8  * This file contains Original Code and/or Modifications of Original Code
    9  * as defined in and that are subject to the Apple Public Source License
   10  * Version 2.0 (the 'License'). You may not use this file except in
   11  * compliance with the License. Please obtain a copy of the License at
   12  * http://www.opensource.apple.com/apsl/ and read it before using this
   13  * file.
   14  * 
   15  * The Original Code and all software distributed under the License are
   16  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   17  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   18  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   19  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
   20  * Please see the License for the specific language governing rights and
   21  * limitations under the License.
   22  * 
   23  * @APPLE_LICENSE_HEADER_END@
   24  */
   25 /*
   26  * @OSF_COPYRIGHT@
   27  * 
   28  */
   29 
   30 #include <kern/thread.h>
   31 #include <kern/thread_act.h>
   32 #include <kern/misc_protos.h>
   33 #include <mach/ppc/thread_status.h>
   34 #include <ppc/proc_reg.h>
   35 #include <ppc/exception.h>
   36 #include <ppc/misc_protos.h>
   37 #include <ppc/savearea.h>
   38 #include <ppc/thread_act.h>
   39 #include <ppc/Firmware.h>
   40 
   41 #include <vm/vm_map.h>
   42 
   43 extern unsigned int killprint;
   44 extern double FloatInit;
   45 extern unsigned long QNaNbarbarian[4];
   46 extern void thread_bootstrap_return(void);
   47 extern struct   Saveanchor saveanchor;
   48 extern int      real_ncpus;                     /* Number of actual CPUs */
   49 
   50 #define       USRSTACK        0xc0000000
   51 
   52 kern_return_t
   53 thread_userstack(
   54     thread_t,
   55     int,
   56     thread_state_t,
   57     unsigned int,
   58     vm_offset_t *,
   59         int *
   60 );
   61 
   62 kern_return_t
   63 thread_entrypoint(
   64     thread_t,
   65     int,
   66     thread_state_t,
   67     unsigned int,
   68     vm_offset_t *
   69 ); 
   70 
   71 unsigned int get_msr_exportmask(void);
   72 unsigned int get_msr_nbits(void);
   73 unsigned int get_msr_rbits(void);
   74 void ppc_checkthreadstate(void *, int);
   75 void thread_set_child(thread_act_t child, int pid);
   76 void thread_set_parent(thread_act_t parent, int pid);
   77                 
   78 /*
   79  * Maps state flavor to number of words in the state:
   80  */
   81 unsigned int state_count[] = {
   82         /* FLAVOR_LIST */ 0,
   83         PPC_THREAD_STATE_COUNT,
   84         PPC_FLOAT_STATE_COUNT,
   85         PPC_EXCEPTION_STATE_COUNT,
   86         PPC_VECTOR_STATE_COUNT,
   87         PPC_THREAD_STATE64_COUNT,
   88         PPC_EXCEPTION_STATE64_COUNT,
   89 };
   90 
   91 /*
   92  * thread_getstatus:
   93  *
   94  * Get the status of the specified thread.
   95  */
   96 
   97 kern_return_t 
   98 machine_thread_get_state(
   99                       thread_act_t           thr_act,
  100                       thread_flavor_t        flavor,
  101                       thread_state_t         tstate,
  102                       mach_msg_type_number_t *count)
  103 {
  104         
  105         register struct savearea *sv;                                           /* Pointer to the context savearea */
  106         register savearea_fpu *fsv;
  107         register savearea_vec *vsv;
  108         savearea *genuser;
  109         int i, j;
  110         unsigned int vrvalidwrk;
  111 
  112         register struct ppc_thread_state *ts;
  113         register struct ppc_thread_state64 *xts;
  114         register struct ppc_exception_state *es;
  115         register struct ppc_exception_state64 *xes;
  116         register struct ppc_float_state *fs;
  117         register struct ppc_vector_state *vs;
  118         
  119         genuser = find_user_regs(thr_act);                                              /* Find the current user general context for this activation */
  120 
  121         switch (flavor) {
  122                 
  123                 case THREAD_STATE_FLAVOR_LIST:
  124                         
  125                         if (*count < 6)  {
  126                                 return (KERN_INVALID_ARGUMENT);
  127                         }
  128                 
  129                         tstate[0] = PPC_THREAD_STATE;
  130                         tstate[1] = PPC_FLOAT_STATE;
  131                         tstate[2] = PPC_EXCEPTION_STATE;
  132                         tstate[3] = PPC_VECTOR_STATE;
  133                         tstate[4] = PPC_THREAD_STATE64;
  134                         tstate[5] = PPC_EXCEPTION_STATE64;
  135                         *count = 6;
  136                 
  137                         return KERN_SUCCESS;
  138         
  139                 case PPC_THREAD_STATE:
  140         
  141                         if (*count < PPC_THREAD_STATE_COUNT) {                  /* Is the count ok? */
  142                                 return KERN_INVALID_ARGUMENT;
  143                         }
  144                 
  145                         ts = (struct ppc_thread_state *) tstate;
  146 
  147                         sv = genuser;                                                                   /* Copy this over */
  148                         
  149                         if(sv) {                                                                                /* Is there a save area yet? */
  150                                 ts->r0  = (unsigned int)sv->save_r0;
  151                                 ts->r1  = (unsigned int)sv->save_r1;
  152                                 ts->r2  = (unsigned int)sv->save_r2;
  153                                 ts->r3  = (unsigned int)sv->save_r3;
  154                                 ts->r4  = (unsigned int)sv->save_r4;
  155                                 ts->r5  = (unsigned int)sv->save_r5;
  156                                 ts->r6  = (unsigned int)sv->save_r6;
  157                                 ts->r7  = (unsigned int)sv->save_r7;
  158                                 ts->r8  = (unsigned int)sv->save_r8;
  159                                 ts->r9  = (unsigned int)sv->save_r9;
  160                                 ts->r10 = (unsigned int)sv->save_r10;
  161                                 ts->r11 = (unsigned int)sv->save_r11;
  162                                 ts->r12 = (unsigned int)sv->save_r12;
  163                                 ts->r13 = (unsigned int)sv->save_r13;
  164                                 ts->r14 = (unsigned int)sv->save_r14;
  165                                 ts->r15 = (unsigned int)sv->save_r15;
  166                                 ts->r16 = (unsigned int)sv->save_r16;
  167                                 ts->r17 = (unsigned int)sv->save_r17;
  168                                 ts->r18 = (unsigned int)sv->save_r18;
  169                                 ts->r19 = (unsigned int)sv->save_r19;
  170                                 ts->r20 = (unsigned int)sv->save_r20;
  171                                 ts->r21 = (unsigned int)sv->save_r21;
  172                                 ts->r22 = (unsigned int)sv->save_r22;
  173                                 ts->r23 = (unsigned int)sv->save_r23;
  174                                 ts->r24 = (unsigned int)sv->save_r24;
  175                                 ts->r25 = (unsigned int)sv->save_r25;
  176                                 ts->r26 = (unsigned int)sv->save_r26;
  177                                 ts->r27 = (unsigned int)sv->save_r27;
  178                                 ts->r28 = (unsigned int)sv->save_r28;
  179                                 ts->r29 = (unsigned int)sv->save_r29;
  180                                 ts->r30 = (unsigned int)sv->save_r30;
  181                                 ts->r31 = (unsigned int)sv->save_r31;
  182                                 ts->cr  = (unsigned int)sv->save_cr;
  183                                 ts->xer = (unsigned int)sv->save_xer;
  184                                 ts->lr  = (unsigned int)sv->save_lr;
  185                                 ts->ctr = (unsigned int)sv->save_ctr;
  186                                 ts->srr0 = (unsigned int)sv->save_srr0;
  187                                 ts->srr1 = (unsigned int)sv->save_srr1;
  188                                 ts->mq  = 0;                                                    /* MQ register (601 only) */
  189                                 ts->vrsave      = (unsigned int)sv->save_vrsave;                        /* VRSAVE register (Altivec only) */
  190                         }
  191                         else {                                                                          /* No user state yet. Save seemingly random values. */
  192                                                 
  193                                 for(i=0; i < 32; i+=2) {                                /* Fill up with defaults */
  194                                         ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
  195                                         ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
  196                                 }
  197                                 ts->cr  = 0;
  198                                 ts->xer = 0;
  199                                 ts->lr  = ((unsigned int *)&FloatInit)[0];
  200                                 ts->ctr = ((unsigned int *)&FloatInit)[1];
  201                                 ts->srr0        = ((unsigned int *)&FloatInit)[0];
  202                                 ts->srr1 = MSR_EXPORT_MASK_SET;
  203                                 ts->mq  = 0;
  204                                 ts->vrsave      = 0;                                            /* VRSAVE register (Altivec only) */
  205                         }
  206                 
  207                         *count = PPC_THREAD_STATE_COUNT;                        /* Pass back the amount we actually copied */
  208                         return KERN_SUCCESS;
  209         
  210         
  211                 case PPC_THREAD_STATE64:
  212         
  213                         if (*count < PPC_THREAD_STATE64_COUNT) {        /* Is the count ok? */
  214                                 return KERN_INVALID_ARGUMENT;
  215                         }
  216                 
  217                         xts = (struct ppc_thread_state64 *) tstate;
  218 
  219                         sv = genuser;                                                           /* Copy this over */
  220                         
  221                         if(sv) {                                                                        /* Is there a save area yet? */
  222                                 xts->r0         = sv->save_r0;
  223                                 xts->r1         = sv->save_r1;
  224                                 xts->r2         = sv->save_r2;
  225                                 xts->r3         = sv->save_r3;
  226                                 xts->r4         = sv->save_r4;
  227                                 xts->r5         = sv->save_r5;
  228                                 xts->r6         = sv->save_r6;
  229                                 xts->r7         = sv->save_r7;
  230                                 xts->r8         = sv->save_r8;
  231                                 xts->r9         = sv->save_r9;
  232                                 xts->r10        = sv->save_r10;
  233                                 xts->r11        = sv->save_r11;
  234                                 xts->r12        = sv->save_r12;
  235                                 xts->r13        = sv->save_r13;
  236                                 xts->r14        = sv->save_r14;
  237                                 xts->r15        = sv->save_r15;
  238                                 xts->r16        = sv->save_r16;
  239                                 xts->r17        = sv->save_r17;
  240                                 xts->r18        = sv->save_r18;
  241                                 xts->r19        = sv->save_r19;
  242                                 xts->r20        = sv->save_r20;
  243                                 xts->r21        = sv->save_r21;
  244                                 xts->r22        = sv->save_r22;
  245                                 xts->r23        = sv->save_r23;
  246                                 xts->r24        = sv->save_r24;
  247                                 xts->r25        = sv->save_r25;
  248                                 xts->r26        = sv->save_r26;
  249                                 xts->r27        = sv->save_r27;
  250                                 xts->r28        = sv->save_r28;
  251                                 xts->r29        = sv->save_r29;
  252                                 xts->r30        = sv->save_r30;
  253                                 xts->r31        = sv->save_r31;
  254                                 xts->cr         = sv->save_cr;
  255                                 xts->xer        = sv->save_xer;
  256                                 xts->lr         = sv->save_lr;
  257                                 xts->ctr        = sv->save_ctr;
  258                                 xts->srr0       = sv->save_srr0;
  259                                 xts->srr1       = sv->save_srr1;
  260                                 xts->vrsave     = sv->save_vrsave;                      /* VRSAVE register (Altivec only) */
  261                         }
  262                         else {                                                                          /* No user state yet. Save seemingly random values. */
  263                                                 
  264                                 for(i=0; i < 32; i++) {                                 /* Fill up with defaults */
  265                                         ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
  266                                 }
  267                                 xts->cr         = 0;
  268                                 xts->xer        = 0;
  269                                 xts->lr         = ((unsigned long long *)&FloatInit)[0];
  270                                 xts->ctr        = ((unsigned long long *)&FloatInit)[0];
  271                                 xts->srr0       = ((unsigned long long *)&FloatInit)[0];
  272                                 xts->srr1       = MSR_EXPORT_MASK_SET;
  273                                 xts->vrsave     = 0;                                            /* VRSAVE register (Altivec only) */
  274                         }
  275                 
  276                         *count = PPC_THREAD_STATE64_COUNT;                      /* Pass back the amount we actually copied */
  277                         return KERN_SUCCESS;
  278         
  279                 case PPC_EXCEPTION_STATE:
  280         
  281                         if (*count < PPC_EXCEPTION_STATE_COUNT) {
  282                                 return KERN_INVALID_ARGUMENT;
  283                         }
  284                 
  285                         es = (struct ppc_exception_state *) tstate;
  286                         sv = genuser;                                                           /* Copy this over */
  287                 
  288                         if(sv) {                                                                        /* See if valid state yet */
  289                                 es->dar = (unsigned int)sv->save_dar;
  290                                 es->dsisr = sv->save_dsisr;
  291                                 es->exception = sv->save_exception;
  292                         }
  293                         else {                                                                          /* Nope, not yet */
  294                                 es->dar = 0;
  295                                 es->dsisr = 0;
  296                                 es->exception = ((unsigned int *)&FloatInit)[0];
  297                         }
  298                 
  299                         *count = PPC_EXCEPTION_STATE_COUNT;
  300                         return KERN_SUCCESS;
  301         
  302                 case PPC_EXCEPTION_STATE64:
  303         
  304                         if (*count < PPC_EXCEPTION_STATE64_COUNT) {
  305                                 return KERN_INVALID_ARGUMENT;
  306                         }
  307                 
  308                         xes = (struct ppc_exception_state64 *) tstate;
  309                         sv = genuser;                                                           /* Copy this over */
  310                 
  311                         if(sv) {                                                                        /* See if valid state yet */
  312                                 xes->dar = sv->save_dar;
  313                                 xes->dsisr = sv->save_dsisr;
  314                                 xes->exception = sv->save_exception;
  315                         }
  316                         else {                                                                          /* Nope, not yet */
  317                                 xes->dar = 0;
  318                                 xes->dsisr = 0;
  319                                 xes->exception = ((unsigned int *)&FloatInit)[0];
  320                         }
  321                 
  322                         *count = PPC_EXCEPTION_STATE64_COUNT;
  323                         return KERN_SUCCESS;
  324         
  325                 case PPC_FLOAT_STATE: 
  326                 
  327                         if (*count < PPC_FLOAT_STATE_COUNT)  {
  328                                 return KERN_INVALID_ARGUMENT;
  329                         }
  330                 
  331                         fpu_save(thr_act->mact.curctx);                         /* Just in case it's live, save it */
  332                 
  333                         fs = (struct ppc_float_state *) tstate;         /* Point to destination */
  334                         
  335                         fsv = find_user_fpu(thr_act);                           /* Get the user's fpu savearea */
  336                         
  337                         if(fsv) {                                                                       /* See if we have any */
  338                                 bcopy((char *)&fsv->save_fp0, (char *)fs, 32*8); /* 32 registers  */
  339                                 fs->fpscr_pad   = 0;                                    /* Be clean and tidy */
  340                                 if(genuser) fs->fpscr = genuser->save_fpscr;    /* Set the fpscr value to general */
  341                                 else fs->fpscr = 0;                                             /* If no user, initialize this */
  342                         }
  343                         else {                                                                          /* No floating point yet */
  344                         
  345                                 for(i=0; i < 32; i++) {                                 /* Initialize floating points */
  346                                         fs->fpregs[i] = FloatInit;                      /* Initial value */
  347                                 }
  348                                 fs->fpscr_pad   = 0;                                    /* Initial value */
  349                                 fs->fpscr               = 0;                                    /* Initial value */
  350                         }
  351                         
  352                         *count = PPC_FLOAT_STATE_COUNT;
  353                         
  354                         return KERN_SUCCESS;
  355         
  356                 case PPC_VECTOR_STATE: 
  357                         
  358                         if (*count < PPC_VECTOR_STATE_COUNT)  {
  359                                 return KERN_INVALID_ARGUMENT;
  360                         }
  361                 
  362                         vec_save(thr_act->mact.curctx);                         /* Just in case it's live, save it */
  363                 
  364                         vs = (struct ppc_vector_state *) tstate;        /* Point to destination */
  365                         
  366                         vsv = find_user_vec(thr_act);                           /* Find the vector savearea */
  367                         
  368                         if(vsv) {                                                                       /* See if we have any */
  369                                 
  370                                 vrvalidwrk = vsv->save_vrvalid;                 /* Get the valid flags */
  371                                 vs->save_vrvalid = vsv->save_vrvalid;   /* Set the valid flags */
  372                                 if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j];      /* Set value for vscr */
  373                                 else {
  374                                         vs->save_vscr[0] = 0;                           /* Set an initial value if no general user yet */
  375                                         vs->save_vscr[1] = 0;
  376                                         vs->save_vscr[2] = 0;
  377                                         vs->save_vscr[3] = 0x00010000;          /* Always start with Java mode off */
  378                                 }
  379                                 for(i=0; i < 32; i++) {                                 /* Copy the saved registers and invalidate the others */
  380                                         for(j=0; j < 4; j++) {
  381                                                 if(vrvalidwrk & 0x80000000) (vs->save_vr)[i][j] = 
  382                                                         ((unsigned int *)&(vsv->save_vr0))[(i * 4) + j];        /* We have this register saved */
  383                                                 else vs->save_vr[i][j] = QNaNbarbarian[j];      /* Set invalid value */
  384                                         }
  385                                         vrvalidwrk = vrvalidwrk << 1;           /* Shift over to the next */
  386                                 }
  387                         }
  388                         else {                                                                          /* No vector yet */
  389                         
  390                                 for(i=0; i < 32; i++) {                                 /* Initialize vector registers */
  391                                         for(j=0; j < 4; j++) vs->save_vr[i][j] = QNaNbarbarian[j];              /* Initial value */
  392                                 }
  393                                 
  394                                 if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j];      /* Set value for vscr */
  395                                 else {
  396                                         vs->save_vscr[0] = 0;                           /* Set an initial value if no general user yet */
  397                                         vs->save_vscr[1] = 0;
  398                                         vs->save_vscr[2] = 0;
  399                                         vs->save_vscr[3] = 0x00010000;          /* Always start with Java mode off */
  400                                 }
  401                                 vs->save_vrvalid = 0;                                   /* Clear the valid flags */
  402                         }
  403                         
  404                         for (i=0; i < 4; i++) vs->save_pad5[i] = 0;     /* Clear cruft */
  405                         for (i=0; i < 7; i++) vs->save_pad6[i] = 0;     /* Clear cruft */
  406                         
  407                         *count = PPC_VECTOR_STATE_COUNT;
  408                         return KERN_SUCCESS;
  409         
  410                 default:
  411                         return KERN_INVALID_ARGUMENT;
  412         }
  413 }
  414 /* Close cousin of machine_thread_get_state(). 
  415  * This function is currently incomplete since we don't really need vector
  416  * or FP for the core dump (the save area can be accessed directly if the 
  417  * user is so inclined). Also the function name is something of a misnomer,
  418  * see the comment above find_kern_regs(). 
  419  */
  420 
  421 kern_return_t 
  422 machine_thread_get_kern_state(
  423                       thread_act_t           thr_act,
  424                       thread_flavor_t        flavor,
  425                       thread_state_t         tstate,
  426                       mach_msg_type_number_t *count)
  427 {
  428         
  429         register struct savearea *sv;                                           /* Pointer to the context savearea */
  430         savearea *genkern;
  431         int i, j;
  432         unsigned int vrvalidwrk;
  433 
  434         register struct ppc_thread_state *ts;
  435         register struct ppc_thread_state64 *xts;
  436         register struct ppc_exception_state *es;
  437         register struct ppc_exception_state64 *xes;
  438         
  439         genkern = find_kern_regs(thr_act);
  440 
  441         switch (flavor) {
  442                 
  443                 case THREAD_STATE_FLAVOR_LIST:
  444                         
  445                         if (*count < 6)  {
  446                                 return (KERN_INVALID_ARGUMENT);
  447                         }
  448                 
  449                         tstate[0] = PPC_THREAD_STATE;
  450                         tstate[1] = PPC_FLOAT_STATE;
  451                         tstate[2] = PPC_EXCEPTION_STATE;
  452                         tstate[3] = PPC_VECTOR_STATE;
  453                         tstate[4] = PPC_THREAD_STATE64;
  454                         tstate[5] = PPC_EXCEPTION_STATE64;
  455                         *count = 6;
  456                 
  457                         return KERN_SUCCESS;
  458         
  459                 case PPC_THREAD_STATE:
  460         
  461                         if (*count < PPC_THREAD_STATE_COUNT) {                  /* Is the count ok? */
  462                                 return KERN_INVALID_ARGUMENT;
  463                         }
  464                 
  465                         ts = (struct ppc_thread_state *) tstate;
  466 
  467                         sv = genkern;                                                                   /* Copy this over */
  468                         
  469                         if(sv) {                                                                                /* Is there a save area yet? */
  470                                 ts->r0  = (unsigned int)sv->save_r0;
  471                                 ts->r1  = (unsigned int)sv->save_r1;
  472                                 ts->r2  = (unsigned int)sv->save_r2;
  473                                 ts->r3  = (unsigned int)sv->save_r3;
  474                                 ts->r4  = (unsigned int)sv->save_r4;
  475                                 ts->r5  = (unsigned int)sv->save_r5;
  476                                 ts->r6  = (unsigned int)sv->save_r6;
  477                                 ts->r7  = (unsigned int)sv->save_r7;
  478                                 ts->r8  = (unsigned int)sv->save_r8;
  479                                 ts->r9  = (unsigned int)sv->save_r9;
  480                                 ts->r10 = (unsigned int)sv->save_r10;
  481                                 ts->r11 = (unsigned int)sv->save_r11;
  482                                 ts->r12 = (unsigned int)sv->save_r12;
  483                                 ts->r13 = (unsigned int)sv->save_r13;
  484                                 ts->r14 = (unsigned int)sv->save_r14;
  485                                 ts->r15 = (unsigned int)sv->save_r15;
  486                                 ts->r16 = (unsigned int)sv->save_r16;
  487                                 ts->r17 = (unsigned int)sv->save_r17;
  488                                 ts->r18 = (unsigned int)sv->save_r18;
  489                                 ts->r19 = (unsigned int)sv->save_r19;
  490                                 ts->r20 = (unsigned int)sv->save_r20;
  491                                 ts->r21 = (unsigned int)sv->save_r21;
  492                                 ts->r22 = (unsigned int)sv->save_r22;
  493                                 ts->r23 = (unsigned int)sv->save_r23;
  494                                 ts->r24 = (unsigned int)sv->save_r24;
  495                                 ts->r25 = (unsigned int)sv->save_r25;
  496                                 ts->r26 = (unsigned int)sv->save_r26;
  497                                 ts->r27 = (unsigned int)sv->save_r27;
  498                                 ts->r28 = (unsigned int)sv->save_r28;
  499                                 ts->r29 = (unsigned int)sv->save_r29;
  500                                 ts->r30 = (unsigned int)sv->save_r30;
  501                                 ts->r31 = (unsigned int)sv->save_r31;
  502                                 ts->cr  = (unsigned int)sv->save_cr;
  503                                 ts->xer = (unsigned int)sv->save_xer;
  504                                 ts->lr  = (unsigned int)sv->save_lr;
  505                                 ts->ctr = (unsigned int)sv->save_ctr;
  506                                 ts->srr0 = (unsigned int)sv->save_srr0;
  507                                 ts->srr1 = (unsigned int)sv->save_srr1;
  508                                 ts->mq  = 0;                                                    /* MQ register (601 only) */
  509                                 ts->vrsave      = (unsigned int)sv->save_vrsave;                        /* VRSAVE register (Altivec only) */
  510                         }
  511                         else {                                                                          /* No state yet. Save seemingly random values. */
  512                                                 
  513                                 for(i=0; i < 32; i+=2) {                                /* Fill up with defaults */
  514                                         ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
  515                                         ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
  516                                 }
  517                                 ts->cr  = 0;
  518                                 ts->xer = 0;
  519                                 ts->lr  = ((unsigned int *)&FloatInit)[0];
  520                                 ts->ctr = ((unsigned int *)&FloatInit)[1];
  521                                 ts->srr0        = ((unsigned int *)&FloatInit)[0];
  522                                 ts->srr1 = MSR_EXPORT_MASK_SET;
  523                                 ts->mq  = 0;
  524                                 ts->vrsave      = 0;                                            /* VRSAVE register (Altivec only) */
  525                         }
  526                 
  527                         *count = PPC_THREAD_STATE_COUNT;                        /* Pass back the amount we actually copied */
  528                         return KERN_SUCCESS;
  529         
  530         
  531                 case PPC_THREAD_STATE64:
  532         
  533                         if (*count < PPC_THREAD_STATE64_COUNT) {        /* Is the count ok? */
  534                                 return KERN_INVALID_ARGUMENT;
  535                         }
  536                 
  537                         xts = (struct ppc_thread_state64 *) tstate;
  538 
  539                         sv = genkern;                                                           /* Copy this over */
  540                         
  541                         if(sv) {                                                                        /* Is there a save area yet? */
  542                                 xts->r0         = sv->save_r0;
  543                                 xts->r1         = sv->save_r1;
  544                                 xts->r2         = sv->save_r2;
  545                                 xts->r3         = sv->save_r3;
  546                                 xts->r4         = sv->save_r4;
  547                                 xts->r5         = sv->save_r5;
  548                                 xts->r6         = sv->save_r6;
  549                                 xts->r7         = sv->save_r7;
  550                                 xts->r8         = sv->save_r8;
  551                                 xts->r9         = sv->save_r9;
  552                                 xts->r10        = sv->save_r10;
  553                                 xts->r11        = sv->save_r11;
  554                                 xts->r12        = sv->save_r12;
  555                                 xts->r13        = sv->save_r13;
  556                                 xts->r14        = sv->save_r14;
  557                                 xts->r15        = sv->save_r15;
  558                                 xts->r16        = sv->save_r16;
  559                                 xts->r17        = sv->save_r17;
  560                                 xts->r18        = sv->save_r18;
  561                                 xts->r19        = sv->save_r19;
  562                                 xts->r20        = sv->save_r20;
  563                                 xts->r21        = sv->save_r21;
  564                                 xts->r22        = sv->save_r22;
  565                                 xts->r23        = sv->save_r23;
  566                                 xts->r24        = sv->save_r24;
  567                                 xts->r25        = sv->save_r25;
  568                                 xts->r26        = sv->save_r26;
  569                                 xts->r27        = sv->save_r27;
  570                                 xts->r28        = sv->save_r28;
  571                                 xts->r29        = sv->save_r29;
  572                                 xts->r30        = sv->save_r30;
  573                                 xts->r31        = sv->save_r31;
  574                                 xts->cr         = sv->save_cr;
  575                                 xts->xer        = sv->save_xer;
  576                                 xts->lr         = sv->save_lr;
  577                                 xts->ctr        = sv->save_ctr;
  578                                 xts->srr0       = sv->save_srr0;
  579                                 xts->srr1       = sv->save_srr1;
  580                                 xts->vrsave     = sv->save_vrsave;                      /* VRSAVE register (Altivec only) */
  581                         }
  582                         else {                                                                          /* No user state yet. Save seemingly random values. */
  583                                                 
  584                                 for(i=0; i < 32; i++) {                                 /* Fill up with defaults */
  585                                         ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
  586                                 }
  587                                 xts->cr         = 0;
  588                                 xts->xer        = 0;
  589                                 xts->lr         = ((unsigned long long *)&FloatInit)[0];
  590                                 xts->ctr        = ((unsigned long long *)&FloatInit)[0];
  591                                 xts->srr0       = ((unsigned long long *)&FloatInit)[0];
  592                                 xts->srr1       = MSR_EXPORT_MASK_SET;
  593                                 xts->vrsave     = 0;                                            /* VRSAVE register (Altivec only) */
  594                         }
  595                 
  596                         *count = PPC_THREAD_STATE64_COUNT;                      /* Pass back the amount we actually copied */
  597                         return KERN_SUCCESS;
  598         
  599                 case PPC_EXCEPTION_STATE:
  600         
  601                         if (*count < PPC_EXCEPTION_STATE_COUNT) {
  602                                 return KERN_INVALID_ARGUMENT;
  603                         }
  604                 
  605                         es = (struct ppc_exception_state *) tstate;
  606                         sv = genkern;                                                           /* Copy this over */
  607                 
  608                         if(sv) {                                                                        /* See if valid state yet */
  609                                 es->dar = (unsigned int)sv->save_dar;
  610                                 es->dsisr = sv->save_dsisr;
  611                                 es->exception = sv->save_exception;
  612                         }
  613                         else {                                                                          /* Nope, not yet */
  614                                 es->dar = 0;
  615                                 es->dsisr = 0;
  616                                 es->exception = ((unsigned int *)&FloatInit)[0];
  617                         }
  618                 
  619                         *count = PPC_EXCEPTION_STATE_COUNT;
  620                         return KERN_SUCCESS;
  621         
  622                 case PPC_EXCEPTION_STATE64:
  623         
  624                         if (*count < PPC_EXCEPTION_STATE64_COUNT) {
  625                                 return KERN_INVALID_ARGUMENT;
  626                         }
  627                 
  628                         xes = (struct ppc_exception_state64 *) tstate;
  629                         sv = genkern;                                                           /* Copy this over */
  630                 
  631                         if(sv) {                                                                        /* See if valid state yet */
  632                                 xes->dar = sv->save_dar;
  633                                 xes->dsisr = sv->save_dsisr;
  634                                 xes->exception = sv->save_exception;
  635                         }
  636                         else {                                                                          /* Nope, not yet */
  637                                 xes->dar = 0;
  638                                 xes->dsisr = 0;
  639                                 xes->exception = ((unsigned int *)&FloatInit)[0];
  640                         }
  641                 
  642                         *count = PPC_EXCEPTION_STATE64_COUNT;
  643                         return KERN_SUCCESS;
  644         
  645                 default:
  646                         return KERN_INVALID_ARGUMENT;
  647         }
  648 }
  649 
  650 
  651 /*
  652  * thread_setstatus:
  653  *
  654  * Set the status of the specified thread.
  655  */
  656 kern_return_t 
  657 machine_thread_set_state(
  658                       thread_act_t           thr_act,
  659                       thread_flavor_t        flavor,
  660                       thread_state_t         tstate,
  661                       mach_msg_type_number_t count)
  662 {
  663   
  664         savearea                *sv, *genuser;
  665         savearea_fpu    *fsv, *fsvn, *fsvo;
  666         savearea_vec    *vsv, *vsvn, *vsvo;
  667         unsigned int    i;
  668         int                             clgn;
  669         register struct ppc_thread_state *ts;
  670         register struct ppc_thread_state64 *xts;
  671         register struct ppc_exception_state *es;
  672         register struct ppc_exception_state *xes;
  673         register struct ppc_float_state *fs;
  674         register struct ppc_vector_state *vs;
  675         
  676 //      dbgTrace((unsigned int)thr_act, (unsigned int)sv, flavor);      /* (TEST/DEBUG) */
  677 
  678         clgn = count;                                                                                   /* Get the count */
  679         
  680         switch (flavor) {                                                                               /* Validate the count before we do anything else */
  681                 case PPC_THREAD_STATE:
  682                         
  683                         if (clgn < PPC_THREAD_STATE_COUNT)  {                   /* Is it too short? */
  684                                 return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
  685                         }
  686                         break;
  687         
  688                 case PPC_THREAD_STATE64:
  689                         
  690                         if (clgn < PPC_THREAD_STATE64_COUNT)  {                 /* Is it too short? */
  691                                 return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
  692                         }
  693                         break;
  694                         
  695                 case PPC_EXCEPTION_STATE:
  696                         
  697                         if (clgn < PPC_EXCEPTION_STATE_COUNT)  {                /* Is it too short? */
  698                                 return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
  699                         }
  700                         
  701                 case PPC_EXCEPTION_STATE64:
  702                         
  703                         if (clgn < PPC_EXCEPTION_STATE64_COUNT)  {              /* Is it too short? */
  704                                 return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
  705                         }
  706                         
  707                         break;
  708                         
  709                 case PPC_FLOAT_STATE:
  710                         
  711                         if (clgn < PPC_FLOAT_STATE_COUNT)  {                    /* Is it too short? */
  712                                 return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
  713                         }
  714                         
  715                         break;
  716                         
  717 
  718                 case PPC_VECTOR_STATE:
  719                         
  720                         if (clgn < PPC_VECTOR_STATE_COUNT)  {                   /* Is it too short? */
  721                                 return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
  722                         }
  723                         
  724                         break;
  725                         
  726                 default:
  727                         return KERN_INVALID_ARGUMENT;
  728         }
  729         
  730         genuser = get_user_regs(thr_act);                                               /* Find or allocate and initialize one */
  731 
  732         switch (flavor) {
  733                 
  734                 case PPC_THREAD_STATE:
  735                                 
  736                         ts = (struct ppc_thread_state *)tstate;
  737 
  738                         genuser->save_r0        = (uint64_t)ts->r0;
  739                         genuser->save_r1        = (uint64_t)ts->r1;
  740                         genuser->save_r2        = (uint64_t)ts->r2;
  741                         genuser->save_r3        = (uint64_t)ts->r3;
  742                         genuser->save_r4        = (uint64_t)ts->r4;
  743                         genuser->save_r5        = (uint64_t)ts->r5;
  744                         genuser->save_r6        = (uint64_t)ts->r6;
  745                         genuser->save_r7        = (uint64_t)ts->r7;
  746                         genuser->save_r8        = (uint64_t)ts->r8;
  747                         genuser->save_r9        = (uint64_t)ts->r9;
  748                         genuser->save_r10       = (uint64_t)ts->r10;
  749                         genuser->save_r11       = (uint64_t)ts->r11;
  750                         genuser->save_r12       = (uint64_t)ts->r12;
  751                         genuser->save_r13       = (uint64_t)ts->r13;
  752                         genuser->save_r14       = (uint64_t)ts->r14;
  753                         genuser->save_r15       = (uint64_t)ts->r15;
  754                         genuser->save_r16       = (uint64_t)ts->r16;
  755                         genuser->save_r17       = (uint64_t)ts->r17;
  756                         genuser->save_r18       = (uint64_t)ts->r18;
  757                         genuser->save_r19       = (uint64_t)ts->r19;
  758                         genuser->save_r20       = (uint64_t)ts->r20;
  759                         genuser->save_r21       = (uint64_t)ts->r21;
  760                         genuser->save_r22       = (uint64_t)ts->r22;
  761                         genuser->save_r23       = (uint64_t)ts->r23;
  762                         genuser->save_r24       = (uint64_t)ts->r24;
  763                         genuser->save_r25       = (uint64_t)ts->r25;
  764                         genuser->save_r26       = (uint64_t)ts->r26;
  765                         genuser->save_r27       = (uint64_t)ts->r27;
  766                         genuser->save_r28       = (uint64_t)ts->r28;
  767                         genuser->save_r29       = (uint64_t)ts->r29;
  768                         genuser->save_r30       = (uint64_t)ts->r30;
  769                         genuser->save_r31       = (uint64_t)ts->r31;
  770                 
  771                         genuser->save_cr        = ts->cr;
  772                         genuser->save_xer       = (uint64_t)ts->xer;
  773                         genuser->save_lr        = (uint64_t)ts->lr;
  774                         genuser->save_ctr       = (uint64_t)ts->ctr;
  775                         genuser->save_srr0      = (uint64_t)ts->srr0;
  776                         genuser->save_vrsave    = ts->vrsave;                                   /* VRSAVE register (Altivec only) */
  777 
  778                         genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, ts->srr1);      /* Set the bits we can change */
  779 
  780                         genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
  781                 
  782                         genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));  /* Make sure we don't enable the floating point unit */
  783                 
  784                         return KERN_SUCCESS;
  785 
  786 
  787                 case PPC_THREAD_STATE64:
  788                                 
  789                         xts = (struct ppc_thread_state64 *)tstate;
  790 
  791                         genuser->save_r0        = xts->r0;
  792                         genuser->save_r1        = xts->r1;
  793                         genuser->save_r2        = xts->r2;
  794                         genuser->save_r3        = xts->r3;
  795                         genuser->save_r4        = xts->r4;
  796                         genuser->save_r5        = xts->r5;
  797                         genuser->save_r6        = xts->r6;
  798                         genuser->save_r7        = xts->r7;
  799                         genuser->save_r8        = xts->r8;
  800                         genuser->save_r9        = xts->r9;
  801                         genuser->save_r10       = xts->r10;
  802                         genuser->save_r11       = xts->r11;
  803                         genuser->save_r12       = xts->r12;
  804                         genuser->save_r13       = xts->r13;
  805                         genuser->save_r14       = xts->r14;
  806                         genuser->save_r15       = xts->r15;
  807                         genuser->save_r16       = xts->r16;
  808                         genuser->save_r17       = xts->r17;
  809                         genuser->save_r18       = xts->r18;
  810                         genuser->save_r19       = xts->r19;
  811                         genuser->save_r20       = xts->r20;
  812                         genuser->save_r21       = xts->r21;
  813                         genuser->save_r22       = xts->r22;
  814                         genuser->save_r23       = xts->r23;
  815                         genuser->save_r24       = xts->r24;
  816                         genuser->save_r25       = xts->r25;
  817                         genuser->save_r26       = xts->r26;
  818                         genuser->save_r27       = xts->r27;
  819                         genuser->save_r28       = xts->r28;
  820                         genuser->save_r29       = xts->r29;
  821                         genuser->save_r30       = xts->r30;
  822                         genuser->save_r31       = xts->r31;
  823                 
  824                         genuser->save_cr        = xts->cr;
  825                         genuser->save_xer       = xts->xer;
  826                         genuser->save_lr        = xts->lr;
  827                         genuser->save_ctr       = xts->ctr;
  828                         genuser->save_srr0      = xts->srr0;
  829                         genuser->save_vrsave    = xts->vrsave;                                  /* VRSAVE register (Altivec only) */
  830 
  831                         genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, xts->srr1);     /* Set the bits we can change */
  832 
  833                         genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
  834                 
  835                         genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));  /* Make sure we don't enable the floating point unit */
  836                 
  837                         return KERN_SUCCESS;
  838                                 
  839                                 
  840                 case PPC_EXCEPTION_STATE:
  841                         
  842                         es = (struct ppc_exception_state *) tstate;
  843                 
  844                         genuser->save_dar = (uint64_t)es->dar;
  845                         genuser->save_dsisr = es->dsisr;
  846                         genuser->save_exception = es->exception;
  847 
  848                         return KERN_SUCCESS;
  849         
  850 /*
  851  *              It's pretty worthless to try to change this stuff, but we'll do it anyway.
  852  */
  853  
  854                 case PPC_EXCEPTION_STATE64:
  855                         
  856                         xes = (struct ppc_exception_state *) tstate;
  857                 
  858                         genuser->save_dar       = xes->dar;
  859                         genuser->save_dsisr = xes->dsisr;
  860                         genuser->save_exception = xes->exception;
  861 
  862                         return KERN_SUCCESS;
  863         
  864                 case PPC_FLOAT_STATE:
  865 
  866                         toss_live_fpu(thr_act->mact.curctx);                    /* Toss my floating point if live anywhere */
  867                         
  868                         fsv = find_user_fpu(thr_act);                                   /* Get the user's floating point context */
  869                 
  870                         if(!fsv) {                                                                              /* Do we have one yet? */
  871                                 fsv = (savearea_fpu *)save_alloc();                     /* If we still don't have one, get a new one */
  872                                 fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft);   /* Mark as in use as float */
  873                                 fsv->save_hdr.save_act = (struct thread_activation *)thr_act;   /* Point to the activation */
  874                                 fsv->save_hdr.save_prev = 0;                            /* Mark no more */
  875                                 fsv->save_hdr.save_level = 0;                           /* Mark user state */
  876                                 
  877                                 if(!thr_act->mact.curctx->FPUsave) thr_act->mact.curctx->FPUsave = fsv; /* If no floating point, chain us first */
  878                                 else {
  879                                 
  880                                         fsvn = fsvo = thr_act->mact.curctx->FPUsave;    /* Remember first one */
  881                                         
  882                                         while (fsvn) {                                                  /* Go until we hit the end */
  883                                                 fsvo = fsvn;                                            /* Remember the previous one */
  884                                                 fsvn = CAST_DOWN(savearea_fpu *, fsvo->save_hdr.save_prev);     /* Skip on to the next */
  885                                         }
  886                                         
  887                                         fsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv);          /* Queue us on in */
  888                                 }
  889                                 
  890                         }
  891                         
  892                         fs = (struct ppc_float_state *) tstate;                 /* Point to source */
  893 
  894                 
  895                         bcopy((char *)fs, (char *)&fsv->save_fp0, 32*8);        /* Move in the 32 registers */
  896                         
  897                         genuser->save_fpscr = fs->fpscr;                                /* Copy the fpscr value to normal */    
  898                         
  899                         return KERN_SUCCESS;
  900                         
  901         
  902                 case PPC_VECTOR_STATE:
  903 
  904                         toss_live_vec(thr_act->mact.curctx);                    /* Toss my vector if live anywhere */
  905                         
  906                         vsv = find_user_vec(thr_act);                                   /* Get the user's vector context */
  907                 
  908                         if(!vsv) {                                                                              /* Do we have one yet? */
  909                                 vsv = (savearea_vec *)save_alloc();                     /* If we still don't have one, get a new one */
  910                                 vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);  /* Mark as in use as vector */
  911                                 vsv->save_hdr.save_act = (struct thread_activation *)thr_act;   /* Point to the activation */
  912                                 vsv->save_hdr.save_prev = 0;                            /* Mark no more */
  913                                 vsv->save_hdr.save_level = 0;                           /* Mark user state */
  914                                 
  915                                 if(!thr_act->mact.curctx->VMXsave) thr_act->mact.curctx->VMXsave = vsv; /* If no vector, chain us first */
  916                                 else {
  917                                 
  918                                         vsvn = vsvo = thr_act->mact.curctx->VMXsave;    /* Remember first one */
  919                                         
  920                                         while (vsvn) {                                                  /* Go until we hit the end */
  921                                                 vsvo = vsvn;                                            /* Remember the previous one */
  922                                                 vsvn = CAST_DOWN(savearea_vec *, vsvo->save_hdr.save_prev);     /* Skip on to the next */
  923                                         }
  924                                         
  925                                         vsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv);  /* Queue us on in */
  926                                 }
  927                                 
  928                         }
  929                         
  930                         vs = (struct ppc_vector_state *) tstate;                /* Point to source */
  931                 
  932                         bcopy((char *)vs, (char *)&vsv->save_vr0, 32*16);       /* 32 registers plus status and validity and pad */
  933                         vsv->save_vrvalid = vs->save_vrvalid;                   /* Set validity bits */
  934                         
  935                         
  936                         for(i = 0; i < 4; i++) genuser->save_vscr[i] = vs->save_vscr[i];        /* Set value for vscr */
  937                 
  938                         return KERN_SUCCESS;
  939                         
  940                 
  941                 default:
  942                         return KERN_INVALID_ARGUMENT;
  943     }
  944 }
  945 
  946 /*
  947  *              Duplicates the context of one thread into a new one.
  948  *              The new thread is assumed to be new and have no user state contexts except maybe a general one.
  949  *              We also assume that the old thread can't be running anywhere.
  950  *
  951  *              We're only going to be duplicating user context here.  That means that we will have to 
  952  *              eliminate any floating point or vector kernel contexts and carry across the user state ones.
  953  */
  954 
  955 kern_return_t machine_thread_dup(thread_act_t self, thread_act_t target) {
  956 
  957         savearea                *sv, *osv; 
  958         savearea_fpu    *fsv, *fsvn;
  959         savearea_vec    *vsv, *vsvn;
  960         unsigned int    spc, i, *srs;
  961         
  962         fpu_save(self->mact.curctx);                                            /* Make certain floating point state is all saved */
  963         vec_save(self->mact.curctx);                                            /* Make certain the vector state is all saved */
  964         
  965         sv = get_user_regs(target);                                             /* Allocate and initialze context in the new activation */
  966         
  967         osv = find_user_regs(self);                                             /* Find the original context */
  968         if(!osv)
  969                 return (KERN_FAILURE);
  970         
  971         bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)),      /* Copy everything but the headers */
  972                 (char *)((unsigned int)sv + sizeof(savearea_comm)), 
  973                 sizeof(struct savearea) - sizeof(savearea_comm));
  974         
  975         sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));       /* Make certain that floating point and vector are turned off */
  976 
  977         fsv = find_user_fpu(self);                                              /* Get any user floating point */
  978         
  979         target->mact.curctx->FPUsave = 0;                                       /* Assume no floating point */
  980 
  981         if(fsv) {                                                                               /* Did we find one? */
  982                 fsvn = (savearea_fpu *)save_alloc();            /* If we still don't have one, get a new one */
  983                 fsvn->save_hdr.save_flags = (fsvn->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft); /* Mark as in use as float */
  984                 fsvn->save_hdr.save_act = (struct thread_activation *)target;   /* Point to the activation */
  985                 fsvn->save_hdr.save_prev = 0;                           /* Mark no more */
  986                 fsvn->save_hdr.save_level = 0;                          /* Mark user state */
  987 
  988                 target->mact.curctx->FPUsave = fsvn;                    /* Chain in the floating point */
  989 
  990                 bcopy((char *)((unsigned int)fsv + sizeof(savearea_comm)),      /* Copy everything but the headers */
  991                         (char *)((unsigned int)fsvn + sizeof(savearea_comm)), 
  992                         sizeof(struct savearea) - sizeof(savearea_comm));
  993         }
  994 
  995         vsv = find_user_vec(self);                                              /* Get any user vector */
  996         
  997         target->mact.curctx->VMXsave = 0;                                       /* Assume no vector */
  998 
  999         if(vsv) {                                                                               /* Did we find one? */
 1000                 vsvn = (savearea_vec *)save_alloc();            /* If we still don't have one, get a new one */
 1001                 vsvn->save_hdr.save_flags = (vsvn->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);        /* Mark as in use as float */
 1002                 vsvn->save_hdr.save_act = (struct thread_activation *)target;   /* Point to the activation */
 1003                 vsvn->save_hdr.save_prev = 0;                           /* Mark no more */
 1004                 vsvn->save_hdr.save_level = 0;                          /* Mark user state */
 1005 
 1006                 target->mact.curctx->VMXsave = vsvn;                    /* Chain in the floating point */
 1007 
 1008                 bcopy((char *)((unsigned int)vsv + sizeof(savearea_comm)),      /* Copy everything but the headers */
 1009                         (char *)((unsigned int)vsvn + sizeof(savearea_comm)), 
 1010                         sizeof(struct savearea) - sizeof(savearea_comm));
 1011         }
 1012 
 1013         return (KERN_SUCCESS);
 1014 }
 1015 
 1016 /*
 1017  *              Initializes a fresh set of user state values.  If there is no user state context,
 1018  *              one is created. Floats and VMX are not created. 
 1019  *              
 1020  *              We only set initial values if there was no context found.
 1021  */
 1022 
 1023 savearea *get_user_regs(thread_act_t act) {
 1024 
 1025         savearea                *sv, *osv;
 1026         unsigned int    spc, i, *srs;
 1027 
 1028         if (act->mact.upcb)
 1029                 return  act->mact.upcb;
 1030 
 1031         sv = act->mact.pcb;                                                             /* Get the top savearea on the stack */
 1032         osv = 0;                                                                                /* Set no user savearea yet */  
 1033         
 1034         while(sv) {                                                                             /* Find the user context */
 1035                 osv = sv;                                                                       /* Save the last one */
 1036                 sv = CAST_DOWN(savearea *, sv->save_hdr.save_prev);     /* Get the previous context */ 
 1037         }
 1038 
 1039         sv = save_alloc();                                                              /* Get one */
 1040         sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft);   /* Mark as in use as general */
 1041         sv->save_hdr.save_act = (struct thread_activation *)act;        /* Point to the activation */
 1042         sv->save_hdr.save_prev = 0;                                             /* Mark no more */
 1043         sv->save_hdr.save_level = 0;                                    /* Mark user state */
 1044         
 1045         if(osv) {                                                                               /* Did we already have one? */
 1046                 osv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv);            /* Chain us on the end */
 1047         }
 1048         else {                                                                                  /* We are the first */
 1049                 act->mact.pcb = sv;                                                     /* Put it there */
 1050         }
 1051         act->mact.upcb = sv;                                                    /* Set user pcb */
 1052 
 1053         for(i=0; i < 32; i+=2) {                                                /* Fill up with defaults */
 1054                 ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
 1055                 ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
 1056         }
 1057         sv->save_cr     = 0;
 1058         sv->save_xer    = 0;
 1059         sv->save_lr     = (uint64_t)FloatInit;
 1060         sv->save_ctr    = (uint64_t)FloatInit;
 1061         sv->save_srr0   = (uint64_t)FloatInit;
 1062         sv->save_srr1 = (uint64_t)MSR_EXPORT_MASK_SET;
 1063 
 1064         sv->save_fpscr = 0;                                                             /* Clear all floating point exceptions */
 1065 
 1066         sv->save_vrsave = 0;                                                    /* Set the vector save state */
 1067         sv->save_vscr[0] = 0x00000000;                                  
 1068         sv->save_vscr[1] = 0x00000000;                                  
 1069         sv->save_vscr[2] = 0x00000000;                                  
 1070         sv->save_vscr[3] = 0x00010000;                                  /* Disable java mode and clear saturated */
 1071         
 1072         return sv;                                                                              /* Bye bye... */
 1073 }
 1074 
 1075 /*
 1076  *              Find the user state context.  If there is no user state context,
 1077  *              we just return a 0.
 1078  */
 1079 
 1080 savearea *find_user_regs(thread_act_t act) {
 1081         return act->mact.upcb;
 1082 }
 1083 
 1084 /* The name of this call is something of a misnomer since the mact.pcb can 
 1085  * contain chained saveareas, but it will do for now..
 1086  */
 1087 savearea *find_kern_regs(thread_act_t act) {
 1088         return act->mact.pcb;
 1089 }
 1090 
 1091 /*
 1092  *              Find the user state floating point context.  If there is no user state context,
 1093  *              we just return a 0.
 1094  */
 1095 
 1096 savearea_fpu *find_user_fpu(thread_act_t act) {
 1097 
 1098         savearea_fpu    *fsv;
 1099 
 1100         fsv = act->mact.curctx->FPUsave;                                /* Get the start of the floating point chain */
 1101         
 1102         while(fsv) {                                                                    /* Look until the end or we find it */
 1103                 if(!(fsv->save_hdr.save_level)) break;          /* Is the the user state stuff? (the level is 0 if so) */       
 1104                 fsv = CAST_DOWN(savearea_fpu *, fsv->save_hdr.save_prev);       /* Try the previous one */ 
 1105         }
 1106         
 1107         return fsv;                                                                             /* Bye bye... */
 1108 }
 1109 
 1110 /*
 1111  *              Find the user state vector context.  If there is no user state context,
 1112  *              we just return a 0.
 1113  */
 1114 
 1115 savearea_vec *find_user_vec(thread_act_t act) {
 1116 
 1117         savearea_vec    *vsv;
 1118 
 1119         vsv = act->mact.curctx->VMXsave;                                /* Get the start of the vector chain */
 1120         
 1121         while(vsv) {                                                                    /* Look until the end or we find it */
 1122                 if(!(vsv->save_hdr.save_level)) break;          /* Is the the user state stuff? (the level is 0 if so) */       
 1123                 vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev);       /* Try the previous one */ 
 1124         }
 1125         
 1126         return vsv;                                                                             /* Bye bye... */
 1127 }
 1128 /*
 1129  *              Find the user state vector context for the current thread.  If there is no user state context,
 1130  *              we just return a 0.
 1131  */
 1132 
 1133 savearea_vec *find_user_vec_curr(void) {
 1134 
 1135         savearea_vec    *vsv;
 1136         thread_act_t    act;
 1137         
 1138         act = current_act();                                                    /* Get the current activation */                        
 1139         
 1140         vec_save(act->mact.curctx);                                             /* Force save if live */
 1141 
 1142         vsv = act->mact.curctx->VMXsave;                                /* Get the start of the vector chain */
 1143         
 1144         while(vsv) {                                                                    /* Look until the end or we find it */
 1145                 if(!(vsv->save_hdr.save_level)) break;          /* Is the the user state stuff? (the level is 0 if so) */       
 1146                 vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev);       /* Try the previous one */ 
 1147         }
 1148         
 1149         return vsv;                                                                             /* Bye bye... */
 1150 }
 1151 
 1152 /*
 1153  * thread_userstack:
 1154  *
 1155  * Return the user stack pointer from the machine
 1156  * dependent thread state info.
 1157  */
 1158 kern_return_t
 1159 thread_userstack(
 1160     thread_t            thread,
 1161     int                 flavor,
 1162     thread_state_t      tstate,
 1163     unsigned int        count,
 1164     vm_offset_t         *user_stack,
 1165         int                                     *customstack
 1166 )
 1167 {
 1168         struct ppc_thread_state *state;
 1169 
 1170         /*
 1171          * Set a default.
 1172          */
 1173         if (*user_stack == 0)
 1174                 *user_stack = USRSTACK;
 1175                 if (customstack)
 1176                         *customstack = 0;
 1177 
 1178         switch (flavor) {
 1179         case PPC_THREAD_STATE:
 1180                 if (count < PPC_THREAD_STATE_COUNT)
 1181                         return (KERN_INVALID_ARGUMENT);
 1182  
 1183                 state = (struct ppc_thread_state *) tstate;
 1184     
 1185                 /*
 1186                  * If a valid user stack is specified, use it.
 1187                  */
 1188                 *user_stack = state->r1 ? state->r1: USRSTACK;
 1189 
 1190                                 if (customstack && state->r1)
 1191                                         *customstack = 1;
 1192                                         
 1193                 break;
 1194         default :
 1195                 return (KERN_INVALID_ARGUMENT);
 1196         }
 1197                 
 1198         return (KERN_SUCCESS);
 1199 }    
 1200 
 1201 
 1202 /*
 1203  * thread_setuserstack:
 1204  *
 1205  * Sets the user stack pointer into the machine
 1206  * dependent thread state info.
 1207  */
 1208 void thread_setuserstack(thread_act_t act, unsigned int user_stack)
 1209 {
 1210         savearea *sv;
 1211         
 1212         sv = get_user_regs(act);                /* Get the user state registers */
 1213         
 1214         sv->save_r1 = (uint64_t)user_stack;
 1215         
 1216         return;
 1217 }    
 1218 
 1219 /*
 1220  * thread_adjuserstack:
 1221  *
 1222  * Returns the adjusted user stack pointer from the machine
 1223  * dependent thread state info.
 1224  */
 1225 unsigned int thread_adjuserstack(thread_act_t act, int adjust)
 1226 {
 1227         savearea *sv;
 1228         
 1229         sv = get_user_regs(act);                /* Get the user state registers */
 1230         
 1231         sv->save_r1 += adjust;                  /* Adjust the stack */
 1232         
 1233         return (unsigned int)sv->save_r1;       /* Return the adjusted stack */
 1234         
 1235 }    
 1236 
 1237 /*
 1238  * thread_setentrypoint:
 1239  *
 1240  * Sets the user PC into the machine
 1241  * dependent thread state info.
 1242  */
 1243 
 1244 void thread_setentrypoint(thread_act_t act, unsigned int entry)
 1245 {
 1246         savearea *sv;
 1247         
 1248         sv = get_user_regs(act);                /* Get the user state registers */
 1249         
 1250         sv->save_srr0 = (uint64_t)entry;
 1251         
 1252         return;
 1253 }    
 1254 
 1255 kern_return_t
 1256 thread_entrypoint(
 1257     thread_t            thread,
 1258     int                 flavor,
 1259     thread_state_t      tstate,
 1260     unsigned int        count,
 1261     vm_offset_t         *entry_point
 1262 )
 1263 { 
 1264     struct ppc_thread_state     *state;
 1265  
 1266     /*
 1267      * Set a default.
 1268      */
 1269     if (*entry_point == 0)
 1270         *entry_point = VM_MIN_ADDRESS;
 1271     
 1272     switch (flavor) {   
 1273     
 1274     case PPC_THREAD_STATE:
 1275         if (count < PPC_THREAD_STATE_COUNT)
 1276             return (KERN_INVALID_ARGUMENT);
 1277 
 1278         state = (struct ppc_thread_state *) tstate;
 1279 
 1280         /* 
 1281          * If a valid entry point is specified, use it.
 1282          */     
 1283         *entry_point = state->srr0 ? state->srr0: VM_MIN_ADDRESS;
 1284         break; 
 1285     default: 
 1286         return (KERN_INVALID_ARGUMENT);
 1287     }           
 1288  
 1289     return (KERN_SUCCESS);
 1290 }   
 1291 
 1292 unsigned int get_msr_exportmask(void)
 1293 {
 1294         return (MSR_EXPORT_MASK_SET);
 1295 }
 1296 
 1297 unsigned int get_msr_nbits(void)
 1298 {
 1299         return (MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
 1300 }
 1301 unsigned int get_msr_rbits(void)
 1302 {
 1303         return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
 1304 }
 1305 
 1306 void ppc_checkthreadstate(void * tsptr, int flavor)
 1307 {
 1308         if (flavor == PPC_THREAD_STATE64) {
 1309                 struct ppc_thread_state64 *ts64 =(struct ppc_thread_state64 *)tsptr;
 1310 
 1311                 /* Make sure naughty bits are off and necessary bits are on */
 1312                 ts64->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
 1313                 ts64->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
 1314         } else {
 1315                 struct ppc_thread_state *ts =(struct ppc_thread_state *)tsptr;
 1316 
 1317                 /* Make sure naughty bits are off and necessary bits are on */
 1318                 ts->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
 1319                 ts->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
 1320         }
 1321         return;
 1322 }
 1323 
 1324 void  thread_set_child(thread_act_t child, int pid)
 1325 {
 1326         struct savearea *child_state;
 1327         
 1328         child_state = get_user_regs(child);
 1329         
 1330         child_state->save_r3 = (uint_t)pid;
 1331         child_state->save_r4 = 1ULL;
 1332 }
 1333 void  thread_set_parent(thread_act_t parent, int pid)
 1334 {
 1335         struct savearea *parent_state;
 1336         
 1337         parent_state = get_user_regs(parent);
 1338         
 1339         parent_state->save_r3 = (uint64_t)pid;
 1340         parent_state->save_r4 = 0;
 1341 }
 1342 
 1343 /*
 1344  *              Saves the complete context (general, floating point, and vector) of the current activation.
 1345  *              We will collect everything into an opaque block of 1 to 3 saveareas and pass back a 
 1346  *              pointer to that.
 1347  *
 1348  *              The savearea is made to look like it belongs to the source activation.  This needs to 
 1349  *              be adjusted when these contexts are attached to a new activation.
 1350  *
 1351  */
 1352 
 1353 void *act_thread_csave(void) {
 1354 
 1355         savearea                *sv, *osv;
 1356         savearea_fpu    *fsv, *ofsv;
 1357         savearea_vec    *vsv, *ovsv;
 1358         unsigned int    spc, i, *srs;
 1359         
 1360         thread_act_t act;       
 1361         
 1362         act = current_act();                                                    /* Find ourselves */    
 1363         
 1364         fpu_save(act->mact.curctx);                                             /* Make certain floating point state is all saved */
 1365         vec_save(act->mact.curctx);                                             /* Make certain the vector state is all saved */
 1366 
 1367         osv = find_user_regs(act);                                              /* Get our savearea */
 1368 
 1369         if(!osv) {
 1370                 panic("act_thread_csave: attempting to preserve the context of an activation with none (%08X)\n", act);
 1371         }
 1372         
 1373         sv = save_alloc();                                                              /* Get a fresh save area to save into */
 1374         sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft);   /* Mark as in use as general */
 1375         sv->save_hdr.save_act = (struct thread_activation *)act;        /* Point to the activation */
 1376         sv->save_hdr.save_prev = 0;                                             /* Mark no more */
 1377         sv->save_hdr.save_level = 0;                                    /* Mark user state */
 1378         
 1379         
 1380         bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)),      /* Copy everything but the headers */
 1381                 (char *)((unsigned int)sv + sizeof(savearea_comm)), 
 1382                 sizeof(struct savearea) - sizeof(savearea_comm));
 1383         
 1384         sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));       /* Make certain that floating point and vector are turned off */        
 1385         
 1386         sv->save_hdr.save_misc2 = 0xDEBB1ED0;                   /* Eye catcher for debug */
 1387         sv->save_hdr.save_misc3 = 0xE5DA11A5;                   /* Eye catcher for debug */
 1388         
 1389 
 1390         ofsv = find_user_fpu(act);                                              /* Get any user floating point */
 1391 
 1392         sv->save_hdr.save_misc0 = 0;                                    /* Assume no floating point */
 1393 
 1394         if(ofsv) {                                                                              /* Did we find one? */
 1395                 fsv = (savearea_fpu *)save_alloc();                     /* If we still don't have one, get a new one */
 1396                 fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft);   /* Mark as in use as float */
 1397                 fsv->save_hdr.save_act = (struct thread_activation *)act;       /* Point to the activation */
 1398                 fsv->save_hdr.save_prev = 0;                            /* Mark no more */
 1399                 fsv->save_hdr.save_level = 0;                           /* Mark user state */
 1400                 fsv->save_hdr.save_misc2 = 0xDEBB1ED0;          /* Eye catcher for debug */
 1401                 fsv->save_hdr.save_misc3 = 0xE5DA11A5;          /* Eye catcher for debug */
 1402 
 1403                 sv->save_hdr.save_misc0 = (uint64_t)((uintptr_t)fsv);   /* Remember this one */
 1404 
 1405                 bcopy((char *)((unsigned int)ofsv + sizeof(savearea_comm)),     /* Copy everything but the headers */
 1406                         (char *)((unsigned int)fsv + sizeof(savearea_comm)), 
 1407                         sizeof(struct savearea) - sizeof(savearea_comm));
 1408         }
 1409 
 1410         ovsv = find_user_vec(act);                                              /* Get any user vector */
 1411         
 1412         sv->save_hdr.save_misc1 = 0;                                    /* Assume no vector */
 1413 
 1414         if(ovsv) {                                                                              /* Did we find one? */
 1415                 vsv = (savearea_vec *)save_alloc();                     /* If we still don't have one, get a new one */
 1416                 vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);  /* Mark as in use as float */
 1417                 vsv->save_hdr.save_act = (struct thread_activation *)act;       /* Point to the activation */
 1418                 vsv->save_hdr.save_prev = 0;                            /* Mark no more */
 1419                 vsv->save_hdr.save_level = 0;                           /* Mark user state */
 1420                 vsv->save_hdr.save_misc2 = 0xDEBB1ED0;          /* Eye catcher for debug */
 1421                 vsv->save_hdr.save_misc3 = 0xE5DA11A5;          /* Eye catcher for debug */
 1422 
 1423                 sv->save_hdr.save_misc1 = (uint64_t)((uintptr_t)vsv);   /* Chain in the floating point */
 1424 
 1425                 bcopy((char *)((unsigned int)ovsv + sizeof(savearea_comm)),     /* Copy everything but the headers */
 1426                         (char *)((unsigned int)vsv + sizeof(savearea_comm)), 
 1427                         sizeof(struct savearea) - sizeof(savearea_comm));
 1428         }
 1429 
 1430         return (void *)sv;                                                              /* Bye bye... */
 1431 }
 1432 
 1433 
 1434 
 1435 /*
 1436  *              Attaches saved user state context to an activation.  We will replace any
 1437  *              user state context with what is passed in.  The saved context consists of a
 1438  *              savearea that was setup by 
 1439  *              We will collect everything into one savearea and pass that back.
 1440  *
 1441  *              The savearea is made to look like it belongs to the source activation.  This needs to 
 1442  *              be adjusted when these contexts are attached to a new activation.
 1443  *
 1444  */
 1445 
 1446 void act_thread_catt(void *ctx) {
 1447 
 1448         savearea                *sv, *osv, *psv;
 1449         savearea_fpu    *fsv, *ofsv, *pfsv;
 1450         savearea_vec    *vsv, *ovsv, *pvsv;
 1451         unsigned int    spc, i, *srs;
 1452         thread_act_t act;       
 1453         
 1454         sv = (savearea *)ctx;                                                   /* Make this easier for C */
 1455         
 1456         fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0);       /* Get a possible floating point savearea */ 
 1457         vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1);       /* Get a possible vector savearea */ 
 1458         
 1459         if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) {        /* See if valid savearea */
 1460                 panic("act_thread_catt: attempt to attach invalid general context savearea - %08X\n", sv);      /* Die */
 1461         }
 1462 
 1463         if(fsv && ((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5))) {     /* See if valid savearea */
 1464                 panic("act_thread_catt: attempt to attach invalid float context savearea - %08X\n", fsv);       /* Die */
 1465         }
 1466 
 1467         if(vsv && ((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5))) {     /* See if valid savearea */
 1468                 panic("act_thread_catt: attempt to attach invalid vector context savearea - %08X\n", vsv);      /* Die */
 1469         }
 1470 
 1471         act = current_act();                                                    /* Find ourselves */    
 1472 
 1473         toss_live_fpu(act->mact.curctx);                                /* Toss my floating point if live anywhere */
 1474         toss_live_vec(act->mact.curctx);                                /* Toss my vector if live anywhere */
 1475                 
 1476         sv->save_hdr.save_misc2 = 0;                                    /* Eye catcher for debug */
 1477         sv->save_hdr.save_misc3 = 0;                                    /* Eye catcher for debug */
 1478         sv->save_hdr.save_act = (struct thread_activation *)act;        /* Set us as owner */
 1479         
 1480         spc = (unsigned int)act->map->pmap->space;              /* Get the space we're in */
 1481         
 1482         osv = act->mact.pcb;                                                    /* Get the top general savearea */
 1483         psv = 0;
 1484         while(osv) {                                                                    /* Any saved state? */
 1485                 if(osv->save_srr1 & MASK(MSR_PR)) break;        /* Leave if this is user state */
 1486                 psv = osv;                                                                      /* Save previous savearea address */
 1487                 osv = CAST_DOWN(savearea *, osv->save_hdr.save_prev);   /* Get one underneath our's */
 1488         }
 1489         
 1490         if(osv) {                                                                               /* Did we find one? */
 1491                 if(psv) psv->save_hdr.save_prev = 0;            /* Yes, clear pointer to it (it should always be last) or */    
 1492                 else act->mact.pcb = 0;                                         /* to the start if the only one */
 1493 
 1494                 save_release(osv);                                                      /* Nope, release it */
 1495                 
 1496         }
 1497 
 1498         if(psv) psv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv);    /* Chain us to the end or */
 1499         else act->mact.pcb = (pcb_t)sv;                                 /* to the start if the only one */
 1500         act->mact.upcb = (pcb_t)sv;                                             /* Set the user pcb */
 1501         
 1502         ovsv = act->mact.curctx->VMXsave;                               /* Get the top vector savearea */
 1503         
 1504         pvsv = 0;
 1505         while(ovsv) {                                                                   /* Any VMX saved state? */
 1506                 if(!(ovsv->save_hdr.save_level)) break;         /* Leave if this is user state */
 1507                 pvsv = ovsv;                                                            /* Save previous savearea address */
 1508                 ovsv = CAST_DOWN(savearea_vec *, ovsv->save_hdr.save_prev);     /* Get one underneath our's */ 
 1509         }
 1510         
 1511         if(ovsv) {                                                                              /* Did we find one? */
 1512                 if(pvsv) pvsv->save_hdr.save_prev = 0;          /* Yes, clear pointer to it (it should always be last) or */    
 1513                 else act->mact.curctx->VMXsave = 0;                     /* to the start if the only one */
 1514 
 1515                 save_release((savearea *)ovsv);                         /* Nope, release it */
 1516         }
 1517         
 1518         if(vsv) {                                                                               /* Are we sticking any vector on this one? */
 1519                 if(pvsv) pvsv->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv); /* Yes, chain us to the end or */
 1520                 else act->mact.curctx->VMXsave = vsv;           /* to the start if the only one */
 1521 
 1522                 vsv->save_hdr.save_misc2 = 0;                           /* Eye catcher for debug */
 1523                 vsv->save_hdr.save_misc3 = 0;                           /* Eye catcher for debug */
 1524                 vsv->save_hdr.save_act = (struct thread_activation *)act;       /* Set us as owner */
 1525         }
 1526         
 1527         ofsv = act->mact.curctx->FPUsave;                               /* Get the top float savearea */
 1528         
 1529         pfsv = 0;
 1530         while(ofsv) {                                                                   /* Any float saved state? */
 1531                 if(!(ofsv->save_hdr.save_level)) break;         /* Leave if this is user state */
 1532                 pfsv = ofsv;                                                            /* Save previous savearea address */
 1533                 ofsv = CAST_DOWN(savearea_fpu *, ofsv->save_hdr.save_prev);     /* Get one underneath our's */
 1534         }
 1535         
 1536         if(ofsv) {                                                                              /* Did we find one? */
 1537                 if(pfsv) pfsv->save_hdr.save_prev = 0;          /* Yes, clear pointer to it (it should always be last) or */    
 1538                 else act->mact.curctx->FPUsave = 0;                     /* to the start if the only one */
 1539 
 1540                 save_release((savearea *)ofsv);                         /* Nope, release it */
 1541         }
 1542         
 1543         if(fsv) {                                                                               /* Are we sticking any vector on this one? */
 1544                 if(pfsv) pfsv->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv); /* Yes, chain us to the end or */
 1545                 else act->mact.curctx->FPUsave = fsv;           /* to the start if the only one */
 1546 
 1547                 fsv->save_hdr.save_misc2 = 0;                           /* Eye catcher for debug */
 1548                 fsv->save_hdr.save_misc3 = 0;                           /* Eye catcher for debug */
 1549                 fsv->save_hdr.save_act = (struct thread_activation *)act;       /* Set us as owner */
 1550         }
 1551         
 1552 }
 1553 
 1554 
 1555 
 1556 /*
 1557  *              Releases saved context.  We need this because the saved context is opague.
 1558  *              be adjusted when these contexts are attached to a new activation.
 1559  *
 1560  */
 1561 
 1562 void act_thread_cfree(void *ctx) {
 1563 
 1564         savearea                *sv, *osv;
 1565         savearea_fpu    *fsv, *ofsv;
 1566         savearea_vec    *vsv, *ovsv, *pvsv;
 1567 
 1568         sv = (savearea *)ctx;                                                   /* Make this easier for C */
 1569         
 1570         fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0);       /* Get a possible floating point savearea */ 
 1571         vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1);       /* Get a possible vector savearea */ 
 1572         
 1573         if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) {        /* See if valid savearea */
 1574                 panic("act_thread_cfree: attempt to detatch invalid general context savearea - %08X\n", sv);    /* Die */
 1575         }
 1576         
 1577         save_release(sv);                                                               /* Toss the general savearea */
 1578 
 1579         if(fsv) {                                                                               /* See if there is any saved floating point */ 
 1580                 if((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5)) {      /* See if valid savearea */
 1581                         panic("act_thread_cfree: attempt to detatch invalid float context savearea - %08X\n", fsv);     /* Die */
 1582                 }
 1583                 
 1584                 save_release((savearea *)fsv);                          /* Toss saved context */
 1585         }
 1586 
 1587         if(vsv) {                                                                               /* See if there is any saved floating point */ 
 1588                 if((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5)) {      /* See if valid savearea */
 1589                         panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %08X\n", vsv);    /* Die */
 1590                 }
 1591                 
 1592                 save_release((savearea *)vsv);                          /* Toss saved context */
 1593         }
 1594         
 1595         return;
 1596 }
 1597 
 1598 /*
 1599  * thread_enable_fpe:
 1600  *
 1601  * enables or disables floating point exceptions for the thread.
 1602  * returns old state
 1603  */
 1604 int thread_enable_fpe(thread_act_t act, int onoff)
 1605 {
 1606         savearea *sv;
 1607         unsigned int oldmsr;
 1608 
 1609         sv = find_user_regs(act);                                               /* Find the user registers */
 1610         if(!sv) sv = get_user_regs(act);                                /* Didn't find any, allocate and initialize o
 1611 ne */
 1612 
 1613         oldmsr = sv->save_srr1;                                                 /* Get the old msr */
 1614 
 1615         if(onoff) sv->save_srr1 = oldmsr | MASK(MSR_FE0) | MASK(MSR_FE1);       /* Flip on precise FP exceptions */
 1616         else sv->save_srr1 = oldmsr & ~(MASK(MSR_FE0) | MASK(MSR_FE1)); /* Flip on precise FP exceptions */
 1617 
 1618         return ((oldmsr & (MASK(MSR_FE0) | MASK(MSR_FE1))) != 0);       /* Return if it was enabled or not */
 1619 }   

Cache object: dcfb51629b453ba674d8ff79761fedf0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.