]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/ppc/status.c
xnu-1486.2.11.tar.gz
[apple/xnu.git] / osfmk / ppc / status.c
index f716068bc66a4cc6acee9d7f6ca38a90ae38567f..50fee6015f694d4bedbf17b718357fe2b15237ae 100644 (file)
@@ -1,23 +1,29 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
  * 
- * @APPLE_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  * @OSF_COPYRIGHT@
  */
 
 #include <kern/thread.h>
-#include <kern/thread_act.h>
 #include <kern/misc_protos.h>
 #include <mach/ppc/thread_status.h>
 #include <ppc/proc_reg.h>
+#include <ppc/cpu_internal.h>
 #include <ppc/exception.h>
-#include <ppc/fpu_protos.h>
 #include <ppc/misc_protos.h>
+#include <ppc/fpu_protos.h>
 #include <ppc/savearea.h>
-#include <ppc/thread_act.h>
+#include <ppc/thread.h>
 #include <ppc/Firmware.h>
 
+typedef        unsigned int fixpt_t;   /* XXX <sys/resource.h> not self contained */
+#include <ppc/vmparam.h>       /* USRSTACK, etc. */
+
 #include <vm/vm_map.h>
 
 extern unsigned int killprint;
 extern double FloatInit;
 extern unsigned long QNaNbarbarian[4];
