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

Cache object: a76a3567942475335dfed107e59446bd


[ 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.