+/* 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 */
+ 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;
+ }
+}