-extern void thread_bootstrap_return(void);
-extern struct   Saveanchor saveanchor;
-extern int      real_ncpus;                     /* Number of actual CPUs */
-
-
-struct ppc_saved_state * get_user_regs(thread_act_t);
-
-#define       USRSTACK        0xc0000000
 
 kern_return_t
 thread_userstack(
@@ -56,7 +57,7 @@ thread_userstack(
     int,
     thread_state_t,
     unsigned int,
-    vm_offset_t *,
+       mach_vm_offset_t *,
        int *
 );
 
@@ -66,23 +67,29 @@ thread_entrypoint(
     int,
     thread_state_t,
     unsigned int,
-    vm_offset_t *
+    mach_vm_offset_t *
 ); 
 
 unsigned int get_msr_exportmask(void);
 unsigned int get_msr_nbits(void);
 unsigned int get_msr_rbits(void);
-void thread_set_child(thread_act_t child, int pid);
-void thread_set_parent(thread_act_t parent, int pid);
+void ppc_checkthreadstate(void *, int);
+void thread_set_child(thread_t child, int pid);
+void thread_set_parent(thread_t parent, int pid);
+void thread_set_cthreadself(thread_t thread, uint64_t pself, int isLP64);
                
 /*
  * Maps state flavor to number of words in the state:
  */
-unsigned int state_count[] = {
+/* __private_extern__ */
+unsigned int _MachineStateCount[] = {
        /* FLAVOR_LIST */ 0,
        PPC_THREAD_STATE_COUNT,
        PPC_FLOAT_STATE_COUNT,
        PPC_EXCEPTION_STATE_COUNT,
+       PPC_VECTOR_STATE_COUNT,
+       PPC_THREAD_STATE64_COUNT,
+       PPC_EXCEPTION_STATE64_COUNT,
 };
 
 /*
@@ -92,42 +99,44 @@ unsigned int state_count[] = {
  */
 
 kern_return_t 
-act_machine_get_state(
-                     thread_act_t           thr_act,
-                     thread_flavor_t        flavor,
-                     thread_state_t         tstate,
-                     mach_msg_type_number_t *count)
+machine_thread_get_state(
+       thread_t                                thread,
+       thread_flavor_t                 flavor,
+       thread_state_t                  tstate,
+       mach_msg_type_number_t  *count)
 {
        
        register struct savearea *sv;                                           /* Pointer to the context savearea */
+       register savearea_fpu *fsv;
+       register savearea_vec *vsv;
+       struct savearea *genuser;
        int i, j;
        unsigned int vrvalidwrk;
 
        register struct ppc_thread_state *ts;
+       register struct ppc_thread_state64 *xts;
        register struct ppc_exception_state *es;
+       register struct ppc_exception_state64 *xes;
        register struct ppc_float_state *fs;
        register struct ppc_vector_state *vs;
        
-#if    MACH_ASSERT
-    if (watchacts & WA_STATE)
-       printf("act_%x act_machine_get_state(thr_act=%x,flav=%x,st=%x,cnt@%x=%x)\n",
-              current_act(), thr_act, flavor, tstate,
-              count, (count ? *count : 0));
-#endif /* MACH_ASSERT */
-
+       genuser = find_user_regs(thread);
 
        switch (flavor) {
                
                case THREAD_STATE_FLAVOR_LIST:
                        
-                       if (*count < 3)  {
+                       if (*count < 6)  {
                                return (KERN_INVALID_ARGUMENT);
                        }
                
                        tstate[0] = PPC_THREAD_STATE;
                        tstate[1] = PPC_FLOAT_STATE;
                        tstate[2] = PPC_EXCEPTION_STATE;
-                       *count = 3;
+                       tstate[3] = PPC_VECTOR_STATE;
+                       tstate[4] = PPC_THREAD_STATE64;
+                       tstate[5] = PPC_EXCEPTION_STATE64;
+                       *count = 6;
                
                        return KERN_SUCCESS;
        
@@ -139,59 +148,53 @@ act_machine_get_state(
                
                        ts = (struct ppc_thread_state *) tstate;
 
-                       sv = (savearea *)(thr_act->mact.pcb);                   /* Start with the normal savearea */
-                       while(sv) {                                                                             /* Find the user context */
-                               if(sv->save_srr1 & MASK(MSR_PR)) {                      /* Are we looking at the user context? */
-                                       break;                                                                  /* Outta here */
-                               }
-                               sv = sv->save_prev;                                                     /* Back chain */
-                       }
-               
+                       sv = genuser;                                                                   /* Copy this over */
+                       
                        if(sv) {                                                                                /* Is there a save area yet? */
-                               ts->r0  = sv->save_r0;
-                               ts->r1  = sv->save_r1;
-                               ts->r2  = sv->save_r2;
-                               ts->r3  = sv->save_r3;
-                               ts->r4  = sv->save_r4;
-                               ts->r5  = sv->save_r5;
-                               ts->r6  = sv->save_r6;
-                               ts->r7  = sv->save_r7;
-                               ts->r8  = sv->save_r8;
-                               ts->r9  = sv->save_r9;
-                               ts->r10 = sv->save_r10;
-                               ts->r11 = sv->save_r11;
-                               ts->r12 = sv->save_r12;
-                               ts->r13 = sv->save_r13;
-                               ts->r14 = sv->save_r14;
-                               ts->r15 = sv->save_r15;
-                               ts->r16 = sv->save_r16;
-                               ts->r17 = sv->save_r17;
-                               ts->r18 = sv->save_r18;
-                               ts->r19 = sv->save_r19;
-                               ts->r20 = sv->save_r20;
-                               ts->r21 = sv->save_r21;
-                               ts->r22 = sv->save_r22;
-                               ts->r23 = sv->save_r23;
-                               ts->r24 = sv->save_r24;
-                               ts->r25 = sv->save_r25;
-                               ts->r26 = sv->save_r26;
-                               ts->r27 = sv->save_r27;
-                               ts->r28 = sv->save_r28;
-                               ts->r29 = sv->save_r29;
-                               ts->r30 = sv->save_r30;
-                               ts->r31 = sv->save_r31;
-                               ts->cr  = sv->save_cr;
-                               ts->xer = sv->save_xer;
-                               ts->lr  = sv->save_lr;
-                               ts->ctr = sv->save_ctr;
-                               ts->srr0 = sv->save_srr0;
-                               ts->srr1 = sv->save_srr1;
-                               ts->mq  = sv->save_mq;                          /* MQ register (601 only) */
-                               ts->vrsave      = sv->save_vrsave;              /* VRSAVE register (Altivec only) */
+                               ts->r0  = (unsigned int)sv->save_r0;
+                               ts->r1  = (unsigned int)sv->save_r1;
+                               ts->r2  = (unsigned int)sv->save_r2;
+                               ts->r3  = (unsigned int)sv->save_r3;
+                               ts->r4  = (unsigned int)sv->save_r4;
+                               ts->r5  = (unsigned int)sv->save_r5;
+                               ts->r6  = (unsigned int)sv->save_r6;
+                               ts->r7  = (unsigned int)sv->save_r7;
+                               ts->r8  = (unsigned int)sv->save_r8;
+                               ts->r9  = (unsigned int)sv->save_r9;
+                               ts->r10 = (unsigned int)sv->save_r10;
+                               ts->r11 = (unsigned int)sv->save_r11;
+                               ts->r12 = (unsigned int)sv->save_r12;
+                               ts->r13 = (unsigned int)sv->save_r13;
+                               ts->r14 = (unsigned int)sv->save_r14;
+                               ts->r15 = (unsigned int)sv->save_r15;
+                               ts->r16 = (unsigned int)sv->save_r16;
+                               ts->r17 = (unsigned int)sv->save_r17;
+                               ts->r18 = (unsigned int)sv->save_r18;
+                               ts->r19 = (unsigned int)sv->save_r19;
+                               ts->r20 = (unsigned int)sv->save_r20;
+                               ts->r21 = (unsigned int)sv->save_r21;
+                               ts->r22 = (unsigned int)sv->save_r22;
+                               ts->r23 = (unsigned int)sv->save_r23;
+                               ts->r24 = (unsigned int)sv->save_r24;
+                               ts->r25 = (unsigned int)sv->save_r25;
+                               ts->r26 = (unsigned int)sv->save_r26;
+                               ts->r27 = (unsigned int)sv->save_r27;
+                               ts->r28 = (unsigned int)sv->save_r28;
+                               ts->r29 = (unsigned int)sv->save_r29;
+                               ts->r30 = (unsigned int)sv->save_r30;
+                               ts->r31 = (unsigned int)sv->save_r31;
+                               ts->cr  = (unsigned int)sv->save_cr;
+                               ts->xer = (unsigned int)sv->save_xer;
+                               ts->lr  = (unsigned int)sv->save_lr;
+                               ts->ctr = (unsigned int)sv->save_ctr;
+                               ts->srr0 = (unsigned int)sv->save_srr0;
+                               ts->srr1 = (unsigned int)sv->save_srr1;
+                               ts->mq  = 0;                                                    /* MQ register (601 only) */
+                               ts->vrsave      = (unsigned int)sv->save_vrsave;                        /* VRSAVE register (Altivec only) */
                        }
-                       else {                                                                  /* No user state yet. Save seemingly random values. */
+                       else {                                                                          /* No user state yet. Save seemingly random values. */
                                                
-                               for(i=0; i < 32; i+=2) {                        /* Fill up with defaults */
+                               for(i=0; i < 32; i+=2) {                                /* Fill up with defaults */
                                        ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
                                        ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
                                }
@@ -202,10 +205,81 @@ act_machine_get_state(
                                ts->srr0        = ((unsigned int *)&FloatInit)[0];
                                ts->srr1 = MSR_EXPORT_MASK_SET;
                                ts->mq  = 0;
-                               ts->vrsave      = 0;                                    /* VRSAVE register (Altivec only) */
+                               ts->vrsave      = 0;                                            /* VRSAVE register (Altivec only) */
                        }
                
-                       *count = PPC_THREAD_STATE_COUNT;                /* Pass back the amount we actually copied */
+                       *count = PPC_THREAD_STATE_COUNT;                        /* Pass back the amount we actually copied */
+                       return KERN_SUCCESS;
+       
+       
+               case PPC_THREAD_STATE64:
+       
+                       if (*count < PPC_THREAD_STATE64_COUNT) {        /* Is the count ok? */
+                               return KERN_INVALID_ARGUMENT;
+                       }
+               
+                       xts = (struct ppc_thread_state64 *) tstate;
+
+                       sv = genuser;                                                           /* Copy this over */
+                       
+                       if(sv) {                                                                        /* Is there a save area yet? */
+                               xts->r0         = sv->save_r0;
+                               xts->r1         = sv->save_r1;
+                               xts->r2         = sv->save_r2;
+                               xts->r3         = sv->save_r3;
+                               xts->r4         = sv->save_r4;
+                               xts->r5         = sv->save_r5;
+                               xts->r6         = sv->save_r6;
+                               xts->r7         = sv->save_r7;
+                               xts->r8         = sv->save_r8;
+                               xts->r9         = sv->save_r9;
+                               xts->r10        = sv->save_r10;
+                               xts->r11        = sv->save_r11;
+                               xts->r12        = sv->save_r12;
+                               xts->r13        = sv->save_r13;
+                               xts->r14        = sv->save_r14;
+                               xts->r15        = sv->save_r15;
+                               xts->r16        = sv->save_r16;
+                               xts->r17        = sv->save_r17;
+                               xts->r18        = sv->save_r18;
+                               xts->r19        = sv->save_r19;
+                               xts->r20        = sv->save_r20;
+                               xts->r21        = sv->save_r21;
+                               xts->r22        = sv->save_r22;
+                               xts->r23        = sv->save_r23;
+                               xts->r24        = sv->save_r24;
+                               xts->r25        = sv->save_r25;
+                               xts->r26        = sv->save_r26;
+                               xts->r27        = sv->save_r27;
+                               xts->r28        = sv->save_r28;
+                               xts->r29        = sv->save_r29;
+                               xts->r30        = sv->save_r30;
+                               xts->r31        = sv->save_r31;
+                               xts->cr         = sv->save_cr;
+                               xts->xer        = sv->save_xer;
+                               xts->lr         = sv->save_lr;
+                               xts->ctr        = sv->save_ctr;
+                               xts->srr0       = sv->save_srr0;
+                               xts->srr1       = sv->save_srr1;
+                               xts->vrsave     = sv->save_vrsave;                      /* VRSAVE register (Altivec only) */
+                       }
+                       else {                                                                          /* No user state yet. Save seemingly random values. */
+                                               
+                               for(i=0; i < 32; i++) {                                 /* Fill up with defaults */
+                                       ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
+                               }
+                               xts->cr         = 0;
+                               xts->xer        = 0;
+                               xts->lr         = ((unsigned long long *)&FloatInit)[0];
+                               xts->ctr        = ((unsigned long long *)&FloatInit)[0];
+                               xts->srr0       = ((unsigned long long *)&FloatInit)[0];
+                               xts->srr1       = MSR_EXPORT_MASK_SET;
+                               if(task_has_64BitAddr(thread->task)) 
+                                       xts->srr1 |= (uint64_t)MASK32(MSR_SF) << 32;    /* If 64-bit task, force 64-bit mode */
+                               xts->vrsave     = 0;                                            /* VRSAVE register (Altivec only) */
+                       }
+               
+                       *count = PPC_THREAD_STATE64_COUNT;                      /* Pass back the amount we actually copied */
                        return KERN_SUCCESS;
        
                case PPC_EXCEPTION_STATE:
@@ -215,17 +289,10 @@ act_machine_get_state(
                        }
                
                        es = (struct ppc_exception_state *) tstate;
+                       sv = genuser;                                                           /* Copy this over */
                
-                       sv = (savearea *)(thr_act->mact.pcb);                   /* Start with the normal savearea */
-                       while(sv) {                                                                             /* Find the user context */
-                               if(sv->save_srr1 & MASK(MSR_PR)) {                      /* Are we looking at the user context? */
-                                       break;                                                                  /* Outta here */
-                               }
-                               sv = sv->save_prev;                                                     /* Back chain */
-                       }
-
                        if(sv) {                                                                        /* See if valid state yet */
-                               es->dar = sv->save_dar;
+                               es->dar = (unsigned int)sv->save_dar;
                                es->dsisr = sv->save_dsisr;
                                es->exception = sv->save_exception;
                        }
@@ -238,26 +305,46 @@ act_machine_get_state(
                        *count = PPC_EXCEPTION_STATE_COUNT;
                        return KERN_SUCCESS;
        
+               case PPC_EXCEPTION_STATE64:
+       
+                       if (*count < PPC_EXCEPTION_STATE64_COUNT) {
+                               return KERN_INVALID_ARGUMENT;
+                       }
+               
+                       xes = (struct ppc_exception_state64 *) tstate;
+                       sv = genuser;                                                           /* Copy this over */
+               
+                       if(sv) {                                                                        /* See if valid state yet */
+                               xes->dar = sv->save_dar;
+                               xes->dsisr = sv->save_dsisr;
+                               xes->exception = sv->save_exception;
+                       }
+                       else {                                                                          /* Nope, not yet */
+                               xes->dar = 0;
+                               xes->dsisr = 0;
+                               xes->exception = ((unsigned int *)&FloatInit)[0];
+                       }
+               
+                       *count = PPC_EXCEPTION_STATE64_COUNT;
+                       return KERN_SUCCESS;
+       
                case PPC_FLOAT_STATE: 
                
                        if (*count < PPC_FLOAT_STATE_COUNT)  {
                                return KERN_INVALID_ARGUMENT;
                        }
                
-                       fpu_save(thr_act);                                                      /* Just in case it's live, save it */
+                       fpu_save(thread->machine.curctx);                               /* Just in case it's live, save it */
                
                        fs = (struct ppc_float_state *) tstate;         /* Point to destination */
                        
-                       sv = (savearea *)(thr_act->mact.FPU_pcb);       /* Start with the top FPU savearea */
-                       while(sv) {                                                                     /* Find the user context */
-                               if(!sv->save_level_fp) {                                /* Are we looking at the user context? */
-                                       break;                                                          /* Outta here */
-                               }
-                               sv = sv->save_prev_float;                               /* Back chain */
-                       }
+                       fsv = find_user_fpu(thread);                            /* Get the user's fpu savearea */
                        
-                       if(sv) {                                                                        /* See if we have any */
-                               bcopy((char *)&sv->save_fp0, (char *)fs, 33*8); /* 32 registers plus status and pad */
+                       if(fsv) {                                                                       /* See if we have any */
+                               bcopy((char *)&fsv->save_fp0, (char *)fs, 32*8); /* 32 registers  */
+                               fs->fpscr_pad   = 0;                                    /* Be clean and tidy */
+                               if(genuser) fs->fpscr = genuser->save_fpscr;    /* Set the fpscr value to general */
+                               else fs->fpscr = 0;                                             /* If no user, initialize this */
                        }
                        else {                                                                          /* No floating point yet */
                        
@@ -278,28 +365,27 @@ act_machine_get_state(
                                return KERN_INVALID_ARGUMENT;
                        }
                
-                       vec_save(thr_act);                                                      /* Just in case it's live, save it */
+                       vec_save(thread->machine.curctx);                               /* Just in case it's live, save it */
                
                        vs = (struct ppc_vector_state *) tstate;        /* Point to destination */
                        
-                       sv = (savearea *)(thr_act->mact.VMX_pcb);       /* Start with the top FPU savearea */
-                       while(sv) {                                                                     /* Find the user context */
-                               if(!sv->save_level_vec) {                               /* Are we looking at the user context? */
-                                       break;                                                          /* Outta here */
-                               }
-                               sv = sv->save_prev_vector;                              /* Back chain */
-                       }
+                       vsv = find_user_vec(thread);                            /* Find the vector savearea */
                        
-                       if(sv) {                                                                        /* See if we have any */
-                               
-                               vrvalidwrk = sv->save_vrvalid;                  /* Get the valid flags */
-                               vs->save_vrvalid = sv->save_vrvalid;    /* Set the valid flags */
-                               for(j=0; j < 4; j++) vs->save_vscr[j] = sv->save_vscr[j];       /* Set value for vscr */
+                       if(vsv) {                                                                       /* See if we have any */
                                
+                               vrvalidwrk = vsv->save_vrvalid;                 /* Get the valid flags */
+                               vs->save_vrvalid = vsv->save_vrvalid;   /* Set the valid flags */
+                               if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j];      /* Set value for vscr */
+                               else {
+                                       vs->save_vscr[0] = 0;                           /* Set an initial value if no general user yet */
+                                       vs->save_vscr[1] = 0;
+                                       vs->save_vscr[2] = 0;
+                                       vs->save_vscr[3] = 0x00010000;          /* Always start with Java mode off */
+                               }
                                for(i=0; i < 32; i++) {                                 /* Copy the saved registers and invalidate the others */
                                        for(j=0; j < 4; j++) {
                                                if(vrvalidwrk & 0x80000000) (vs->save_vr)[i][j] = 
-                                                       ((unsigned int *)&(sv->save_vr0))[(i * 4) + j]; /* We have this register saved */
+                                                       ((unsigned int *)&(vsv->save_vr0))[(i * 4) + j];        /* We have this register saved */
                                                else vs->save_vr[i][j] = QNaNbarbarian[j];      /* Set invalid value */
                                        }
                                        vrvalidwrk = vrvalidwrk << 1;           /* Shift over to the next */
@@ -310,7 +396,14 @@ act_machine_get_state(
                                for(i=0; i < 32; i++) {                                 /* Initialize vector registers */
                                        for(j=0; j < 4; j++) vs->save_vr[i][j] = QNaNbarbarian[j];              /* Initial value */
                                }
-                               for(j=0; j < 4; j++) vs->save_vscr[j] = 0;      /* Initial value */
+                               
+                               if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j];      /* Set value for vscr */
+                               else {
+                                       vs->save_vscr[0] = 0;                           /* Set an initial value if no general user yet */
+                                       vs->save_vscr[1] = 0;
+                                       vs->save_vscr[2] = 0;
+                                       vs->save_vscr[3] = 0x00010000;          /* Always start with Java mode off */
+                               }
                                vs->save_vrvalid = 0;                                   /* Clear the valid flags */
                        }
                        
@@ -324,6 +417,240 @@ act_machine_get_state(
                        return KERN_INVALID_ARGUMENT;
        }
 }
+/* Close cousin of machine_thread_get_state(). 
+ * This function is currently incomplete since we don't really need vector
+ * or FP for the core dump (the save area can be accessed directly if the 
+ * user is so inclined). Also the function name is something of a misnomer,
+ * see the comment above find_kern_regs(). 
+ */
+
+kern_return_t 
+machine_thread_get_kern_state(
+       thread_t                                thread,
+       thread_flavor_t                 flavor,
+       thread_state_t                  tstate,
+       mach_msg_type_number_t  *count)
+{
+       
+       register struct savearea *sv;                                           /* Pointer to the context savearea */
+       struct savearea *genkern;
+       int i;
+
+       register struct ppc_thread_state *ts;
+       register struct ppc_thread_state64 *xts;
+       register struct ppc_exception_state *es;
+       register struct ppc_exception_state64 *xes;
+       
+       genkern = find_kern_regs(thread);
+
+       switch (flavor) {
+               
+               case THREAD_STATE_FLAVOR_LIST:
+                       
+                       if (*count < 6)  {
+                               return (KERN_INVALID_ARGUMENT);
+                       }
+               
+                       tstate[0] = PPC_THREAD_STATE;
+                       tstate[1] = PPC_FLOAT_STATE;
+                       tstate[2] = PPC_EXCEPTION_STATE;
+                       tstate[3] = PPC_VECTOR_STATE;
+                       tstate[4] = PPC_THREAD_STATE64;
+                       tstate[5] = PPC_EXCEPTION_STATE64;
+                       *count = 6;
+               
+                       return KERN_SUCCESS;
+       
+               case PPC_THREAD_STATE:
+       
+                       if (*count < PPC_THREAD_STATE_COUNT) {                  /* Is the count ok? */
+                               return KERN_INVALID_ARGUMENT;
+                       }
+               
+                       ts = (struct ppc_thread_state *) tstate;
+
+                       sv = genkern;                                                                   /* Copy this over */
+                       
+                       if(sv) {                                                                                /* Is there a save area yet? */
+                               ts->r0  = (unsigned int)sv->save_r0;
+                               ts->r1  = (unsigned int)sv->save_r1;
+                               ts->r2  = (unsigned int)sv->save_r2;
+                               ts->r3  = (unsigned int)sv->save_r3;
+                               ts->r4  = (unsigned int)sv->save_r4;
+                               ts->r5  = (unsigned int)sv->save_r5;
+                               ts->r6  = (unsigned int)sv->save_r6;
+                               ts->r7  = (unsigned int)sv->save_r7;
+                               ts->r8  = (unsigned int)sv->save_r8;
+                               ts->r9  = (unsigned int)sv->save_r9;
+                               ts->r10 = (unsigned int)sv->save_r10;
+                               ts->r11 = (unsigned int)sv->save_r11;
+                               ts->r12 = (unsigned int)sv->save_r12;
+                               ts->r13 = (unsigned int)sv->save_r13;
+                               ts->r14 = (unsigned int)sv->save_r14;
+                               ts->r15 = (unsigned int)sv->save_r15;
+                               ts->r16 = (unsigned int)sv->save_r16;
+                               ts->r17 = (unsigned int)sv->save_r17;
+                               ts->r18 = (unsigned int)sv->save_r18;
+                               ts->r19 = (unsigned int)sv->save_r19;
+                               ts->r20 = (unsigned int)sv->save_r20;
+                               ts->r21 = (unsigned int)sv->save_r21;
+                               ts->r22 = (unsigned int)sv->save_r22;
+                               ts->r23 = (unsigned int)sv->save_r23;
+                               ts->r24 = (unsigned int)sv->save_r24;
+                               ts->r25 = (unsigned int)sv->save_r25;
+                               ts->r26 = (unsigned int)sv->save_r26;
+                               ts->r27 = (unsigned int)sv->save_r27;
+                               ts->r28 = (unsigned int)sv->save_r28;
+                               ts->r29 = (unsigned int)sv->save_r29;
+                               ts->r30 = (unsigned int)sv->save_r30;
+                               ts->r31 = (unsigned int)sv->save_r31;
+                               ts->cr  = (unsigned int)sv->save_cr;
+                               ts->xer = (unsigned int)sv->save_xer;
+                               ts->lr  = (unsigned int)sv->save_lr;
+                               ts->ctr = (unsigned int)sv->save_ctr;
+                               ts->srr0 = (unsigned int)sv->save_srr0;
+                               ts->srr1 = (unsigned int)sv->save_srr1;
+                               ts->mq  = 0;                                                    /* MQ register (601 only) */
+                               ts->vrsave      = (unsigned int)sv->save_vrsave;                        /* VRSAVE register (Altivec only) */
+                       }
+                       else {                                                                          /* No state yet. Save seemingly random values. */
+                                               
+                               for(i=0; i < 32; i+=2) {                                /* Fill up with defaults */
+                                       ((unsigned int *)&ts->r0)[i] = ((unsigned int *)&FloatInit)[0];
+                                       ((unsigned int *)&ts->r0)[i+1] = ((unsigned int *)&FloatInit)[1];
+                               }
+                               ts->cr  = 0;
+                               ts->xer = 0;
+                               ts->lr  = ((unsigned int *)&FloatInit)[0];
+                               ts->ctr = ((unsigned int *)&FloatInit)[1];
+                               ts->srr0        = ((unsigned int *)&FloatInit)[0];
+                               ts->srr1 = MSR_EXPORT_MASK_SET;
+                               ts->mq  = 0;
+                               ts->vrsave      = 0;                                            /* VRSAVE register (Altivec only) */
+                       }
+               
+                       *count = PPC_THREAD_STATE_COUNT;                        /* Pass back the amount we actually copied */
+                       return KERN_SUCCESS;
+       
+       
+               case PPC_THREAD_STATE64:
+       
+                       if (*count < PPC_THREAD_STATE64_COUNT) {        /* Is the count ok? */
+                               return KERN_INVALID_ARGUMENT;
+                       }
+               
+                       xts = (struct ppc_thread_state64 *) tstate;
+
+                       sv = genkern;                                                           /* Copy this over */
+                       
+                       if(sv) {                                                                        /* Is there a save area yet? */
+                               xts->r0         = sv->save_r0;
+                               xts->r1         = sv->save_r1;
+                               xts->r2         = sv->save_r2;
+                               xts->r3         = sv->save_r3;
+                               xts->r4         = sv->save_r4;
+                               xts->r5         = sv->save_r5;
+                               xts->r6         = sv->save_r6;
+                               xts->r7         = sv->save_r7;
+                               xts->r8         = sv->save_r8;
+                               xts->r9         = sv->save_r9;
+                               xts->r10        = sv->save_r10;
+                               xts->r11        = sv->save_r11;
+                               xts->r12        = sv->save_r12;
+                               xts->r13        = sv->save_r13;
+                               xts->r14        = sv->save_r14;
+                               xts->r15        = sv->save_r15;
+                               xts->r16        = sv->save_r16;
+                               xts->r17        = sv->save_r17;
+                               xts->r18        = sv->save_r18;
+                               xts->r19        = sv->save_r19;
+                               xts->r20        = sv->save_r20;
+                               xts->r21        = sv->save_r21;
+                               xts->r22        = sv->save_r22;
+                               xts->r23        = sv->save_r23;
+                               xts->r24        = sv->save_r24;
+                               xts->r25        = sv->save_r25;
+                               xts->r26        = sv->save_r26;
+                               xts->r27        = sv->save_r27;
+                               xts->r28        = sv->save_r28;
+                               xts->r29        = sv->save_r29;
+                               xts->r30        = sv->save_r30;
+                               xts->r31        = sv->save_r31;
+                               xts->cr         = sv->save_cr;
+                               xts->xer        = sv->save_xer;
+                               xts->lr         = sv->save_lr;
+                               xts->ctr        = sv->save_ctr;
+                               xts->srr0       = sv->save_srr0;
+                               xts->srr1       = sv->save_srr1;
+                               xts->vrsave     = sv->save_vrsave;                      /* VRSAVE register (Altivec only) */
+                       }
+                       else {                                                                          /* No user state yet. Save seemingly random values. */
+                                               
+                               for(i=0; i < 32; i++) {                                 /* Fill up with defaults */
+                                       ((unsigned long long *)&xts->r0)[i] = ((unsigned long long *)&FloatInit)[0];
+                               }
+                               xts->cr         = 0;
+                               xts->xer        = 0;
+                               xts->lr         = ((unsigned long long *)&FloatInit)[0];
+                               xts->ctr        = ((unsigned long long *)&FloatInit)[0];
+                               xts->srr0       = ((unsigned long long *)&FloatInit)[0];
+                               xts->srr1       = MSR_EXPORT_MASK_SET;
+                               xts->vrsave     = 0;                                            /* VRSAVE register (Altivec only) */
+                       }
+               
+                       *count = PPC_THREAD_STATE64_COUNT;                      /* Pass back the amount we actually copied */
+                       return KERN_SUCCESS;
+       
+               case PPC_EXCEPTION_STATE:
+       
+                       if (*count < PPC_EXCEPTION_STATE_COUNT) {
+                               return KERN_INVALID_ARGUMENT;
+                       }
+               
+                       es = (struct ppc_exception_state *) tstate;
+                       sv = genkern;                                                           /* Copy this over */
+               
+                       if(sv) {                                                                        /* See if valid state yet */
+                               es->dar = (unsigned int)sv->save_dar;
+                               es->dsisr = sv->save_dsisr;
+                               es->exception = sv->save_exception;
+                       }
+                       else {                                                                          /* Nope, not yet */
+                               es->dar = 0;
+                               es->dsisr = 0;
+                               es->exception = ((unsigned int *)&FloatInit)[0];
+                       }
+               
+                       *count = PPC_EXCEPTION_STATE_COUNT;
+                       return KERN_SUCCESS;
+       
+               case PPC_EXCEPTION_STATE64:
+       
+                       if (*count < PPC_EXCEPTION_STATE64_COUNT) {
+                               return KERN_INVALID_ARGUMENT;
+                       }
+               
+                       xes = (struct ppc_exception_state64 *) tstate;
+                       sv = genkern;                                                           /* Copy this over */
+               
+                       if(sv) {                                                                        /* See if valid state yet */
+                               xes->dar = sv->save_dar;
+                               xes->dsisr = sv->save_dsisr;
+                               xes->exception = sv->save_exception;
+                       }
+                       else {                                                                          /* Nope, not yet */
+                               xes->dar = 0;
+                               xes->dsisr = 0;
+                               xes->exception = ((unsigned int *)&FloatInit)[0];
+                       }
+               
+                       *count = PPC_EXCEPTION_STATE64_COUNT;
+                       return KERN_SUCCESS;
+       
+               default:
+                       return KERN_INVALID_ARGUMENT;
+       }
+}
 
 
 /*
@@ -332,30 +659,26 @@ act_machine_get_state(
  * Set the status of the specified thread.
  */
 kern_return_t 
-act_machine_set_state(
-                     thread_act_t           thr_act,
-                     thread_flavor_t        flavor,
-                     thread_state_t         tstate,
-                     mach_msg_type_number_t count)
+machine_thread_set_state(
+       thread_t                                thread,
+       thread_flavor_t                 flavor,
+       thread_state_t                  tstate,
+       mach_msg_type_number_t  count)
 {
   
-       savearea                *sv, *osv, *usv, *ssv;
-       unsigned int    spc, i, *srs, isnew, clgn;
+       struct savearea         *genuser;
+       savearea_fpu    *fsv, *fsvn, *fsvo;
+       savearea_vec    *vsv, *vsvn, *vsvo;
+       unsigned int    i;
+       unsigned int    clgn;
        register struct ppc_thread_state *ts;
+       register struct ppc_thread_state64 *xts;
        register struct ppc_exception_state *es;
+       register struct ppc_exception_state *xes;
        register struct ppc_float_state *fs;
        register struct ppc_vector_state *vs;
-       spl_t                   spl;
        
-    int        kernel_act = thr_act->kernel_loading || thr_act->kernel_loaded;
-
-#if    MACH_ASSERT
-    if (watchacts & WA_STATE)
-       printf("act_%x act_machine_set_state(thr_act=%x,flav=%x,st=%x,cnt=%x)\n",
-              current_act(), thr_act, flavor, tstate, count);
-#endif /* MACH_ASSERT */
-               
-//     dbgTrace((unsigned int)thr_act, (unsigned int)sv, flavor);      /* (TEST/DEBUG) */
+//     dbgTrace((unsigned int)thr_act, (unsigned int)0 /*sv: was never set*/, flavor); /* (TEST/DEBUG) */
 
        clgn = count;                                                                                   /* Get the count */
        
@@ -365,8 +688,13 @@ act_machine_set_state(
                        if (clgn < PPC_THREAD_STATE_COUNT)  {                   /* Is it too short? */
                                return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
                        }
+                       break;
+       
+               case PPC_THREAD_STATE64:
                        
-                       if(clgn > PPC_THREAD_STATE_COUNT) clgn = PPC_THREAD_STATE_COUNT;        /* If too long, pin it at max */
+                       if (clgn < PPC_THREAD_STATE64_COUNT)  {                 /* Is it too short? */
+                               return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
+                       }
                        break;
                        
                case PPC_EXCEPTION_STATE:
@@ -375,7 +703,12 @@ act_machine_set_state(
                                return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
                        }
                        
-                       if(clgn > PPC_EXCEPTION_STATE_COUNT) clgn = PPC_EXCEPTION_STATE_COUNT;  /* If too long, pin it at max */
+               case PPC_EXCEPTION_STATE64:
+                       
+                       if (clgn < PPC_EXCEPTION_STATE64_COUNT)  {              /* Is it too short? */
+                               return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
+                       }
+                       
                        break;
                        
                case PPC_FLOAT_STATE:
@@ -384,7 +717,6 @@ act_machine_set_state(
                                return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
                        }
                        
-                       if(clgn > PPC_FLOAT_STATE_COUNT) clgn = PPC_FLOAT_STATE_COUNT;  /* If too long, pin it at max */
                        break;
                        
 
@@ -394,302 +726,229 @@ act_machine_set_state(
                                return KERN_INVALID_ARGUMENT;                           /* Yeah, just leave... */
                        }
                        
-                       if(clgn > PPC_VECTOR_STATE_COUNT) clgn = PPC_VECTOR_STATE_COUNT;        /* If too long, pin it at max */
                        break;
                        
                default:
                        return KERN_INVALID_ARGUMENT;
        }
-
-    isnew = 0;                                                                                         /* Remember when we make a new one */
        
+       genuser = get_user_regs(thread);                                                /* Find or allocate and initialize one */
+
        switch (flavor) {
                
                case PPC_THREAD_STATE:
-               case PPC_EXCEPTION_STATE:
                                
                        ts = (struct ppc_thread_state *)tstate;
+
+                       genuser->save_r0        = (uint64_t)ts->r0;
+                       genuser->save_r1        = (uint64_t)ts->r1;
+                       genuser->save_r2        = (uint64_t)ts->r2;
+                       genuser->save_r3        = (uint64_t)ts->r3;
+                       genuser->save_r4        = (uint64_t)ts->r4;
+                       genuser->save_r5        = (uint64_t)ts->r5;
+                       genuser->save_r6        = (uint64_t)ts->r6;
+                       genuser->save_r7        = (uint64_t)ts->r7;
+                       genuser->save_r8        = (uint64_t)ts->r8;
+                       genuser->save_r9        = (uint64_t)ts->r9;
+                       genuser->save_r10       = (uint64_t)ts->r10;
+                       genuser->save_r11       = (uint64_t)ts->r11;
+                       genuser->save_r12       = (uint64_t)ts->r12;
+                       genuser->save_r13       = (uint64_t)ts->r13;
+                       genuser->save_r14       = (uint64_t)ts->r14;
+                       genuser->save_r15       = (uint64_t)ts->r15;
+                       genuser->save_r16       = (uint64_t)ts->r16;
+                       genuser->save_r17       = (uint64_t)ts->r17;
+                       genuser->save_r18       = (uint64_t)ts->r18;
+                       genuser->save_r19       = (uint64_t)ts->r19;
+                       genuser->save_r20       = (uint64_t)ts->r20;
+                       genuser->save_r21       = (uint64_t)ts->r21;
+                       genuser->save_r22       = (uint64_t)ts->r22;
+                       genuser->save_r23       = (uint64_t)ts->r23;
+                       genuser->save_r24       = (uint64_t)ts->r24;
+                       genuser->save_r25       = (uint64_t)ts->r25;
+                       genuser->save_r26       = (uint64_t)ts->r26;
+                       genuser->save_r27       = (uint64_t)ts->r27;
+                       genuser->save_r28       = (uint64_t)ts->r28;
+                       genuser->save_r29       = (uint64_t)ts->r29;
+                       genuser->save_r30       = (uint64_t)ts->r30;
+                       genuser->save_r31       = (uint64_t)ts->r31;
+               
+                       genuser->save_cr        = ts->cr;
+                       genuser->save_xer       = (uint64_t)ts->xer;
+                       genuser->save_lr        = (uint64_t)ts->lr;
+                       genuser->save_ctr       = (uint64_t)ts->ctr;
+                       genuser->save_srr0      = (uint64_t)ts->srr0;
+                       genuser->save_vrsave    = ts->vrsave;                                   /* VRSAVE register (Altivec only) */
+
+                       genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, ts->srr1);      /* Set the bits we can change */
+
+                       genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
                
-                       sv = (savearea *)thr_act->mact.pcb;                             /* Get the top savearea on the stack */
-                       osv = 0;                                                                                /* Set no user savearea yet */  
+                       genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));  /* Make sure we don't enable the floating point unit */
                        
-                       while(sv) {                                                                             /* Find the user context */
-                               if(sv->save_srr1 & MASK(MSR_PR)) {                      /* Are we looking at the user context? */
-                                       break;                                                                  /* Outta here */
-                               }
-                               osv = sv;                                                                       /* Save the last one */
-                               sv = sv->save_prev;                                                     /* Get the previous context */
-                       }
+                       if(task_has_64BitAddr(thread->task)) 
+                               genuser->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32;   /* If 64-bit task, force 64-bit mode */
+                       else
+                               genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32);        /* else 32-bit mode */
                
-                       if(!sv) {                                                                               /* We didn't find a user context so allocate and initialize one */
-                               isnew = 1;                                                                      /* Remember we made a new one */
-                               sv = save_alloc();                                                      /* Get one */
-                               sv->save_act = thr_act;                                         /* Point to the activation */
-                               sv->save_flags |= SAVattach;                            /* Say that it is in use  */
-                               sv->save_srr1 = MSR_EXPORT_MASK_SET & ~MASK(MSR_PR);    /* Assume kernel state */
-                               sv->save_xfpscrpad = 0;                                         /* Start with a clear fpscr */
-                               sv->save_xfpscr = 0;                                            /* Start with a clear fpscr */
-                               
-                               spc = (unsigned int)thr_act->map->pmap->space;  /* Get the space we're in */
-                               
-                               srs = (unsigned int *)&sv->save_sr0;            /* Point to the SRs */
-                               for(i=0; i < 16; i++) {                                         /* Fill in the SRs for the new context */
-                                       srs[i] = SEG_REG_PROT | (i<<20) | spc;  /* Set the SR */
-                               }
-                               
-                               sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc;  /* Make sure the copyin is set */
+                       return KERN_SUCCESS;
+
+
+               case PPC_THREAD_STATE64:
                                
-                               if(osv) {                                                                       /* Did we already have one? */
-                                       osv->save_prev = sv;                                    /* Chain us on the end */
-                               }
-                               else {                                                                          /* We are the first */
-                                       thr_act->mact.pcb = (pcb_t)sv;                  /* Put it there */
-                               }
-                               sv->save_prev = 0;                                                      /* Properly terminate the chain */
+                       xts = (struct ppc_thread_state64 *)tstate;
+
+                       genuser->save_r0        = xts->r0;
+                       genuser->save_r1        = xts->r1;
+                       genuser->save_r2        = xts->r2;
+                       genuser->save_r3        = xts->r3;
+                       genuser->save_r4        = xts->r4;
+                       genuser->save_r5        = xts->r5;
+                       genuser->save_r6        = xts->r6;
+                       genuser->save_r7        = xts->r7;
+                       genuser->save_r8        = xts->r8;
+                       genuser->save_r9        = xts->r9;
+                       genuser->save_r10       = xts->r10;
+                       genuser->save_r11       = xts->r11;
+                       genuser->save_r12       = xts->r12;
+                       genuser->save_r13       = xts->r13;
+                       genuser->save_r14       = xts->r14;
+                       genuser->save_r15       = xts->r15;
+                       genuser->save_r16       = xts->r16;
+                       genuser->save_r17       = xts->r17;
+                       genuser->save_r18       = xts->r18;
+                       genuser->save_r19       = xts->r19;
+                       genuser->save_r20       = xts->r20;
+                       genuser->save_r21       = xts->r21;
+                       genuser->save_r22       = xts->r22;
+                       genuser->save_r23       = xts->r23;
+                       genuser->save_r24       = xts->r24;
+                       genuser->save_r25       = xts->r25;
+                       genuser->save_r26       = xts->r26;
+                       genuser->save_r27       = xts->r27;
+                       genuser->save_r28       = xts->r28;
+                       genuser->save_r29       = xts->r29;
+                       genuser->save_r30       = xts->r30;
+                       genuser->save_r31       = xts->r31;
+               
+                       genuser->save_cr        = xts->cr;
+                       genuser->save_xer       = xts->xer;
+                       genuser->save_lr        = xts->lr;
+                       genuser->save_ctr       = xts->ctr;
+                       genuser->save_srr0      = xts->srr0;
+                       genuser->save_vrsave    = xts->vrsave;                                  /* VRSAVE register (Altivec only) */
 
-                       }
-                       
-                       if(flavor == PPC_THREAD_STATE) {                                /* Are we updating plain state? */
+                       genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, xts->srr1);     /* Set the bits we can change */
+
+                       genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
+               
+                       genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));  /* Make sure we don't enable the floating point unit */
                        
-                               sv->save_r0             = ts->r0;
-                               sv->save_r1             = ts->r1;
-                               sv->save_r2             = ts->r2;
-                               sv->save_r3             = ts->r3;
-                               sv->save_r4             = ts->r4;
-                               sv->save_r5             = ts->r5;
-                               sv->save_r6             = ts->r6;
-                               sv->save_r7             = ts->r7;
-                               sv->save_r8             = ts->r8;
-                               sv->save_r9             = ts->r9;
-                               sv->save_r10    = ts->r10;
-                               sv->save_r11    = ts->r11;
-                               sv->save_r12    = ts->r12;
-                               sv->save_r13    = ts->r13;
-                               sv->save_r14    = ts->r14;
-                               sv->save_r15    = ts->r15;
-                               sv->save_r16    = ts->r16;
-                               sv->save_r17    = ts->r17;
-                               sv->save_r18    = ts->r18;
-                               sv->save_r19    = ts->r19;
-                               sv->save_r20    = ts->r20;
-                               sv->save_r21    = ts->r21;
-                               sv->save_r22    = ts->r22;
-                               sv->save_r23    = ts->r23;
-                               sv->save_r24    = ts->r24;
-                               sv->save_r25    = ts->r25;
-                               sv->save_r26    = ts->r26;
-                               sv->save_r27    = ts->r27;
-                               sv->save_r28    = ts->r28;
-                               sv->save_r29    = ts->r29;
-                               sv->save_r30    = ts->r30;
-                               sv->save_r31    = ts->r31;
+                       if(task_has_64BitAddr(thread->task)) 
+                               genuser->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32;   /* If 64-bit task, force 64-bit mode */
+                       else
+                               genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32);        /* else 32-bit mode */
+               
+                       return KERN_SUCCESS;
+                               
+                               
+               case PPC_EXCEPTION_STATE:
                        
-                               sv->save_cr             = ts->cr;
-                               sv->save_xer    = ts->xer;
-                               sv->save_lr             = ts->lr;
-                               sv->save_ctr    = ts->ctr;
-                               sv->save_srr0   = ts->srr0;
-                               sv->save_mq             = ts->mq;       
-                               sv->save_vrsave = ts->vrsave;                                   /* VRSAVE register (Altivec only) */
+                       es = (struct ppc_exception_state *) tstate;
+               
+                       genuser->save_dar = (uint64_t)es->dar;
+                       genuser->save_dsisr = es->dsisr;
+                       genuser->save_exception = es->exception;
 
-                               sv->save_srr1   = MSR_PREPARE_FOR_IMPORT(sv->save_srr1, ts->srr1);      /* Set the bits we can change */
+                       return KERN_SUCCESS;
        
-                               if(!kernel_act) sv->save_srr1 |= MSR_EXPORT_MASK_SET;   /* If not a kernel guy, force the magic bits on */      
-                       
-                               sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));       /* Make sure we don't enable the floating point unit */
+/*
+ *             It's pretty worthless to try to change this stuff, but we'll do it anyway.
+ */
+               case PPC_EXCEPTION_STATE64:
                        
-                               if(isnew) {                                                                             /* Is it a new one? */
-                                       sv->save_dar = 0;                                                       /* Yes, these need initialization also */
-                                       sv->save_dsisr = 0;
-                                       sv->save_exception = 0;
-                               }
-                               
-                               return KERN_SUCCESS;
-                       }
-                       else {                                                                                          /* This must be exception state */
-                               if(isnew)                                                                               /* If new, we need to initialize the normal registers */
-                                       for(i=0; i < 32; i+=2) {                                        /* Fill up with defaults */
-                                               ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
-                                               ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
-                                       }
-                                       sv->save_cr     = 0;
-                                       sv->save_xer    = 0;
-                                       sv->save_lr     = ((unsigned int *)&FloatInit)[0];
-                                       sv->save_ctr    = ((unsigned int *)&FloatInit)[1];
-                                       sv->save_srr0   = ((unsigned int *)&FloatInit)[0];
-                                       sv->save_srr1 = MSR_EXPORT_MASK_SET;
-                                       sv->save_mq     = 0;
-                                       sv->save_vrsave = 0;                                            /* VRSAVE register (Altivec only) */
-                       }
-
-                       es = (struct ppc_exception_state *) tstate;
+                       xes = (struct ppc_exception_state *) tstate;
                
-                       sv->save_dar = es->dar;
-                       sv->save_dsisr = es->dsisr;
-                       sv->save_exception = es->exception;
+                       genuser->save_dar       = xes->dar;
+                       genuser->save_dsisr = xes->dsisr;
+                       genuser->save_exception = xes->exception;
 
                        return KERN_SUCCESS;
        
                case PPC_FLOAT_STATE:
 
-                       spl = splhigh();                                                                /* Don't bother me while I'm zapping the owner stuff */
+                       toss_live_fpu(thread->machine.curctx);                  /* Toss my floating point if live anywhere */
                        
-                       if (per_proc_info[cpu_number()].FPU_thread == (unsigned int)thr_act)    /* If we own the FPU, and */
-                               if(!thr_act->mact.FPU_lvl) per_proc_info[cpu_number()].FPU_thread = 0; /* it's user level, say we don't own it any more */
-                       
-                       splx(spl);                                                                              /* Restore the interrupt level */
-                       
-                       sv = (savearea *)thr_act->mact.FPU_pcb;                 /* Get the top savearea on the stack */
-                       osv = 0;                                                                                /* Set no user savearea yet */  
-                       
-                       if(sv && (sv->save_level_fp == 1)) {                    /* Is the first savearea invalid? */
-                               thr_act->mact.FPU_pcb = (pcb_t)sv->save_prev_float;     /* Yes, clean it out */
-                               sv->save_flags &= ~SAVfpuvalid;                         /* Clear the floating point flag */
-                               if(!(sv->save_flags & SAVinuse)) {                      /* Anyone left with this one? */                        
-                                       save_release(sv);                                               /* Nope, release it */
-                               }
-                               sv = (savearea *)thr_act->mact.FPU_pcb;         /* Get the new top savearea on the stack */
-                       }
-
-                       while(sv) {                                                                             /* Find the user context */
-                               if(!(sv->save_level_fp)) {                                      /* Are we looking at the user context? */
-                                       break;                                                                  /* Outta here */
-                               }
-                               osv = sv;                                                                       /* Save the last one */
-                               sv = sv->save_prev_float;                                       /* Get the previous context */
-                       }
-                       
-                       if(!sv) {                                                                               /* We didn't find a user context so allocate and initialize one */
-       
-                               sv = (savearea *)thr_act->mact.pcb;                     /* Point to the top savearea on the normal stack */
-       
-                               while(sv) {                                                                     /* Have we hit the end? */
-                                       if(!(sv->save_flags & SAVfpuvalid)) break;      /* Is floating point in use here? */
-                                       sv = sv->save_prev;                                             /* Back chain */
-                               }
-       
-                               if(!sv) {                                                                       /* If there wasn't one on the normal chain, check vector */
-                                       sv = (savearea *)thr_act->mact.VMX_pcb; /* Point to the top savearea on the vector stack */
-                                       while(sv) {                                                             /* Have we hit the end? */
-                                               if(!(sv->save_flags & SAVfpuvalid)) break;      /* Is floating point in use here? */
-                                               sv = sv->save_prev_vector;                      /* Back chain */
-                                       }
-                               }
+                       fsv = find_user_fpu(thread);                                    /* Get the user's floating point context */
+               
+                       if(!fsv) {                                                                              /* Do we have one yet? */
+                               fsv = (savearea_fpu *)save_alloc();                     /* If we still don't have one, get a new one */
+                               fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft);   /* Mark as in use as float */
+                               fsv->save_hdr.save_act = thread;
+                               fsv->save_hdr.save_prev = 0;                            /* Mark no more */
+                               fsv->save_hdr.save_level = 0;                           /* Mark user state */
                                
-                               if(!sv) {                                                                       /* Do we have one yet? */
-                                       sv = save_alloc();                                              /* If we still don't have one, get a new one */
-                                       sv->save_act = thr_act;                                 /* Point to the activation */
-                                       
-                                       spc=(unsigned int)thr_act->map->pmap->space;    /* Get the space we're in */
+                               if(!thread->machine.curctx->FPUsave) thread->machine.curctx->FPUsave = fsv;     /* If no floating point, chain us first */
+                               else {
+                               
+                                       fsvn = fsvo = thread->machine.curctx->FPUsave;  /* Remember first one */
                                        
-                                       srs=(unsigned int *)&sv->save_sr0;              /* Point to the SRs */
-                                       for(i=0; i < 16; i++) {                                 /* Fill in the SRs for the new context */
-                                               srs[i] = SEG_REG_PROT | (i<<20) | spc;  /* Set the SR */
+                                       while (fsvn) {                                                  /* Go until we hit the end */
+                                               fsvo = fsvn;                                            /* Remember the previous one */
+                                               fsvn = CAST_DOWN(savearea_fpu *, fsvo->save_hdr.save_prev);     /* Skip on to the next */
                                        }
                                        
-                                       sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc;  /* Make sure the copyin is set */
-                               }
-                                       
-                               if(osv) {                                                                       /* Did we already have one? */
-                                       osv->save_prev_float = sv;                              /* Chain us on the end */
-                               }
-                               else {                                                                          /* We are the first */
-                                       thr_act->mact.FPU_pcb = (pcb_t)sv;              /* Put it there */
+                                       fsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv);          /* Queue us on in */
                                }
-                               sv->save_prev_float = 0;                                        /* Properly terminate the chain */
-                               sv->save_level_fp = 0;                                          /* Make sure we are for the user level */
-                               sv->save_flags |= SAVfpuvalid;                          /* Say that it is in use by floating point */
+                               
                        }
                        
                        fs = (struct ppc_float_state *) tstate;                 /* Point to source */
 
                
-                       bcopy((char *)fs, (char *)&sv->save_fp0, clgn*4); /* 32 registers plus status and pad */
-               
-                       usv = find_user_regs(thr_act);                                  /* Find the user registers */
-                       if(!usv) usv = get_user_regs(thr_act);                  /* Didn't find any, allocate and initialize one */
+                       bcopy((char *)fs, (char *)&fsv->save_fp0, 32*8);        /* Move in the 32 registers */
                        
-                       usv->save_xfpscrpad = sv->save_fpscr_pad;               /* Copy the pad value to normal */      
-                       usv->save_xfpscr = sv->save_fpscr;                              /* Copy the fpscr value to normal */    
+                       genuser->save_fpscr = fs->fpscr;                                /* Copy the fpscr value to normal */    
                        
                        return KERN_SUCCESS;
                        
        
                case PPC_VECTOR_STATE:
 
-                       spl = splhigh();                                                                /* Don't bother me while I'm zapping the owner stuff */
+                       toss_live_vec(thread->machine.curctx);                  /* Toss my vector if live anywhere */
                        
-                       if (per_proc_info[cpu_number()].VMX_thread == (unsigned int)thr_act)    /* If we own the vector, and */
-                               if(!thr_act->mact.VMX_lvl) per_proc_info[cpu_number()].VMX_thread = 0; /* it's user level, say we don't own it any more */
-                       
-                       splx(spl);                                                                              /* Restore the interrupt level */
-                       
-                       sv = (savearea *)thr_act->mact.VMX_pcb;                 /* Get the top savearea on the stack */
-                       osv = 0;                                                                                /* Set no user savearea yet */  
-                       
-                       if(sv && (sv->save_level_vec == 1)) {                   /* Is the first savearea invalid? */
-                               thr_act->mact.VMX_pcb = (pcb_t)sv->save_prev_vector;    /* Yes, clean it out */
-                               sv->save_flags &= ~SAVvmxvalid;                         /* Clear the floating point flag */
-                               if(!(sv->save_flags & SAVinuse)) {                      /* Anyone left with this one? */                        
-                                       save_release(sv);                                               /* Nope, release it */
-                               }
-                               sv = (savearea *)thr_act->mact.VMX_pcb;         /* Get the new top savearea on the stack */
-                       }
-                       
-                       while(sv) {                                                                             /* Find the user context */
-                               if(!(sv->save_level_vec)) {                                     /* Are we looking at the user context? */
-                                       break;                                                                  /* Outta here */
-                               }
-                               osv = sv;                                                                       /* Save the last one */
-                               sv = sv->save_prev_vector;                                      /* Get the previous context */
-                       }
-                       
-                       if(!sv) {                                                                               /* We didn't find a user context so allocate and initialize one */
-       
-                               sv = (savearea *)thr_act->mact.pcb;                     /* Point to the top savearea on the normal stack */
-       
-                               while(sv) {                                                                     /* Have we hit the end? */
-                                       if(!(sv->save_flags & SAVvmxvalid)) break;      /* Is vector in use here? */
-                                       sv = sv->save_prev;                                             /* Back chain */
-                               }
-       
-                               if(!sv) {                                                                       /* If there wasn't one on the normal chain, check vector */
-                                       sv = (savearea *)thr_act->mact.FPU_pcb; /* Point to the top savearea on the FPU stack */
-                                       while(sv) {                                                             /* Have we hit the end? */
-                                               if(!(sv->save_flags & SAVvmxvalid)) break;      /* Is vector in use here? */
-                                               sv = sv->save_prev_float;                       /* Get the previous context */
-                                       }
-                               }
+                       vsv = find_user_vec(thread);                                    /* Get the user's vector context */
+               
+                       if(!vsv) {                                                                              /* Do we have one yet? */
+                               vsv = (savearea_vec *)save_alloc();                     /* If we still don't have one, get a new one */
+                               vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);  /* Mark as in use as vector */
+                               vsv->save_hdr.save_act = thread;
+                               vsv->save_hdr.save_prev = 0;                            /* Mark no more */
+                               vsv->save_hdr.save_level = 0;                           /* Mark user state */
                                
-                               if(!sv) {                                                                       /* Do we have one yet? */
-                                       sv = save_alloc();                                              /* If we still don't have one, get a new one */
-                                       sv->save_act = thr_act;                                 /* Point to the activation */
-                                       
-                                       spc=(unsigned int)thr_act->map->pmap->space;    /* Get the space we're in */
+                               if(!thread->machine.curctx->VMXsave) thread->machine.curctx->VMXsave = vsv;     /* If no vector, chain us first */
+                               else {
+                               
+                                       vsvn = vsvo = thread->machine.curctx->VMXsave;  /* Remember first one */
                                        
-                                       srs=(unsigned int *)&sv->save_sr0;              /* Point to the SRs */
-                                       for(i=0; i < 16; i++) {                                 /* Fill in the SRs for the new context */
-                                               srs[i] = SEG_REG_PROT | (i<<20) | spc;  /* Set the SR */
+                                       while (vsvn) {                                                  /* Go until we hit the end */
+                                               vsvo = vsvn;                                            /* Remember the previous one */
+                                               vsvn = CAST_DOWN(savearea_vec *, vsvo->save_hdr.save_prev);     /* Skip on to the next */
                                        }
                                        
-                                       sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc;  /* Make sure the copyin is set */
-                               }
-                                       
-                               if(osv) {                                                                       /* Did we already have one? */
-                                       osv->save_prev_vector = sv;                             /* Chain us on the end */
+                                       vsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv);  /* Queue us on in */
                                }
-                               else {                                                                          /* We are the first */
-                                       thr_act->mact.VMX_pcb = (pcb_t)sv;              /* Put it there */
-                               }
-                               sv->save_prev_vector = 0;                                       /* Properly terminate the chain */
-                               sv->save_level_vec = 0;                                         /* Make sure we are for the user level */
-                               sv->save_flags |= SAVvmxvalid;                          /* Say that it is in use by vector */
+                               
                        }
-
                        
                        vs = (struct ppc_vector_state *) tstate;                /* Point to source */
                
-                       bcopy((char *)vs, (char *)&sv->save_vr0, clgn*4); /* 32 registers plus status and validity and pad */
+                       bcopy((char *)vs, (char *)&vsv->save_vr0, 32*16);       /* 32 registers plus status and validity and pad */
+                       vsv->save_vrvalid = vs->save_vrvalid;                   /* Set validity bits */
+                       
+                       
+                       for(i = 0; i < 4; i++) genuser->save_vscr[i] = vs->save_vscr[i];        /* Set value for vscr */
                
                        return KERN_SUCCESS;
                        
@@ -699,147 +958,175 @@ act_machine_set_state(
     }
 }
 
+
+void
+thread_set_wq_state64(thread_t thread, thread_state_t tstate)
+{
+        struct ppc_thread_state64 *ts;
+       struct savearea         *genuser;
+       thread_t curth = current_thread();
+
+       genuser = get_user_regs(thread);                                        /* Find or allocate and initialize one */
+       ts = (struct ppc_thread_state64 *)tstate;
+
+       if (curth != thread)
+               thread_lock(thread);
+
+       genuser->save_r1        = ts->r1;
+       genuser->save_r3        = ts->r3;
+       genuser->save_r4        = ts->r4;
+       genuser->save_r5        = ts->r5;
+       genuser->save_r6        = ts->r6;
+       genuser->save_r7        = ts->r7;
+       genuser->save_r8        = ts->r8;
+       genuser->save_srr0      = ts->srr0;
+
+        genuser->save_srr1 = (uint64_t)MSR_EXPORT_MASK_SET;
+
+        if (task_has_64BitAddr(thread->task))
+               genuser->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32;           /* If 64-bit task, force 64-bit mode */
+
+       if (curth != thread)
+               thread_unlock(thread);
+}
+
+
+/*
+ * This is where registers that are not normally specified by the mach-o
+ * file on an execve should be nullified, perhaps to avoid a covert channel.
+ * We've never bothered to clear FPRs or VRs, but it is important to clear
+ * the FPSCR, which is kept in the general state but not set by the general
+ * flavor (ie, PPC_THREAD_STATE or PPC_THREAD_STATE64.)
+ */
+kern_return_t
+machine_thread_state_initialize(
+       thread_t thread)
+{
+       struct savearea         *sv;
+       
+       sv = get_user_regs(thread);                                             /* Find or allocate and initialize one */
+
+       sv->save_fpscr = 0;                                                             /* Clear all floating point exceptions */
+       sv->save_vrsave = 0;                                                    /* Set the vector save state */
+       sv->save_vscr[0] = 0x00000000;                                  
+       sv->save_vscr[1] = 0x00000000;                                  
+       sv->save_vscr[2] = 0x00000000;                                  
+       sv->save_vscr[3] = 0x00010000;                                  /* Disable java mode and clear saturated */
+
+    return  KERN_SUCCESS;
+}
+
+
 /*
  *             Duplicates the context of one thread into a new one.
- *             The new thread is assumed to be new and have no user state contexts.
+ *             The new thread is assumed to be new and have no user state contexts except maybe a general one.
  *             We also assume that the old thread can't be running anywhere.
  *
  *             We're only going to be duplicating user context here.  That means that we will have to 
  *             eliminate any floating point or vector kernel contexts and carry across the user state ones.
- *             We will optimize and cram all states into one savearea.  Actually that will be the easiest thing
- *             to do.
  */
 
-void act_thread_dup(thread_act_t old, thread_act_t new) {
-
-       savearea                *sv, *osv, *fsv;
-       unsigned int    spc, i, *srs;
+kern_return_t
+machine_thread_dup(
+       thread_t                self,
+       thread_t                target)
+{
+       struct savearea         *sv, *osv; 
+       savearea_fpu    *fsv, *fsvn;
+       savearea_vec    *vsv, *vsvn;
        
-       fpu_save(old);                                                                  /* Make certain floating point state is all saved */
-       vec_save(old);                                                                  /* Make certain the vector state is all saved */
+       fpu_save(self->machine.curctx);                                         /* Make certain floating point state is all saved */
+       vec_save(self->machine.curctx);                                         /* Make certain the vector state is all saved */
        
-       osv = (savearea *)new->mact.pcb;                                /* Get the top savearea on the stack */
-       sv = 0;                                                                                 /* Set no new user savearea yet */      
+       sv = get_user_regs(target);                                             /* Allocate and initialze context in the new activation */
        
-       while(osv) {                                                                    /* Find the user context */
-               if(osv->save_srr1 & MASK(MSR_PR)) {                     /* Are we looking at the user context? */
-                       sv=osv;                                                                 /* Say which to use */
-                       break;                                                                  /* Outta here */
-               }
-               osv=osv->save_prev;                                                     /* Get the previous context */
-       }
+       osv = find_user_regs(self);                                             /* Find the original context */
+       if(!osv)
+               return (KERN_FAILURE);
        
-       if(!sv) {                                                                               /* We didn't find a user context so allocate and initialize one */
-               osv = (savearea *)new->mact.pcb;                        /* Point to the top savearea on the stack */
-               sv = save_alloc();                                                      /* Get one */
-               sv->save_flags |= SAVattach;                            /* Say that it is in use  */
-               sv->save_act = new;                                                     /* Point to the activation */
-               
-               spc=(unsigned int)new->map->pmap->space;        /* Get the space we're in */
-               
-               srs=(unsigned int *)&sv->save_sr0;                      /* Point to the SRs */
-               for(i=0; i < 16; i++) {                                         /* Fill in the SRs for the new context */
-                       srs[i] = SEG_REG_PROT | (i<<20) | spc;  /* Set the SR */
-               }
-               
-               sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc;  /* Make sure the copyin is set */
-               
-               if(osv) {                                                                       /* Did we already have one? */
-                       sv->save_prev = osv->save_prev;                 /* Move the back chain of the top savearea */
-                       osv->save_prev = sv;                                    /* Chain us just after it */
-               }
-               else {                                                                          /* We are the first */
-                       new->mact.pcb = (pcb_t)sv;                              /* Make it the active one */
-               }
-               
-       }
-
-       osv = (savearea *)(old->mact.pcb);                              /* Start with the normal savearea */
-       while(osv) {                                                                    /* Find the user context */
-               if(osv->save_srr1 & MASK(MSR_PR)) {                     /* Are we looking at the user context? */
-                       break;                                                                  /* Outta here */
-               }
-               osv = osv->save_prev;                                           /* Back chain */
-       }
+       bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)),      /* Copy everything but the headers */
+               (char *)((unsigned int)sv + sizeof(savearea_comm)), 
+               sizeof(struct savearea) - sizeof(savearea_comm));
+       
+       sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC)));   /* Make certain that floating point and vector are turned off */
 
-       bcopy((char *)&osv->save_srr0, (char *)&sv->save_srr0, sizeof(struct ppc_thread_state)); /* Copy in normal state stuff */
+       fsv = find_user_fpu(self);                                              /* Get any user floating point */
        
-       sv->save_xfpscrpad = osv->save_xfpscrpad;               /* Copy the pad value to old */ 
-       sv->save_xfpscr = osv->save_xfpscr;                             /* Copy the fpscr value to old */       
+       target->machine.curctx->FPUsave = NULL;                                 /* Assume no floating point */
 
-       new->mact.FPU_pcb = (pcb_t)0 ;                                  /* Initialize floating point savearea */
-       new->mact.FPU_lvl = (pcb_t)0 ;                                  /* Initialize floating point level */
-       new->mact.FPU_cpu = 0 ;                                                 /* Initialize last used cpu (FP not live, so this doesn't really matter) */
-       new->mact.VMX_pcb = (pcb_t)0 ;                                  /* Initialize vector savearea */
-       new->mact.VMX_lvl = (pcb_t)0 ;                                  /* Initialize vector level */
-       new->mact.VMX_cpu = 0 ;                                                 /* Initialize last used cpu (vector not live, so this doesn't reall matter) */
+       if(fsv) {                                                                               /* Did we find one? */
+               fsvn = (savearea_fpu *)save_alloc();            /* If we still don't have one, get a new one */
+               fsvn->save_hdr.save_flags = (fsvn->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft); /* Mark as in use as float */
+               fsvn->save_hdr.save_act = target;
+               fsvn->save_hdr.save_prev = 0;                           /* Mark no more */
+               fsvn->save_hdr.save_level = 0;                          /* Mark user state */
 
-       sv->save_prev_float = (savearea *)0;                    /* Clear the back chain */
-       sv->save_prev_vector = (savearea *)0;                   /* Clear the back chain */
-       sv->save_level_fp = 0;                                                  /* Set the level for FP */
-       sv->save_level_vec = 0;                                                 /* Set the level for vector */
-       
-       sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));       /* Make certain that floating point and vector are turned off */
-       
-       fsv = (savearea *)old->mact.FPU_pcb;                    /* Get the start of the floating point chain */
-       while(fsv) {                                                                    /* Look until the end or we find it */
-               if(!(fsv->save_level_fp)) {                                     /* Is the the user state stuff? (the level is 0 if so) */       
-                       sv->save_flags |= SAVfpuvalid;                  /* Show we have it */
-                       bcopy((char *)&osv->save_fp0, (char *)&sv->save_fp0, sizeof(struct ppc_float_state)); /* Copy in floating point state stuff */
-                       new->mact.FPU_pcb = (pcb_t)sv;                  /* Make it the active one */
-                       break;                                                                  /* Done, everything else is all set up... */
-               }
-               fsv = fsv->save_prev_float;                                     /* Try the previous one */
+               target->machine.curctx->FPUsave = fsvn;                 /* Chain in the floating point */
+
+               bcopy((char *)((unsigned int)fsv + sizeof(savearea_comm)),      /* Copy everything but the headers */
+                       (char *)((unsigned int)fsvn + sizeof(savearea_comm)), 
+                       sizeof(struct savearea) - sizeof(savearea_comm));
        }
