#include <kern/thread.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/misc_protos.h>
#include <ppc/fpu_protos.h>
#include <ppc/savearea.h>
#include <ppc/thread.h>
#include <ppc/Firmware.h>
typedef unsigned int fixpt_t;
#include <ppc/vmparam.h>
#include <vm/vm_map.h>
extern unsigned int killprint;
extern double FloatInit;
extern unsigned long QNaNbarbarian[4];
kern_return_t
thread_userstack(
thread_t,
int,
thread_state_t,
unsigned int,
mach_vm_offset_t *,
int *
);
kern_return_t
thread_entrypoint(
thread_t,
int,
thread_state_t,
unsigned int,
mach_vm_offset_t *
);
unsigned int get_msr_exportmask(void);
unsigned int get_msr_nbits(void);
unsigned int get_msr_rbits(void);
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);
unsigned int _MachineStateCount[] = {
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,
};
kern_return_t
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;
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;
genuser = find_user_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) {
return KERN_INVALID_ARGUMENT;
}
ts = (struct ppc_thread_state *) tstate;
sv = genuser;
if(sv) {
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;
ts->vrsave = (unsigned int)sv->save_vrsave;
}
else {
for(i=0; i < 32; i+=2) {
((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;
}
*count = PPC_THREAD_STATE_COUNT;
return KERN_SUCCESS;
case PPC_THREAD_STATE64:
if (*count < PPC_THREAD_STATE64_COUNT) {
return KERN_INVALID_ARGUMENT;
}
xts = (struct ppc_thread_state64 *) tstate;
sv = genuser;
if(sv) {
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;
}
else {
for(i=0; i < 32; i++) {
((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;
xts->vrsave = 0;
}
*count = PPC_THREAD_STATE64_COUNT;
return KERN_SUCCESS;
case PPC_EXCEPTION_STATE:
if (*count < PPC_EXCEPTION_STATE_COUNT) {
return KERN_INVALID_ARGUMENT;
}
es = (struct ppc_exception_state *) tstate;
sv = genuser;
if(sv) {
es->dar = (unsigned int)sv->save_dar;
es->dsisr = sv->save_dsisr;
es->exception = sv->save_exception;
}
else {
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 = genuser;
if(sv) {
xes->dar = sv->save_dar;
xes->dsisr = sv->save_dsisr;
xes->exception = sv->save_exception;
}
else {
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(thread->machine.curctx);
fs = (struct ppc_float_state *) tstate;
fsv = find_user_fpu(thread);
if(fsv) {
bcopy((char *)&fsv->save_fp0, (char *)fs, 32*8);
fs->fpscr_pad = 0;
if(genuser) fs->fpscr = genuser->save_fpscr;
else fs->fpscr = 0;
}
else {
for(i=0; i < 32; i++) {
fs->fpregs[i] = FloatInit;
}
fs->fpscr_pad = 0;
fs->fpscr = 0;
}
*count = PPC_FLOAT_STATE_COUNT;
return KERN_SUCCESS;
case PPC_VECTOR_STATE:
if (*count < PPC_VECTOR_STATE_COUNT) {
return KERN_INVALID_ARGUMENT;
}
vec_save(thread->machine.curctx);
vs = (struct ppc_vector_state *) tstate;
vsv = find_user_vec(thread);
if(vsv) {
vrvalidwrk = vsv->save_vrvalid;
vs->save_vrvalid = vsv->save_vrvalid;
if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j];
else {
vs->save_vscr[0] = 0;
vs->save_vscr[1] = 0;
vs->save_vscr[2] = 0;
vs->save_vscr[3] = 0x00010000;
}
for(i=0; i < 32; i++) {
for(j=0; j < 4; j++) {
if(vrvalidwrk & 0x80000000) (vs->save_vr)[i][j] =
((unsigned int *)&(vsv->save_vr0))[(i * 4) + j];
else vs->save_vr[i][j] = QNaNbarbarian[j];
}
vrvalidwrk = vrvalidwrk << 1;
}
}
else {
for(i=0; i < 32; i++) {
for(j=0; j < 4; j++) vs->save_vr[i][j] = QNaNbarbarian[j];
}
if(genuser) for(j=0; j < 4; j++) vs->save_vscr[j] = genuser->save_vscr[j];
else {
vs->save_vscr[0] = 0;
vs->save_vscr[1] = 0;
vs->save_vscr[2] = 0;
vs->save_vscr[3] = 0x00010000;
}
vs->save_vrvalid = 0;
}
for (i=0; i < 4; i++) vs->save_pad5[i] = 0;
for (i=0; i < 7; i++) vs->save_pad6[i] = 0;
*count = PPC_VECTOR_STATE_COUNT;
return KERN_SUCCESS;
default:
return KERN_INVALID_ARGUMENT;
}
}
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;
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) {
return KERN_INVALID_ARGUMENT;
}
ts = (struct ppc_thread_state *) tstate;
sv = genkern;
if(sv) {
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;
ts->vrsave = (unsigned int)sv->save_vrsave;
}
else {
for(i=0; i < 32; i+=2) {
((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;
}
*count = PPC_THREAD_STATE_COUNT;
return KERN_SUCCESS;
case PPC_THREAD_STATE64:
if (*count < PPC_THREAD_STATE64_COUNT) {
return KERN_INVALID_ARGUMENT;
}
xts = (struct ppc_thread_state64 *) tstate;
sv = genkern;
if(sv) {
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;
}
else {
for(i=0; i < 32; i++) {
((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;
}
*count = PPC_THREAD_STATE64_COUNT;
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;
if(sv) {
es->dar = (unsigned int)sv->save_dar;
es->dsisr = sv->save_dsisr;
es->exception = sv->save_exception;
}
else {
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;
if(sv) {
xes->dar = sv->save_dar;
xes->dsisr = sv->save_dsisr;
xes->exception = sv->save_exception;
}
else {
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;
}
}
kern_return_t
machine_thread_set_state(
thread_t thread,
thread_flavor_t flavor,
thread_state_t tstate,
mach_msg_type_number_t count)
{
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;
clgn = count;
switch (flavor) {
case PPC_THREAD_STATE:
if (clgn < PPC_THREAD_STATE_COUNT) {
return KERN_INVALID_ARGUMENT;
}
break;
case PPC_THREAD_STATE64:
if (clgn < PPC_THREAD_STATE64_COUNT) {
return KERN_INVALID_ARGUMENT;
}
break;
case PPC_EXCEPTION_STATE:
if (clgn < PPC_EXCEPTION_STATE_COUNT) {
return KERN_INVALID_ARGUMENT;
}
case PPC_EXCEPTION_STATE64:
if (clgn < PPC_EXCEPTION_STATE64_COUNT) {
return KERN_INVALID_ARGUMENT;
}
break;
case PPC_FLOAT_STATE:
if (clgn < PPC_FLOAT_STATE_COUNT) {
return KERN_INVALID_ARGUMENT;
}
break;
case PPC_VECTOR_STATE:
if (clgn < PPC_VECTOR_STATE_COUNT) {
return KERN_INVALID_ARGUMENT;
}
break;
default:
return KERN_INVALID_ARGUMENT;
}
genuser = get_user_regs(thread);
switch (flavor) {
case PPC_THREAD_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;
genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, ts->srr1);
genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));
if(task_has_64BitAddr(thread->task))
genuser->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32;
else
genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32);
return KERN_SUCCESS;
case PPC_THREAD_STATE64:
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;
genuser->save_srr1 = MSR_PREPARE_FOR_IMPORT(genuser->save_srr1, xts->srr1);
genuser->save_srr1 |= MSR_EXPORT_MASK_SET;
genuser->save_srr1 &= ~(MASK(MSR_FP) | MASK(MSR_VEC));
if(task_has_64BitAddr(thread->task))
genuser->save_srr1 |= (uint64_t)MASK32(MSR_SF) << 32;
else
genuser->save_srr1 &= ~((uint64_t)MASK32(MSR_SF) << 32);
return KERN_SUCCESS;
case PPC_EXCEPTION_STATE:
es = (struct ppc_exception_state *) tstate;
genuser->save_dar = (uint64_t)es->dar;
genuser->save_dsisr = es->dsisr;
genuser->save_exception = es->exception;
return KERN_SUCCESS;
case PPC_EXCEPTION_STATE64:
xes = (struct ppc_exception_state *) tstate;
genuser->save_dar = xes->dar;
genuser->save_dsisr = xes->dsisr;
genuser->save_exception = xes->exception;
return KERN_SUCCESS;
case PPC_FLOAT_STATE:
toss_live_fpu(thread->machine.curctx);
fsv = find_user_fpu(thread);
if(!fsv) {
fsv = (savearea_fpu *)save_alloc();
fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft);
fsv->save_hdr.save_act = thread;
fsv->save_hdr.save_prev = 0;
fsv->save_hdr.save_level = 0;
if(!thread->machine.curctx->FPUsave) thread->machine.curctx->FPUsave = fsv;
else {
fsvn = fsvo = thread->machine.curctx->FPUsave;
while (fsvn) {
fsvo = fsvn;
fsvn = CAST_DOWN(savearea_fpu *, fsvo->save_hdr.save_prev);
}
fsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv);
}
}
fs = (struct ppc_float_state *) tstate;
bcopy((char *)fs, (char *)&fsv->save_fp0, 32*8);
genuser->save_fpscr = fs->fpscr;
return KERN_SUCCESS;
case PPC_VECTOR_STATE:
toss_live_vec(thread->machine.curctx);
vsv = find_user_vec(thread);
if(!vsv) {
vsv = (savearea_vec *)save_alloc();
vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);
vsv->save_hdr.save_act = thread;
vsv->save_hdr.save_prev = 0;
vsv->save_hdr.save_level = 0;
if(!thread->machine.curctx->VMXsave) thread->machine.curctx->VMXsave = vsv;
else {
vsvn = vsvo = thread->machine.curctx->VMXsave;
while (vsvn) {
vsvo = vsvn;
vsvn = CAST_DOWN(savearea_vec *, vsvo->save_hdr.save_prev);
}
vsvo->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv);
}
}
vs = (struct ppc_vector_state *) tstate;
bcopy((char *)vs, (char *)&vsv->save_vr0, 32*16);
vsv->save_vrvalid = vs->save_vrvalid;
for(i = 0; i < 4; i++) genuser->save_vscr[i] = vs->save_vscr[i];
return KERN_SUCCESS;
default:
return KERN_INVALID_ARGUMENT;
}
}
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);
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 (curth != thread)
thread_unlock(thread);
}
kern_return_t
machine_thread_state_initialize(
thread_t thread)
{
struct savearea *sv;
sv = get_user_regs(thread);
sv->save_fpscr = 0;
sv->save_vrsave = 0;
sv->save_vscr[0] = 0x00000000;
sv->save_vscr[1] = 0x00000000;
sv->save_vscr[2] = 0x00000000;
sv->save_vscr[3] = 0x00010000;
return KERN_SUCCESS;
}
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(self->machine.curctx);
vec_save(self->machine.curctx);
sv = get_user_regs(target);
osv = find_user_regs(self);
if(!osv)
return (KERN_FAILURE);
bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)),
(char *)((unsigned int)sv + sizeof(savearea_comm)),
sizeof(struct savearea) - sizeof(savearea_comm));
sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC)));
fsv = find_user_fpu(self);
target->machine.curctx->FPUsave = NULL;
if(fsv) {
fsvn = (savearea_fpu *)save_alloc();
fsvn->save_hdr.save_flags = (fsvn->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft);
fsvn->save_hdr.save_act = target;
fsvn->save_hdr.save_prev = 0;
fsvn->save_hdr.save_level = 0;
target->machine.curctx->FPUsave = fsvn;
bcopy((char *)((unsigned int)fsv + sizeof(savearea_comm)),
(char *)((unsigned int)fsvn + sizeof(savearea_comm)),
sizeof(struct savearea) - sizeof(savearea_comm));
}
vsv = find_user_vec(self);
target->machine.curctx->VMXsave = NULL;
if(vsv) {
vsvn = (savearea_vec *)save_alloc();
vsvn->save_hdr.save_flags = (vsvn->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);
vsvn->save_hdr.save_act = target;
vsvn->save_hdr.save_prev = 0;
vsvn->save_hdr.save_level = 0;
target->machine.curctx->VMXsave = vsvn;
bcopy((char *)((unsigned int)vsv + sizeof(savearea_comm)),
(char *)((unsigned int)vsvn + sizeof(savearea_comm)),
sizeof(struct savearea) - sizeof(savearea_comm));
}
return (KERN_SUCCESS);
}
struct savearea *
get_user_regs(
thread_t thread)
{
struct savearea *sv, *osv;
unsigned int i;
if (thread->machine.upcb)
return thread->machine.upcb;
sv = thread->machine.pcb;
osv = NULL;
while(sv) {
osv = sv;
sv = CAST_DOWN(struct savearea *, sv->save_hdr.save_prev);
}
sv = save_alloc();
sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft);
sv->save_hdr.save_act = thread;
sv->save_hdr.save_prev = 0;
sv->save_hdr.save_level = 0;
if(osv) {
osv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv);
}
else {
thread->machine.pcb = sv;
}
thread->machine.upcb = sv;
for(i=0; i < 32; i+=2) {
((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 = (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;
sv->save_fpscr = 0;
sv->save_vrsave = 0;
sv->save_vscr[0] = 0x00000000;
sv->save_vscr[1] = 0x00000000;
sv->save_vscr[2] = 0x00000000;
sv->save_vscr[3] = 0x00010000;
return sv;
}
struct savearea *
find_user_regs(
thread_t thread)
{
return thread->machine.upcb;
}
struct savearea *
find_kern_regs(
thread_t thread)
{
return thread->machine.pcb;
}
savearea_fpu *
find_user_fpu(
thread_t thread)
{
savearea_fpu *fsv;
boolean_t intr;
intr = ml_set_interrupts_enabled(FALSE);
fsv = thread->machine.curctx->FPUsave;
while(fsv) {
if(!(fsv->save_hdr.save_level)) break;
fsv = CAST_DOWN(savearea_fpu *, fsv->save_hdr.save_prev);
}
(void) ml_set_interrupts_enabled(intr);
return fsv;
}
savearea_vec *
find_user_vec(
thread_t thread)
{
savearea_vec *vsv;
boolean_t intr;
intr = ml_set_interrupts_enabled(FALSE);
vsv = thread->machine.curctx->VMXsave;
while(vsv) {
if(!(vsv->save_hdr.save_level)) break;
vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev);
}
(void) ml_set_interrupts_enabled(intr);
return vsv;
}
savearea_vec *find_user_vec_curr(void) {
savearea_vec *vsv;
thread_t thread = current_thread();
boolean_t intr;
vec_save(thread->machine.curctx);
intr = ml_set_interrupts_enabled(FALSE);
vsv = thread->machine.curctx->VMXsave;
while(vsv) {
if(!(vsv->save_hdr.save_level)) break;
vsv = CAST_DOWN(savearea_vec *, vsv->save_hdr.save_prev);
}
(void) ml_set_interrupts_enabled(intr);
return vsv;
}
kern_return_t
thread_userstack(
__unused thread_t thread,
int flavor,
thread_state_t tstate,
unsigned int count,
mach_vm_offset_t *user_stack,
int *customstack
)
{
switch (flavor) {
case PPC_THREAD_STATE:
{
struct ppc_thread_state *state;
if (count < PPC_THREAD_STATE_COUNT)
return (KERN_INVALID_ARGUMENT);
state = (struct ppc_thread_state *) tstate;
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 (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);
}
return (KERN_SUCCESS);
}
void
thread_setuserstack(thread_t thread, mach_vm_address_t user_stack)
{
struct savearea *sv;
sv = get_user_regs(thread);
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);
thread->machine.cthread_self = pself;
sv->save_r13 = pself;
}
}
uint64_t
thread_adjuserstack(thread_t thread, int adjust)
{
struct savearea *sv;
sv = get_user_regs(thread);
sv->save_r1 += adjust;
return sv->save_r1;
}
kern_return_t
thread_setsinglestep(thread_t thread, int on)
{
struct savearea *sv;
sv = get_user_regs(thread);
if (on)
sv->save_srr1 |= MASK(MSR_SE);
else
sv->save_srr1 &= ~MASK(MSR_SE);
return (KERN_SUCCESS);
}
void
thread_setentrypoint(thread_t thread, uint64_t entry)
{
struct savearea *sv;
sv = get_user_regs(thread);
sv->save_srr0 = entry;
}
kern_return_t
thread_entrypoint(
__unused thread_t thread,
int flavor,
thread_state_t tstate,
unsigned int count,
mach_vm_offset_t *entry_point
)
{
#if 0
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);
state = (struct ppc_thread_state *) tstate;
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 (state64->srr0) {
*entry_point = state64->srr0;
} else {
*entry_point = MACH_VM_MIN_ADDRESS;
}
}
break;
default:
return (KERN_INVALID_ARGUMENT);
}
return (KERN_SUCCESS);
}
unsigned int get_msr_exportmask(void)
{
return (MSR_EXPORT_MASK_SET);
}
unsigned int get_msr_nbits(void)
{
return (MASK(MSR_POW)|MASK(MSR_ILE)|MASK(MSR_IP)|MASK(MSR_LE));
}
unsigned int get_msr_rbits(void)
{
return (MASK(MSR_PR)|MASK(MSR_ME)|MASK(MSR_IR)|MASK(MSR_DR)|MASK(MSR_EE));
}
void ppc_checkthreadstate(void * tsptr, int flavor)
{
if (flavor == PPC_THREAD_STATE64) {
struct ppc_thread_state64 *ts64 =(struct ppc_thread_state64 *)tsptr;
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;
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 savearea *child_state;
child_state = get_user_regs(child);
child_state->save_r3 = (uint_t)pid;
child_state->save_r4 = 1ULL;
}
void
thread_set_parent(
thread_t parent,
int pid)
{
struct savearea *parent_state;
parent_state = get_user_regs(parent);
parent_state->save_r3 = (uint64_t)pid;
parent_state->save_r4 = 0;
}
void *act_thread_csave(void) {
struct savearea *sv, *osv;
savearea_fpu *fsv, *ofsv;
savearea_vec *vsv, *ovsv;
thread_t thread;
thread = current_thread();
fpu_save(thread->machine.curctx);
vec_save(thread->machine.curctx);
osv = find_user_regs(thread);
if(!osv) {
panic("act_thread_csave: attempting to preserve the context of an activation with none (%p)\n", thread);
}
sv = save_alloc();
sv->save_hdr.save_flags = (sv->save_hdr.save_flags & ~SAVtype) | (SAVgeneral << SAVtypeshft);
sv->save_hdr.save_act = thread;
sv->save_hdr.save_prev = 0;
sv->save_hdr.save_level = 0;
bcopy((char *)((unsigned int)osv + sizeof(savearea_comm)),
(char *)((unsigned int)sv + sizeof(savearea_comm)),
sizeof(struct savearea) - sizeof(savearea_comm));
sv->save_srr1 &= (uint64_t)(~(MASK(MSR_FP) | MASK(MSR_VEC)));
sv->save_hdr.save_misc2 = 0xDEBB1ED0;
sv->save_hdr.save_misc3 = 0xE5DA11A5;
ofsv = find_user_fpu(thread);
sv->save_hdr.save_misc0 = 0;
if(ofsv) {
fsv = (savearea_fpu *)save_alloc();
fsv->save_hdr.save_flags = (fsv->save_hdr.save_flags & ~SAVtype) | (SAVfloat << SAVtypeshft);
fsv->save_hdr.save_act = thread;
fsv->save_hdr.save_prev = 0;
fsv->save_hdr.save_level = 0;
fsv->save_hdr.save_misc2 = 0xDEBB1ED0;
fsv->save_hdr.save_misc3 = 0xE5DA11A5;
sv->save_hdr.save_misc0 = (uint64_t)((uintptr_t)fsv);
bcopy((char *)((unsigned int)ofsv + sizeof(savearea_comm)),
(char *)((unsigned int)fsv + sizeof(savearea_comm)),
sizeof(struct savearea) - sizeof(savearea_comm));
}
ovsv = find_user_vec(thread);
sv->save_hdr.save_misc1 = 0;
if(ovsv) {
vsv = (savearea_vec *)save_alloc();
vsv->save_hdr.save_flags = (vsv->save_hdr.save_flags & ~SAVtype) | (SAVvector << SAVtypeshft);
vsv->save_hdr.save_act = thread;
vsv->save_hdr.save_prev = 0;
vsv->save_hdr.save_level = 0;
vsv->save_hdr.save_misc2 = 0xDEBB1ED0;
vsv->save_hdr.save_misc3 = 0xE5DA11A5;
sv->save_hdr.save_misc1 = (uint64_t)((uintptr_t)vsv);
bcopy((char *)((unsigned int)ovsv + sizeof(savearea_comm)),
(char *)((unsigned int)vsv + sizeof(savearea_comm)),
sizeof(struct savearea) - sizeof(savearea_comm));
}
return (void *)sv;
}
void act_thread_catt(void *ctx) {
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;
fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0);
vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1);
if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) {
panic("act_thread_catt: attempt to attach invalid general context savearea - %p\n", sv);
}
if(fsv && ((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5))) {
panic("act_thread_catt: attempt to attach invalid float context savearea - %p\n", fsv);
}
if(vsv && ((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5))) {
panic("act_thread_catt: attempt to attach invalid vector context savearea - %p\n", vsv);
}
thread = current_thread();
act_machine_sv_free(thread, 0);
toss_live_fpu(thread->machine.curctx);
toss_live_vec(thread->machine.curctx);
sv->save_hdr.save_misc2 = 0;
sv->save_hdr.save_misc3 = 0;
sv->save_hdr.save_act = thread;
spc = (unsigned int)thread->map->pmap->space;
osv = thread->machine.pcb;
psv = NULL;
while(osv) {
if(osv->save_srr1 & MASK(MSR_PR)) break;
psv = osv;
osv = CAST_DOWN(struct savearea *, osv->save_hdr.save_prev);
}
if(osv) {
if(psv) psv->save_hdr.save_prev = 0;
else thread->machine.pcb = NULL;
save_release(osv);
}
if(psv) psv->save_hdr.save_prev = (addr64_t)((uintptr_t)sv);
else thread->machine.pcb = (pcb_t)sv;
thread->machine.upcb = (pcb_t)sv;
ovsv = thread->machine.curctx->VMXsave;
pvsv = NULL;
while(ovsv) {
if(!(ovsv->save_hdr.save_level)) break;
pvsv = ovsv;
ovsv = CAST_DOWN(savearea_vec *, ovsv->save_hdr.save_prev);
}
if(ovsv) {
if(pvsv) pvsv->save_hdr.save_prev = 0;
else thread->machine.curctx->VMXsave = NULL;
save_release((struct savearea *)ovsv);
}
if(vsv) {
if(pvsv) pvsv->save_hdr.save_prev = (addr64_t)((uintptr_t)vsv);
else {
thread->machine.curctx->VMXsave = vsv;
thread->machine.curctx->VMXlevel = NULL;
}
vsv->save_hdr.save_misc2 = 0;
vsv->save_hdr.save_misc3 = 0;
vsv->save_hdr.save_act = thread;
}
ofsv = thread->machine.curctx->FPUsave;
pfsv = NULL;
while(ofsv) {
if(!(ofsv->save_hdr.save_level)) break;
pfsv = ofsv;
ofsv = CAST_DOWN(savearea_fpu *, ofsv->save_hdr.save_prev);
}
if(ofsv) {
if(pfsv) pfsv->save_hdr.save_prev = 0;
else thread->machine.curctx->FPUsave = NULL;
save_release((struct savearea *)ofsv);
}
if(fsv) {
if(pfsv) pfsv->save_hdr.save_prev = (addr64_t)((uintptr_t)fsv);
else {
thread->machine.curctx->FPUsave = fsv;
thread->machine.curctx->FPUlevel = NULL;
}
fsv->save_hdr.save_misc2 = 0;
fsv->save_hdr.save_misc3 = 0;
fsv->save_hdr.save_act = thread;
}
}
void
act_thread_cfree(void *ctx)
{
struct savearea *sv;
savearea_fpu *fsv;
savearea_vec *vsv;
sv = (struct savearea *)ctx;
fsv = CAST_DOWN(savearea_fpu *, sv->save_hdr.save_misc0);
vsv = CAST_DOWN(savearea_vec *, sv->save_hdr.save_misc1);
if((sv->save_hdr.save_misc2 != 0xDEBB1ED0) || (sv->save_hdr.save_misc3 != 0xE5DA11A5)) {
panic("act_thread_cfree: attempt to detatch invalid general context savearea - %p\n", sv);
}
save_release(sv);
if(fsv) {
if((fsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (fsv->save_hdr.save_misc3 != 0xE5DA11A5)) {
panic("act_thread_cfree: attempt to detatch invalid float context savearea - %p\n", fsv);
}
save_release((struct savearea *)fsv);
}
if(vsv) {
if((vsv->save_hdr.save_misc2 != 0xDEBB1ED0) || (vsv->save_hdr.save_misc3 != 0xE5DA11A5)) {
panic("act_thread_cfree: attempt to detatch invalid vector context savearea - %p\n", vsv);
}
save_release((struct savearea *)vsv);
}
return;
}
int thread_enable_fpe(
thread_t thread,
int onoff)
{
struct savearea *sv;
uint64_t oldmsr;
sv = find_user_regs(thread);
if(!sv) sv = get_user_regs(thread);
oldmsr = sv->save_srr1;
if(onoff) sv->save_srr1 = oldmsr | (uint64_t)(MASK(MSR_FE0) | MASK(MSR_FE1));
else sv->save_srr1 = oldmsr & (uint64_t)(~(MASK(MSR_FE0) | MASK(MSR_FE1)));
return ((oldmsr & (MASK(MSR_FE0) | MASK(MSR_FE1))) != 0);
}