summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2008-04-27 16:01:48 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2008-04-27 16:01:48 +0000
commitbd03abea783aaa8400341d61a5af3f6f0f8f7bf2 (patch)
tree97a90dc24f46b4ea4de2ae57eaab17ac9523e52b
parent5788a8af1750cfa41066856b1ecabf16211465dc (diff)
FPU/Altivec cleanup and prep for SMP.
-rw-r--r--sys/arch/powerpc/include/pcb.h4
-rw-r--r--sys/arch/powerpc/powerpc/fpu.c9
-rw-r--r--sys/arch/powerpc/powerpc/trap.c17
3 files changed, 24 insertions, 6 deletions
diff --git a/sys/arch/powerpc/include/pcb.h b/sys/arch/powerpc/include/pcb.h
index 7560dee7b17..e6672182033 100644
--- a/sys/arch/powerpc/include/pcb.h
+++ b/sys/arch/powerpc/include/pcb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcb.h,v 1.11 2007/10/10 15:53:52 art Exp $ */
+/* $OpenBSD: pcb.h,v 1.12 2008/04/27 16:01:47 drahn Exp $ */
/* $NetBSD: pcb.h,v 1.1 1996/09/30 16:34:29 ws Exp $ */
/*-
@@ -57,6 +57,8 @@ struct pcb {
double fpcsr; /* FPCSR stored as double for easier access */
} pcb_fpu; /* Floating point processor */
struct vreg *pcb_vr; /* Vector unit */
+ struct cpu_info *pcb_fpcpu;
+ struct cpu_info *pcb_veccpu;
};
struct md_coredump {
diff --git a/sys/arch/powerpc/powerpc/fpu.c b/sys/arch/powerpc/powerpc/fpu.c
index 7b40ea97df6..b4d01c1b1d3 100644
--- a/sys/arch/powerpc/powerpc/fpu.c
+++ b/sys/arch/powerpc/powerpc/fpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fpu.c,v 1.10 2007/03/20 20:59:53 kettenis Exp $ */
+/* $OpenBSD: fpu.c,v 1.11 2008/04/27 16:01:47 drahn Exp $ */
/* $NetBSD: fpu.c,v 1.1 1996/09/30 16:34:44 ws Exp $ */
/*
@@ -50,6 +50,11 @@ enable_fpu(struct proc *p)
bzero(&pcb->pcb_fpu, sizeof pcb->pcb_fpu);
pcb->pcb_flags |= PCB_FPU;
}
+
+ if (pcb->pcb_fpcpu != NULL || ci->ci_fpuproc != NULL) {
+ printf("attempting to restore fpu state when in use pcb %x"
+ " fpproc %x\n", pcb->pcb_fpcpu, ci->ci_fpuproc);
+ }
msr = ppc_mfmsr();
ppc_mtmsr((msr & ~PSL_EE) | PSL_FP);
__asm volatile("isync");
@@ -88,6 +93,7 @@ enable_fpu(struct proc *p)
"lfd 30,240(%0);"
"lfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0]));
ci->ci_fpuproc = p;
+ pcb->pcb_fpcpu = ci;
tf->srr1 |= PSL_FP;
ppc_mtmsr(msr);
__asm volatile("isync");
@@ -154,6 +160,7 @@ save_fpu()
tf = trapframe(ci->ci_fpuproc);
tf->srr1 &= ~PSL_FP;
ci->ci_fpuproc = NULL;
+ pcb->pcb_fpcpu = NULL;
ppc_mtmsr(msr);
__asm volatile("isync");
diff --git a/sys/arch/powerpc/powerpc/trap.c b/sys/arch/powerpc/powerpc/trap.c
index b418ccc42ed..6ceff97cb4b 100644
--- a/sys/arch/powerpc/powerpc/trap.c
+++ b/sys/arch/powerpc/powerpc/trap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: trap.c,v 1.80 2008/04/27 15:59:49 drahn Exp $ */
+/* $OpenBSD: trap.c,v 1.81 2008/04/27 16:01:47 drahn Exp $ */
/* $NetBSD: trap.c,v 1.3 1996/10/13 03:31:37 christos Exp $ */
/*
@@ -118,7 +118,7 @@ save_vec(struct proc *p)
* in kernel mode
*/
oldmsr = ppc_mfmsr();
- msr = oldmsr | PSL_VEC;
+ msr = (oldmsr & ~PSL_EE) | PSL_VEC;
ppc_mtmsr(msr);
__asm__ volatile ("sync;isync");
@@ -163,6 +163,9 @@ save_vec(struct proc *p)
__asm__ volatile ("mfvscr 0");
SAVE_VEC_REG(0,&pcb_vr->vscr);
+ curcpu()->ci_vecproc = NULL;
+ pcb->pcb_veccpu = NULL;
+
/* fix kernel msr back */
ppc_mtmsr(oldmsr);
}
@@ -175,6 +178,7 @@ enable_vec(struct proc *p)
{
struct pcb *pcb = &p->p_addr->u_pcb;
struct vreg *pcb_vr = pcb->pcb_vr;
+ struct cpu_info *ci = curcpu();
u_int32_t oldmsr, msr;
/* If this is the very first altivec instruction executed
@@ -185,13 +189,19 @@ enable_vec(struct proc *p)
bzero(pcb->pcb_vr, sizeof *(pcb->pcb_vr));
}
+ if (curcpu()->ci_vecproc != NULL || pcb->pcb_veccpu != NULL)
+ printf("attempting to restore vector in use vecproc %x"
+ " veccpu %x\n", curcpu()->ci_vecproc, pcb->pcb_veccpu);
+
/* first we enable vector so that we dont throw an exception
* in kernel mode
*/
oldmsr = ppc_mfmsr();
- msr = oldmsr | PSL_VEC;
+ msr = (oldmsr & ~PSL_EE) | PSL_VEC;
ppc_mtmsr(msr);
__asm__ volatile ("sync;isync");
+ ci->ci_vecproc = p;
+ pcb->pcb_veccpu = ci;
#define LOAD_VEC_REG(reg, addr) \
__asm__ volatile ("lvxl %0, 0, %1" :: "n"(reg), "r" (addr));
@@ -643,7 +653,6 @@ for (i = 0; i < errnum; i++) {
if (ci->ci_vecproc)
save_vec(ci->ci_vecproc);
- ci->ci_vecproc = p;
enable_vec(p);
break;
#else /* ALTIVEC */