+
+       vsv = find_user_vec(self);                                              /* Get any user vector */
        
-       fsv = (savearea *)old->mact.VMX_pcb;                    /* Get the start of the vector chain */
-       while(fsv) {                                                                    /* Look until the end or we find it */
-               if(!(fsv->save_level_vec)) {                            /* Is the the user state stuff? (the level is 0 if so) */       
-                       sv->save_flags |= SAVvmxvalid;                  /* Show we have it */
-                       bcopy((char *)&osv->save_vr0, (char *)&sv->save_vr0, sizeof(struct ppc_vector_state)); /* Copy in Altivec state stuff */
-                       new->mact.VMX_pcb = (pcb_t)sv;                  /* Make it the active one */
-                       break;                                                                  /* Done, everything else is all set up... */
-               }
-               fsv = fsv->save_prev_vector;                            /* Try the previous one */
+       target->machine.curctx->VMXsave = NULL;                                 /* Assume no vector */
+
+       if(vsv) {                                                                               /* Did we find one? */
+               vsvn = (savearea_vec *)save_alloc();            /* If we still don't have one, get a new one */
+               vsvn->save_hdr.save_flags = (vsvn->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);        /* Mark as in use as float */
+               vsvn->save_hdr.save_act = target;
+               vsvn->save_hdr.save_prev = 0;                           /* Mark no more */
+               vsvn->save_hdr.save_level = 0;                          /* Mark user state */
+
+               target->machine.curctx->VMXsave = vsvn;                 /* Chain in the floating point */
+
+               bcopy((char *)((unsigned int)vsv + sizeof(savearea_comm)),      /* Copy everything but the headers */
+                       (char *)((unsigned int)vsvn + sizeof(savearea_comm)), 
+                       sizeof(struct savearea) - sizeof(savearea_comm));
        }
 
-       return;                                                                                 /* Bye bye... */
+       return (KERN_SUCCESS);
 }
 
 /*
  *             Initializes a fresh set of user state values.  If there is no user state context,
- *             one is created. Floats and VMX are not created. We set initial values for everything.
+ *             one is created. Floats and VMX are not created. 
+ *             
+ *             We only set initial values if there was no context found.
  */
 
-struct ppc_saved_state * get_user_regs(thread_act_t act) {
+struct savearea *
+get_user_regs(
+       thread_t         thread)
+{
+       struct savearea         *sv, *osv;
+       unsigned int    i;
 
-       savearea                *sv, *osv;
-       unsigned int    spc, i, *srs;
+       if (thread->machine.upcb)
+               return  thread->machine.upcb;
 
-       sv = (savearea *)act->mact.pcb;                                 /* Get the top savearea on the stack */
-       osv = 0;                                                                                /* Set no user savearea yet */  
+       sv = thread->machine.pcb;                                                               /* Get the top savearea on the stack */
+       osv = NULL;                                                                             /* Set no user savearea yet */  
        
        while(sv) {                                                                             /* Find the user context */
-               if(sv->save_srr1 & MASK(MSR_PR)) {                      /* Are we looking at the user context? */
-                       break;                                                                  /* Outta here */
-               }
                osv = sv;                                                                       /* Save the last one */
-               sv = sv->save_prev;                                                     /* Get the previous context */
+               sv = CAST_DOWN(struct savearea *, sv->save_hdr.save_prev);      /* Get the previous context */ 
        }
 
-       if(!sv) {                                                                               /* We didn't find a user context so allocate and initialize one */
-               sv = save_alloc();                                                      /* Get one */
-               sv->save_flags |= SAVattach;                            /* Say that it is in use  */
-               sv->save_act = act;                                                     /* Point to the activation */
-               
-               if(osv) {                                                                       /* Did we already have one? */
-                       osv->save_prev = sv;                                    /* Chain us on the end */
-               }
-               else {                                                                          /* We are the first */
-                       act->mact.pcb = (pcb_t)sv;                              /* Put it there */
-               }
-               sv->save_prev = 0;                                                      /* Properly terminate the chain */
+       sv = save_alloc();                                                              /* Get one */
+       sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft);   /* Mark as in use as general */
+       sv->save_hdr.save_act = thread;
+       sv->save_hdr.save_prev = 0;                                             /* Mark no more */
+       sv->save_hdr.save_level = 0;                                    /* Mark user state */
+       
+       if(osv) {                                                                               /* Did we already have one? */
+               osv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv);            /* Chain us on the end */
+       }
+       else {                                                                                  /* We are the first */
+               thread->machine.pcb = sv;                                                       /* Put it there */
        }
+       thread->machine.upcb = sv;                                                      /* Set user pcb */
 
        for(i=0; i < 32; i+=2) {                                                /* Fill up with defaults */
                ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
@@ -847,25 +1134,22 @@ struct ppc_saved_state * get_user_regs(thread_act_t act) {
        }
        sv->save_cr     = 0;
        sv->save_xer    = 0;
-       sv->save_lr     = ((unsigned int *)&FloatInit)[0];
-       sv->save_ctr    = ((unsigned int *)&FloatInit)[1];
-       sv->save_srr0   = ((unsigned int *)&FloatInit)[0];
-       sv->save_srr1 = MSR_EXPORT_MASK_SET;
-       sv->save_mq     = 0;
-       sv->save_vrsave = 0;                                                    /* VRSAVE register (Altivec only) */
-       sv->save_xfpscrpad = 0;                                                 /* Start with a clear fpscr */
-       sv->save_xfpscr = 0;                                                    /* Start with a clear fpscr */
-       
-       spc=(unsigned int)act->map->pmap->space;                /* Get the space we're in */
-       
-       srs=(unsigned int *)&sv->save_sr0;                              /* Point to the SRs */
-       for(i=0; i < 16; i++) {                                                 /* Fill in the SRs for the new context */
-               srs[i] = SEG_REG_PROT | (i<<20) | spc;          /* Set the SR */
-       }
-       
-       sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc;  /* Make sure the copyin is set */
-       
-       return (struct ppc_saved_state *)sv;                    /* Bye bye... */
+       sv->save_lr     = (uint64_t)FloatInit;
+       sv->save_ctr    = (uint64_t)FloatInit;
+       sv->save_srr0   = (uint64_t)FloatInit;
+       sv->save_srr1 = (uint64_t)MSR_EXPORT_MASK_SET;
+       if(task_has_64BitAddr(thread->task)) 
+               sv->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32;        /* If 64-bit task, force 64-bit mode */
+
+       sv->save_fpscr = 0;                                                             /* Clear all floating point exceptions */
+
+       sv->save_vrsave = 0;                                                    /* Set the vector save state */
+       sv->save_vscr[0] = 0x00000000;                                  
+       sv->save_vscr[1] = 0x00000000;                                  
+       sv->save_vscr[2] = 0x00000000;                                  
+       sv->save_vscr[3] = 0x00010000;                                  /* Disable java mode and clear saturated */
+       
+       return sv;                                                                              /* Bye bye... */
 }
 
 /*
@@ -873,38 +1157,93 @@ struct ppc_saved_state * get_user_regs(thread_act_t act) {
  *             we just return a 0.
  */
 
-struct ppc_saved_state * find_user_regs(thread_act_t act) {
+struct savearea *
+find_user_regs(
+       thread_t        thread)
+{
+       return thread->machine.upcb;
+}
+
+/* The name of this call is something of a misnomer since the mact.pcb can 
+ * contain chained saveareas, but it will do for now..
+ */
+struct savearea *
+find_kern_regs(
+       thread_t        thread)
+{
+        return thread->machine.pcb;
+}
+
+/*
+ *             Find the user state floating point context.  If there is no user state context,
+ *             we just return a 0.
+ */
 
-       savearea                *sv;
+savearea_fpu *
+find_user_fpu(
+       thread_t        thread)
+{
+       savearea_fpu    *fsv;
+       boolean_t               intr;
 
-       sv = (savearea *)act->mact.pcb;                                 /* Get the top savearea on the stack */
+       intr = ml_set_interrupts_enabled(FALSE);
+       fsv = thread->machine.curctx->FPUsave;                          /* Get the start of the floating point chain */
        
-       while(sv) {                                                                             /* Find the user context */
-               if(sv->save_srr1 & MASK(MSR_PR)) {                      /* Are we looking at the user context? */
-                       break;                                                                  /* Outta here */
-               }
-               sv = sv->save_prev;                                                     /* Get the previous context */
+       while(fsv) {                                                                    /* Look until the end or we find it */
+               if(!(fsv->save_hdr.save_level)) break;          /* Is the the user state stuff? (the level is 0 if so) */       
+               fsv = CAST_DOWN(savearea_fpu *, fsv->save_hdr.save_prev);       /* Try the previous one */ 
        }
+       (void) ml_set_interrupts_enabled(intr);
        
-       return (struct ppc_saved_state *)sv;                    /* Bye bye... */
+       return fsv;                                                                             /* Bye bye... */
 }
 
 /*
- *             Find the user state floating pointcontext.  If there is no user state context,
+ *             Find the user state vector context.  If there is no user state context,
  *             we just return a 0.
  */
 
-struct ppc_float_state * find_user_fpu(thread_act_t act) {
+savearea_vec *
+find_user_vec(
+       thread_t        thread)
+{
+       savearea_vec    *vsv;
+       boolean_t               intr;
 
-       savearea                *fsv;
+       intr = ml_set_interrupts_enabled(FALSE);
+       vsv = thread->machine.curctx->VMXsave;                          /* Get the start of the vector chain */
+       
+       while(vsv) {                                                                    /* Look until the end or we find it */
+               if(!(vsv->save_hdr.save_level)) break;          /* Is the the user state stuff? (the level is 0 if so) */       
+               vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev);       /* Try the previous one */ 
+       }
+       (void) ml_set_interrupts_enabled(intr);
+       
+       return vsv;                                                                             /* Bye bye... */
+}
+/*
+ *             Find the user state vector context for the current thread.  If there is no user state context,
+ *             we just return a 0.
+ */
 
-       fsv = (savearea *)act->mact.FPU_pcb;                    /* Get the start of the floating point chain */
-       while(fsv) {                                                                    /* Look until the end or we find it */
-               if(!(fsv->save_level_fp)) break;                        /* Is the the user state stuff? (the level is 0 if so) */       
-               fsv = fsv->save_prev_float;                                     /* Try the previous one */
+savearea_vec *find_user_vec_curr(void) {
+
+       savearea_vec    *vsv;
+       thread_t                thread = current_thread();
+       boolean_t               intr;
+       
+       vec_save(thread->machine.curctx);                                               /* Force save if live */
+
+       intr = ml_set_interrupts_enabled(FALSE);
+       vsv = thread->machine.curctx->VMXsave;                          /* Get the start of the vector chain */
+       
+       while(vsv) {                                                                    /* Look until the end or we find it */
+               if(!(vsv->save_hdr.save_level)) break;          /* Is the the user state stuff? (the level is 0 if so) */       
+               vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev);       /* Try the previous one */ 
        }
+       (void) ml_set_interrupts_enabled(intr);
        
-       return (struct ppc_float_state *)&(fsv->save_fp0);      /* Bye bye... */
+       return vsv;                                                                             /* Bye bye... */
 }
 
 /*
@@ -915,26 +1254,23 @@ struct ppc_float_state * find_user_fpu(thread_act_t act) {
  */
 kern_return_t
 thread_userstack(
-    thread_t            thread,
+    __unused thread_t  thread,
     int                 flavor,
     thread_state_t      tstate,
     unsigned int        count,
-    vm_offset_t         *user_stack,
+    mach_vm_offset_t   *user_stack,
        int                                     *customstack
 )
 {
-        struct ppc_thread_state *state;
-
         /*
          * Set a default.
          */
-        if (*user_stack == 0)
-                *user_stack = USRSTACK;
-               if (customstack)
-                       *customstack = 0;
 
         switch (flavor) {
         case PPC_THREAD_STATE:
+               {
+                       struct ppc_thread_state *state;
+
                 if (count < PPC_THREAD_STATE_COUNT)
                         return (KERN_INVALID_ARGUMENT);
  
@@ -943,12 +1279,42 @@ thread_userstack(
                 /*
                  * If a valid user stack is specified, use it.
                  */
-                *user_stack = state->r1 ? state->r1: USRSTACK;
-
-                               if (customstack && state->r1)
+                       if (state->r1) {
+                               *user_stack = CAST_USER_ADDR_T(state->r1);
+                               if (customstack)
                                        *customstack = 1;
+                       } else {
+                               *user_stack = CAST_USER_ADDR_T(USRSTACK);
+                               if (customstack)
+                                       *customstack = 0;
+                       }
+               }
+                break;
                                        
+       case PPC_THREAD_STATE64:
+               {
+                       struct ppc_thread_state64 *state64;
+                                       
+                       if (count < PPC_THREAD_STATE64_COUNT)
+                               return (KERN_INVALID_ARGUMENT);
+
+                       state64 = (struct ppc_thread_state64 *)tstate;
+
+                       /*
+                        * If a valid user stack is specified, use it.
+                        */
+                       if (state64->r1 != MACH_VM_MIN_ADDRESS) {
+                               *user_stack = state64->r1;
+                               if (customstack)
+                                       *customstack = 1;
+                       } else {
+                               *user_stack = USRSTACK64;
+                               if (customstack)
+                                       *customstack = 0;
+                       }
+               }
                 break;
+               
         default :
                 return (KERN_INVALID_ARGUMENT);
         }
@@ -956,26 +1322,115 @@ thread_userstack(
         return (KERN_SUCCESS);
 }    
 
+
+/*
+ * thread_setuserstack:
+ *
+ * Sets the user stack pointer into the machine
+ * dependent thread state info.
+ */
+void
+thread_setuserstack(thread_t thread, mach_vm_address_t user_stack)
+{
+       struct savearea *sv;
+       
+       sv = get_user_regs(thread);     /* Get the user state registers */
+       
+       sv->save_r1 = user_stack;
+       
+       return;
+}    
+
+void 
+thread_set_cthreadself(thread_t thread, uint64_t pself, int isLP64)
+{
+       struct savearea *sv;
+       
+       if (isLP64 == 0) {
+               thread->machine.cthread_self = pself;
+       } else {
+               sv = get_user_regs(thread);     /* Get the user state registers */
+
+               thread->machine.cthread_self = pself;
+               sv->save_r13 = pself;
+       }
+}
+
+
+/*
+ * thread_adjuserstack:
+ *
+ * Returns the adjusted user stack pointer from the machine
+ * dependent thread state info.  Usef for small (<2G) deltas.
+ */
+uint64_t
+thread_adjuserstack(thread_t thread, int adjust)
+{
+       struct savearea *sv;
+       
+       sv = get_user_regs(thread);     /* Get the user state registers */
+       
+       sv->save_r1 += adjust;          /* Adjust the stack */
+       
+       return sv->save_r1;             /* Return the adjusted stack */
+       
+}    
+
+kern_return_t
+thread_setsinglestep(thread_t thread, int on)
+{
+       struct savearea *sv;
+       
+       sv = get_user_regs(thread);     /* Get the user state registers */
+       
+       if (on)
+               sv->save_srr1 |= MASK(MSR_SE);
+       else
+               sv->save_srr1 &= ~MASK(MSR_SE);
+       
+       return (KERN_SUCCESS);
+}    
+
+/*
+ * thread_setentrypoint:
+ *
+ * Sets the user PC into the machine
+ * dependent thread state info.
+ */
+
+void
+thread_setentrypoint(thread_t thread, uint64_t entry)
+{
+       struct savearea *sv;
+       
+       sv = get_user_regs(thread);     /* Get the user state registers */
+       
+       sv->save_srr0 = entry;
+}    
+
 kern_return_t
 thread_entrypoint(
-    thread_t            thread,
+    __unused thread_t  thread,
     int                 flavor,
     thread_state_t      tstate,
     unsigned int        count,
-    vm_offset_t         *entry_point
+    mach_vm_offset_t   *entry_point
 )
 { 
-    struct ppc_thread_state     *state;
+#if 0
+       /* Silly code: "if *entry_point is 0, make it 0" */
     /*
      * Set a default.
      */
-    if (*entry_point == 0)
-        *entry_point = VM_MIN_ADDRESS;
+    if (*entry_point == 0ULL)
+        *entry_point = MACH_VM_MIN_ADDRESS;
+#endif
     
     switch (flavor) {   
-    
     case PPC_THREAD_STATE:
+       {
+           struct ppc_thread_state     *state;
+
         if (count < PPC_THREAD_STATE_COUNT)
             return (KERN_INVALID_ARGUMENT);
 
@@ -984,8 +1439,34 @@ thread_entrypoint(
         /* 
          * If a valid entry point is specified, use it.
          */     
-        *entry_point = state->srr0 ? state->srr0: VM_MIN_ADDRESS;
+           if (state->srr0) {
+               *entry_point = CAST_USER_ADDR_T(state->srr0);
+           } else {
+               *entry_point = CAST_USER_ADDR_T(VM_MIN_ADDRESS);
+           }
+       }
+        break; 
+
+    case PPC_THREAD_STATE64:
+       {
+           struct ppc_thread_state64     *state64;
+
+           if (count < PPC_THREAD_STATE_COUNT)
+               return (KERN_INVALID_ARGUMENT);
+
+           state64 = (struct ppc_thread_state64 *)tstate;
+
+           /* 
+            * If a valid entry point is specified, use it.
+            */     
+           if (state64->srr0) {
+               *entry_point = state64->srr0;
+           } else {
+               *entry_point = MACH_VM_MIN_ADDRESS;
+           }
+       }
         break; 
+
     default: 
         return (KERN_INVALID_ARGUMENT);
     }           
@@ -1007,28 +1488,53 @@ unsigned int get_msr_rbits(void)
        return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
 }
 
-void  thread_set_child(thread_act_t child, int pid)
+void ppc_checkthreadstate(void * tsptr, int flavor)
+{
+       if (flavor == PPC_THREAD_STATE64) {
+               struct ppc_thread_state64 *ts64 =(struct ppc_thread_state64 *)tsptr;
+
+               /* Make sure naughty bits are off and necessary bits are on */
+               ts64->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
+               ts64->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
+       } else {
+               struct ppc_thread_state *ts =(struct ppc_thread_state *)tsptr;
+
+               /* Make sure naughty bits are off and necessary bits are on */
+               ts->srr1 &= ~(MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
+               ts->srr1 |= (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
+       }
+       return;
+}
+
+void
+thread_set_child(
+       thread_t        child,
+       int                     pid)
 {
-       struct ppc_saved_state *child_state;
+       struct savearea *child_state;
        
-       child_state = find_user_regs(child);
+       child_state = get_user_regs(child);
        
-       child_state->r3 = pid;
-       child_state->r4 = 1;
+       child_state->save_r3 = (uint_t)pid;
+       child_state->save_r4 = 1ULL;
 }
-void  thread_set_parent(thread_act_t parent, int pid)
+void
+thread_set_parent(
+       thread_t        parent,
+       int                     pid)
 {
-       struct ppc_saved_state *parent_state;
+       struct savearea *parent_state;
        
-       parent_state = find_user_regs(parent);
+       parent_state = get_user_regs(parent);
        
-       parent_state->r3 = pid;
-       parent_state->r4 = 0;
+       parent_state->save_r3 = (uint64_t)pid;
+       parent_state->save_r4 = 0;
 }
 
 /*
  *             Saves the complete context (general, floating point, and vector) of the current activation.
- *             We will collect everything into one savearea and pass that back.
+ *             We will collect everything into an opaque block of 1 to 3 saveareas and pass back a 
+ *             pointer to that.
  *
  *             The savearea is made to look like it belongs to the source activation.  This needs to 
  *             be adjusted when these contexts are attached to a new activation.
@@ -1037,90 +1543,78 @@ void  thread_set_parent(thread_act_t parent, int pid)
 
 void *act_thread_csave(void) {
 
-       savearea                *sv, *osv, *fsv;
-       unsigned int    spc, i, *srs;
+       struct savearea         *sv, *osv;
+       savearea_fpu    *fsv, *ofsv;
+       savearea_vec    *vsv, *ovsv;
+       
+       thread_t thread;        
        
-       thread_act_t act;       
+       thread = current_thread();
        
-       fpu_save(current_act());                                                /* Make certain floating point state is all saved */
-       vec_save(current_act());                                                /* Make certain the vector state is all saved */
+       fpu_save(thread->machine.curctx);                                               /* Make certain floating point state is all saved */
+       vec_save(thread->machine.curctx);                                               /* Make certain the vector state is all saved */
 
-       sv = save_alloc();                                                              /* Get a fresh save area */
-       hw_atomic_add(&saveanchor.saveneed, 1);                 /* Account for the extra saveareas "need" */
+       osv = find_user_regs(thread);                                           /* Get our savearea */
 
-       act = current_act();                                                    /* Find ourselves */    
+       if(!osv) {
+               panic("act_thread_csave: attempting to preserve the context of an activation with none (%p)\n", thread);
+       }
        
-       sv->save_flags |= SAVattach;                                    /* Say that it is in use  */
-       sv->save_act = act;                                                             /* Point to the activation */
+       sv = save_alloc();                                                              /* Get a fresh save area to save into */
+       sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft);   /* Mark as in use as general */
+       sv->save_hdr.save_act = thread;
+       sv->save_hdr.save_prev = 0;                                             /* Mark no more */
+       sv->save_hdr.save_level = 0;                                    /* Mark user state */
        
-       spc=(unsigned int)act->map->pmap->space;                /* Get the space we're in */
        
-       srs=(unsigned int *)&sv->save_sr0;                              /* Point to the SRs */
-       for(i=0; i < 16; i++) {                                                 /* Fill in the SRs for the new context */
-               srs[i] = SEG_REG_PROT | (i<<20) | spc;          /* Set the SR */
-       }
+       bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)),      /* Copy everything but the headers */
+               (char *)((unsigned int)sv + sizeof(savearea_comm)), 
+               sizeof(struct savearea) - sizeof(savearea_comm));
+       
+       sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC)));   /* Make certain that floating point and vector are turned off */        
+       
+       sv->save_hdr.save_misc2 = 0xDEBB1ED0;                   /* Eye catcher for debug */
+       sv->save_hdr.save_misc3 = 0xE5DA11A5;                   /* Eye catcher for debug */
        
-       sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc;  /* Make sure the copyin is set */
 
-       osv = (savearea *)(act->mact.pcb);                              /* Start with the normal savearea */
-       fsv = 0;                                                                                /* Assume none */
-       while(osv) {                                                                    /* Find the user context */
-               if(osv->save_srr1 & MASK(MSR_PR)) {                     /* Are we looking at the user context? */
-                       fsv = osv;                                                              /* Remember what we found */
-                       break;                                                                  /* Outta here */
-               }
-               osv = osv->save_prev;                                           /* Back chain */
-       }
+       ofsv = find_user_fpu(thread);                                           /* Get any user floating point */
 
-       if(!fsv) {                                                                              /* Did we find one? */
-               for(i=0; i < 32; i+=2) {                                        /* Fill up with defaults */
-                       ((unsigned int *)&sv->save_r0)[i] = ((unsigned int *)&FloatInit)[0];
-                       ((unsigned int *)&sv->save_r0)[i+1] = ((unsigned int *)&FloatInit)[1];
-               }
-               sv->save_cr     = 0;
-               sv->save_xer    = 0;
-               sv->save_lr     = ((unsigned int *)&FloatInit)[0];
-               sv->save_ctr    = ((unsigned int *)&FloatInit)[1];
-               sv->save_srr0   = ((unsigned int *)&FloatInit)[0];
-               sv->save_srr1 = MSR_EXPORT_MASK_SET;
-               sv->save_mq     = 0;
-               sv->save_vrsave = 0;                                            /* VRSAVE register (Altivec only) */
-               sv->save_xfpscrpad = 0;                                         /* Start with a clear fpscr */
-               sv->save_xfpscr = 0;                                            /* Start with a clear fpscr */
-       }
-       else {                                                                                  /* We did find one, copy it */
-               bcopy((char *)&fsv->save_srr0, (char *)&sv->save_srr0, sizeof(struct ppc_thread_state)); /* Copy in normal state stuff */
-               sv->save_xfpscrpad = osv->save_xfpscrpad;       /* Copy the pad value to old */ 
-               sv->save_xfpscr = osv->save_xfpscr;                     /* Copy the fpscr value to old */       
-       }
+       sv->save_hdr.save_misc0 = 0;                                    /* Assume no floating point */
 
-       
-       sv->save_prev = (savearea *)0xDEBB1ED0;                 /* Eye catcher for debug */
-       sv->save_prev_float = (savearea *)0xE5DA11A5;   /* Eye catcher for debug */
-       sv->save_prev_vector = (savearea *)0;                   /* Clear */
-       sv->save_level_fp = 0;                                                  /* Set the level for FP */
-       sv->save_level_vec = 0;                                                 /* Set the level for vector */
-       
-       sv->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));       /* Make certain that floating point and vector are turned off */
-       
-       fsv = (savearea *)act->mact.FPU_pcb;                    /* Get the start of the floating point chain */
-       while(fsv) {                                                                    /* Look until the end or we find it */
-               if(!(fsv->save_level_fp)) {                                     /* Is the the user state stuff? (the level is 0 if so) */       
-                       sv->save_flags |= SAVfpuvalid;                  /* Show we have it */
-                       bcopy((char *)&fsv->save_fp0, (char *)&sv->save_fp0, sizeof(struct ppc_float_state)); /* Copy in floating point state stuff */
-                       break;                                                                  /* Done, everything else is all set up... */
-               }
-               fsv = fsv->save_prev_float;                                     /* Try the previous one */
+       if(ofsv) {                                                                              /* Did we find one? */
+               fsv = (savearea_fpu *)save_alloc();                     /* If we still don't have one, get a new one */
+               fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft);   /* Mark as in use as float */
+               fsv->save_hdr.save_act = thread;
+               fsv->save_hdr.save_prev = 0;                            /* Mark no more */
+               fsv->save_hdr.save_level = 0;                           /* Mark user state */
+               fsv->save_hdr.save_misc2 = 0xDEBB1ED0;          /* Eye catcher for debug */
+               fsv->save_hdr.save_misc3 = 0xE5DA11A5;          /* Eye catcher for debug */
+
+               sv->save_hdr.save_misc0 = (uint64_t)((uintptr_t)fsv);   /* Remember this one */
+
+               bcopy((char *)((unsigned int)ofsv + sizeof(savearea_comm)),     /* Copy everything but the headers */
+                       (char *)((unsigned int)fsv + sizeof(savearea_comm)), 
+                       sizeof(struct savearea) - sizeof(savearea_comm));
        }
+
+       ovsv = find_user_vec(thread);                                           /* Get any user vector */
        
-       fsv = (savearea *)act->mact.VMX_pcb;                    /* Get the start of the vector chain */
-       while(fsv) {                                                                    /* Look until the end or we find it */
-               if(!(fsv->save_level_vec)) {                            /* Is the the user state stuff? (the level is 0 if so) */       
-                       sv->save_flags |= SAVvmxvalid;                  /* Show we have it */
-                       bcopy((char *)&fsv->save_vr0, (char *)&sv->save_vr0, sizeof(struct ppc_vector_state)); /* Copy in Altivec state stuff */
-                       break;                                                                  /* Done, everything else is all set up... */
-               }
-               fsv = fsv->save_prev_vector;                            /* Try the previous one */
+       sv->save_hdr.save_misc1 = 0;                                    /* Assume no vector */
+
+       if(ovsv) {                                                                              /* Did we find one? */
+               vsv = (savearea_vec *)save_alloc();                     /* If we still don't have one, get a new one */
+               vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);  /* Mark as in use as float */
+               vsv->save_hdr.save_act = thread;
+               vsv->save_hdr.save_prev = 0;                            /* Mark no more */
+               vsv->save_hdr.save_level = 0;                           /* Mark user state */
+               vsv->save_hdr.save_misc2 = 0xDEBB1ED0;          /* Eye catcher for debug */
+               vsv->save_hdr.save_misc3 = 0xE5DA11A5;          /* Eye catcher for debug */
+
+               sv->save_hdr.save_misc1 = (uint64_t)((uintptr_t)vsv);   /* Chain in the floating point */
+
+               bcopy((char *)((unsigned int)ovsv + sizeof(savearea_comm)),     /* Copy everything but the headers */
+                       (char *)((unsigned int)vsv + sizeof(savearea_comm)), 
+                       sizeof(struct savearea) - sizeof(savearea_comm));
        }
 
        return (void *)sv;                                                              /* Bye bye... */
@@ -1141,141 +1635,118 @@ void *act_thread_csave(void) {
 
 void act_thread_catt(void *ctx) {
 
-       savearea                *sv, *osv, *fsv, *psv;
-       unsigned int    spc, i, *srs;
-       thread_act_t act;       
+       struct savearea         *sv, *osv, *psv;
+       savearea_fpu    *fsv, *ofsv, *pfsv;
+       savearea_vec    *vsv, *ovsv, *pvsv;
+       unsigned int    spc;
+       thread_t thread;        
+       
+       sv = (struct savearea *)ctx;                                                    /* Make this easier for C */
        
-       sv = (savearea *)ctx;                                                   /* Make this easier for C */
+       fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0);       /* Get a possible floating point savearea */ 
+       vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1);       /* Get a possible vector savearea */ 
        
-       if((sv->save_prev != (savearea *)0xDEBB1ED0) || (sv->save_prev_float != (savearea *)0xE5DA11A5)) {      /* See if valid savearea */
-               panic("act_thread_catt: attempt to attach invalid context savearea - %08X\n", sv);      /* Die */
+       if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) {        /* See if valid savearea */
+               panic("act_thread_catt: attempt to attach invalid general context savearea - %p\n", sv);        /* Die */
        }
 
-       act = current_act();                                                    /* Find ourselves */    
-               
-/*
- *     This next bit insures that any live facility context for this thread is discarded on every processor
- *     that may have it. 
- *
- *     Note that this will not be good if the activation has any kernel fp or vec contexts that are live.
- *     We won't worry about it because it would be silly to call this if we are a kernel task using altivec
- *     or floating point......
- */
-       for(i=0; i < real_ncpus; i++) {                                                 /* Cycle through processors */
-               (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].FPU_thread); /* Clear if ours */
-               (void)hw_compare_and_store((unsigned int)act, 0, &per_proc_info[i].VMX_thread); /* Clear if ours */
+       if(fsv && ((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5))) {     /* See if valid savearea */
+               panic("act_thread_catt: attempt to attach invalid float context savearea - %p\n", fsv); /* Die */
        }
 
+       if(vsv && ((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5))) {     /* See if valid savearea */
+               panic("act_thread_catt: attempt to attach invalid vector context savearea - %p\n", vsv);        /* Die */
+       }
 
-/*
- *     Now we make the savearea look like we own it
- */
+       thread = current_thread();
 
-       sv->save_prev = (savearea *)0;                                  /* Clear */
-       sv->save_prev_float = (savearea *)0;                    /* Clear */
-       sv->save_prev_vector = (savearea *)0;                   /* Clear */
-       sv->save_act = act;                                                             /* Point to the activation */
-       
-       spc=(unsigned int)act->map->pmap->space;                /* Get the space we're in */
-       
-       srs=(unsigned int *)&sv->save_sr0;                              /* Point to the SRs */
-       for(i=0; i < 16; i++) {                                                 /* Fill in the SRs for the new context */
-               srs[i] = SEG_REG_PROT | (i<<20) | spc;          /* Set the SRs */
-       }
-       
-       sv->save_sr_copyin = SEG_REG_PROT | (SR_COPYIN_NUM<<20) | spc;  /* Make sure the copyin is set */
-       
-       osv = (savearea *)act->mact.VMX_pcb;                    /* Get the top vector savearea */
+       act_machine_sv_free(thread, 0);                                 /* Blow away any current kernel FP or vector.
+                                                                                                          We do not support those across a vfork */
+       toss_live_fpu(thread->machine.curctx);                  /* Toss my floating point if live anywhere */
+       toss_live_vec(thread->machine.curctx);                  /* Toss my vector if live anywhere */
+               
+       sv->save_hdr.save_misc2 = 0;                                    /* Eye catcher for debug */
+       sv->save_hdr.save_misc3 = 0;                                    /* Eye catcher for debug */
+       sv->save_hdr.save_act = thread;
        
-       if(osv && (osv->save_level_vec == 1)) {                 /* Is the first one a special dummy one? */
-               psv = osv;                                                                      /* Yes, remember it */
-               osv = osv->save_prev_vector;                            /* Step to the next */
-               (savearea *)act->mact.VMX_pcb = osv;            /* Dequeue it */
-               psv->save_flags &= ~SAVvmxvalid;                        /* Clear the VMX flag */
-               if(!(psv->save_flags & SAVinuse)) {                     /* Anyone left with this one? */                        
-                       save_release(psv);                                              /* Nope, release it */
-               }
-       }
+       spc = (unsigned int)thread->map->pmap->space;   /* Get the space we're in */
        
-       psv = 0;
-       while(osv) {                                                                    /* Any VMX saved state? */
-               if(!(osv->save_level_vec)) break;                       /* Leave if this is user state */
+       osv = thread->machine.pcb;                                              /* Get the top general savearea */
+       psv = NULL;
+       while(osv) {                                                                    /* Any saved state? */
+               if(osv->save_srr1 & MASK(MSR_PR)) break;        /* Leave if this is user state */
                psv = osv;                                                                      /* Save previous savearea address */
-               osv = osv->save_prev_vector;                            /* Get one underneath our's */
+               osv = CAST_DOWN(struct savearea *, osv->save_hdr.save_prev);    /* Get one underneath our's */
        }
        
        if(osv) {                                                                               /* Did we find one? */
-               if(psv) psv->save_prev_vector = 0;                      /* Yes, clear pointer to it (it should always be last) or */    
-               else act->mact.VMX_pcb = 0;                                     /* to the start if the only one */
+               if(psv) psv->save_hdr.save_prev = 0;            /* Yes, clear pointer to it (it should always be last) or */    
+               else thread->machine.pcb = NULL;                                        /* to the start if the only one */
 
-               osv->save_flags &= ~SAVvmxvalid;                        /* Clear the VMX flag */
-               if(!(osv->save_flags & SAVinuse)) {                     /* Anyone left with this one? */                        
-                       save_release(osv);                                              /* Nope, release it */
-               }
-       }
-       
-       if(sv->save_flags & SAVvmxvalid) {                              /* Are we adding Altivec context? */
-               if(psv) psv->save_prev_vector = sv;                     /* Yes, chain us to the end or */
-               else act->mact.VMX_pcb = (pcb_t)sv;                     /* to the start if the only one */
+               save_release(osv);                                                      /* Nope, release it */
+               
        }
+
+       if(psv) psv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv);    /* Chain us to the end or */
+       else thread->machine.pcb = (pcb_t)sv;                                   /* to the start if the only one */
+       thread->machine.upcb = (pcb_t)sv;                                               /* Set the user pcb */
        
-       osv = (savearea *)act->mact.FPU_pcb;                    /* Get the top floating point savearea */
+       ovsv = thread->machine.curctx->VMXsave;                         /* Get the top vector savearea */
        
-       if(osv && (osv->save_level_fp == 1)) {                  /* Is the first one a special dummy one? */
-               psv = osv;                                                                      /* Yes, remember it */
-               osv = osv->save_prev_float;                                     /* Step to the next */
-               (savearea *)act->mact.FPU_pcb = osv;            /* Dequeue it */
-               psv->save_flags &= ~SAVfpuvalid;                        /* Clear the float flag */
-               if(!(psv->save_flags & SAVinuse)) {                     /* Anyone left with this one? */                        
-                       save_release(psv);                                              /* Nope, release it */
-               }
+       pvsv = NULL;
+       while(ovsv) {                                                                   /* Any VMX saved state? */
+               if(!(ovsv->save_hdr.save_level)) break;         /* Leave if this is user state */
+               pvsv = ovsv;                                                            /* Save previous savearea address */
+               ovsv = CAST_DOWN(savearea_vec *, ovsv->save_hdr.save_prev);     /* Get one underneath our's */ 
        }
+       
+       if(ovsv) {                                                                              /* Did we find one? */
+               if(pvsv) pvsv->save_hdr.save_prev = 0;          /* Yes, clear pointer to it (it should always be last) or */    
+               else thread->machine.curctx->VMXsave = NULL;    /* to the start if the only one */
 
-       psv = 0;
-       while(osv) {                                                                    /* Any floating point saved state? */
-               if(!(osv->save_level_fp)) break;                        /* Leave if this is user state */
-               psv = osv;                                                                      /* Save previous savearea address */
-               osv = osv->save_prev_float;                                     /* Get one underneath our's */
+               save_release((struct savearea *)ovsv);                          /* Nope, release it */
        }
        
-       if(osv) {                                                                               /* Did we find one? */
-               if(psv) psv->save_prev_float = 0;                       /* Yes, clear pointer to it (it should always be last) or */    
-               else act->mact.FPU_pcb = 0;                                     /* to the start if the only one */
-
-               osv->save_flags &= ~SAVfpuvalid;                        /* Clear the floating point flag */
-               if(!(osv->save_flags & SAVinuse)) {                     /* Anyone left with this one? */                        
-                       save_release(osv);                                              /* Nope, release it */
+       if(vsv) {                                                                               /* Are we sticking any vector on this one? */
+               if(pvsv) pvsv->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv); /* Yes, chain us to the end or */
+               else {
+                       thread->machine.curctx->VMXsave = vsv;  /* to the start if the only one */
+                       thread->machine.curctx->VMXlevel = NULL;        /* Insure that we don't have a leftover level */
                }
+
+               vsv->save_hdr.save_misc2 = 0;                           /* Eye catcher for debug */
+               vsv->save_hdr.save_misc3 = 0;                           /* Eye catcher for debug */
+               vsv->save_hdr.save_act = thread;
        }
        
-       if(sv->save_flags & SAVfpuvalid) {                              /* Are we adding floating point context? */
-               if(psv) psv->save_prev_float = sv;                      /* Yes, chain us to the end or */
-               else act->mact.FPU_pcb = (pcb_t)sv;                     /* to the start if the only one */
-       }
+       ofsv = thread->machine.curctx->FPUsave;                 /* Get the top float savearea */
        
-       osv = (savearea *)act->mact.pcb;                                /* Get the top general savearea */
-       psv = 0;
-       while(osv) {                                                                    /* Any floating point saved state? */
-               if(osv->save_srr1 & MASK(MSR_PR)) break;        /* Leave if this is user state */
-               psv = osv;                                                                      /* Save previous savearea address */
-               osv = osv->save_prev;                                           /* Get one underneath our's */
+       pfsv = NULL;
+       while(ofsv) {                                                                   /* Any float saved state? */
+               if(!(ofsv->save_hdr.save_level)) break;         /* Leave if this is user state */
+               pfsv = ofsv;                                                            /* Save previous savearea address */
+               ofsv = CAST_DOWN(savearea_fpu *, ofsv->save_hdr.save_prev);     /* Get one underneath our's */
        }
        
-       if(osv) {                                                                               /* Did we find one? */
-               if(psv) psv->save_prev = 0;                                     /* Yes, clear pointer to it (it should always be last) or */    
-               else act->mact.pcb = 0;                                         /* to the start if the only one */
+       if(ofsv) {                                                                              /* Did we find one? */
+               if(pfsv) pfsv->save_hdr.save_prev = 0;          /* Yes, clear pointer to it (it should always be last) or */    
+               else thread->machine.curctx->FPUsave = NULL;    /* to the start if the only one */
 
-               osv->save_flags &= ~SAVattach;                          /* Clear the attached flag */
-               if(!(osv->save_flags & SAVinuse)) {                     /* Anyone left with this one? */                        
-                       save_release(osv);                                              /* Nope, release it */
-               }
+               save_release((struct savearea *)ofsv);                          /* Nope, release it */
        }
        
-       if(psv) psv->save_prev = sv;                                    /* Chain us to the end or */
-       else act->mact.pcb = (pcb_t)sv;                                 /* to the start if the only one */
+       if(fsv) {                                                                               /* Are we sticking any vector on this one? */
+               if(pfsv) pfsv->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv); /* Yes, chain us to the end or */
+               else {
+                       thread->machine.curctx->FPUsave = fsv;  /* to the start if the only one */
+                       thread->machine.curctx->FPUlevel = NULL;        /* Insure that we don't have a leftover level */
+               }
 
-       hw_atomic_sub(&saveanchor.saveneed, 1);                 /* Unaccount for the savearea we think we "need" */
+               fsv->save_hdr.save_misc2 = 0;                           /* Eye catcher for debug */
+               fsv->save_hdr.save_misc3 = 0;                           /* Eye catcher for debug */
+               fsv->save_hdr.save_act = thread;
+       }
+       
 }
 
 
@@ -1286,16 +1757,64 @@ void act_thread_catt(void *ctx) {
  *
  */
 
-void act_thread_cfree(void *ctx) {
+void
+act_thread_cfree(void *ctx)
+{
+
+       struct savearea *sv;
+       savearea_fpu    *fsv;
+       savearea_vec    *vsv;
 
-       if((((savearea *)ctx)->save_prev != (savearea *)0xDEBB1ED0) || 
-               (((savearea *)ctx)->save_prev_float != (savearea *)0xE5DA11A5)) {       /* See if valid savearea */
-               panic("act_thread_cfree: attempt to free invalid context savearea - %08X\n", ctx);      /* Die */
+       sv = (struct savearea *)ctx;                                                    /* Make this easier for C */
+       
+       fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0);       /* Get a possible floating point savearea */ 
+       vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1);       /* Get a possible vector savearea */ 
+       
+       if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) {        /* See if valid savearea */
+               panic("act_thread_cfree: attempt to detatch invalid general context savearea - %p\n", sv);      /* Die */
        }
+       
+       save_release(sv);                                                               /* Toss the general savearea */
 
-       ((savearea *)ctx)->save_flags = 0;                              /* Clear all flags since we release this in any case */
-       save_release((savearea *)ctx);                                  /* Release this one */
-       hw_atomic_sub(&saveanchor.saveneed, 1);                 /* Unaccount for the savearea we think we "need" */
+       if(fsv) {                                                                               /* See if there is any saved floating point */ 
+               if((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5)) {      /* See if valid savearea */
+                       panic("act_thread_cfree: attempt to detatch invalid float context savearea - %p\n", fsv);       /* Die */
+               }
+               
+               save_release((struct savearea *)fsv);                           /* Toss saved context */
+       }
+
+       if(vsv) {                                                                               /* See if there is any saved floating point */ 
+               if((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5)) {      /* See if valid savearea */
+                       panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %p\n", vsv);      /* Die */
+               }
+               
+               save_release((struct savearea *)vsv);                           /* Toss saved context */
+       }
        
        return;
 }
+
+/*
+ * thread_enable_fpe:
+ *
+ * enables or disables floating point exceptions for the thread.
+ * returns old state
+ */
+int thread_enable_fpe(
+       thread_t                thread,
+       int                             onoff)
+{
+        struct savearea *sv;
+        uint64_t oldmsr;
+
+        sv = find_user_regs(thread);                                                                           /* Find the user registers */
+        if(!sv) sv = get_user_regs(thread);                                                                    /* Didn't find any, allocate and initialize one */
+
+        oldmsr = sv->save_srr1;                                                                                                /* Get the old msr */
+
+        if(onoff) sv->save_srr1 = oldmsr | (uint64_t)(MASK(MSR_FE0) | MASK(MSR_FE1));  /* Flip on precise FP exceptions */
+        else sv->save_srr1 = oldmsr & (uint64_t)(~(MASK(MSR_FE0) | MASK(MSR_FE1)));            /* Flip on precise FP exceptions */
+
+        return ((oldmsr & (MASK(MSR_FE0) | MASK(MSR_FE1))) != 0);                      /* Return if it was enabled or not */
+}