Make the current FPU owner (`fpproc') a per-CPU entity. Unresolved issue

as yet: lazy FPU context switching may require co-operation from other
CPUs.
This commit is contained in:
pk 1998-09-30 18:38:57 +00:00
parent 7f233b2f7a
commit 4826aac9cf
4 changed files with 47 additions and 25 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cpu.c,v 1.75 1998/09/26 20:13:56 pk Exp $ */
/* $NetBSD: cpu.c,v 1.76 1998/09/30 18:38:57 pk Exp $ */
/*
* Copyright (c) 1996
@ -96,7 +96,6 @@ int ncpu;
struct cpu_info *cpus[_MAXNCPU];
#define CPU_MID2CPUNO(mid) ((mid) - 8)
struct proc *fpproc;
/* The CPU configuration driver. */
static void cpu_attach __P((struct device *, struct device *, void *));

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.130 1998/09/17 02:26:26 thorpej Exp $ */
/* $NetBSD: machdep.c,v 1.131 1998/09/30 18:38:57 pk Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@ -511,10 +511,13 @@ setregs(p, pack, stack)
* we must get rid of it, and the only way to do that is
* to save it. In any case, get rid of our FPU state.
*/
if (p == fpproc) {
if (p == cpuinfo.fpproc) {
savefpstate(fs);
fpproc = NULL;
}
cpuinfo.fpproc = NULL;
} else if (p->p_md.md_fpumid != -1)
panic("setreg: own FPU on module %d; fix this",
p->p_md.md_fpumid);
p->p_md.md_fpumid = -1;
free((void *)fs, M_SUBPROC);
p->p_md.md_fpstate = NULL;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.73 1998/09/20 20:01:15 pk Exp $ */
/* $NetBSD: trap.c,v 1.74 1998/09/30 18:38:57 pk Exp $ */
/*
* Copyright (c) 1996
@ -256,7 +256,7 @@ static __inline void share_fpu(p, tf)
struct proc *p;
struct trapframe *tf;
{
if ((tf->tf_psr & PSR_EF) != 0 && fpproc != p)
if ((tf->tf_psr & PSR_EF) != 0 && cpuinfo.fpproc != p)
tf->tf_psr &= ~PSR_EF;
}
@ -414,11 +414,27 @@ badtrap:
fpu_cleanup(p, fs);
break;
}
if (fpproc != p) { /* we do not have it */
if (fpproc != NULL) /* someone else had it */
savefpstate(fpproc->p_md.md_fpstate);
if (cpuinfo.fpproc != p) { /* we do not have it */
int mid = p->p_md.md_fpumid;
if (cpuinfo.fpproc != NULL) { /* someone else had it*/
savefpstate(cpuinfo.fpproc->p_md.md_fpstate);
cpuinfo.fpproc->p_md.md_fpumid = -1;
}
/*
* On MP machines, some of the other FPUs might
* still have our state. We can't handle that yet,
* so panic if it happens. Possible solutions:
* (1) send an inter-processor message to have the
* other FPU save the state, or (2) don't do lazy FPU
* context switching at all.
*/
if (mid != -1 && mid != cpuinfo.mid) {
printf("own FPU on module %d\n", mid);
panic("fix this");
}
loadfpstate(fs);
fpproc = p; /* now we do have it */
cpuinfo.fpproc = p; /* now we do have it */
p->p_md.md_fpumid = cpuinfo.mid;
}
tf->tf_psr |= PSR_EF;
break;
@ -503,10 +519,10 @@ badtrap:
* will not match once fpu_cleanup does its job, so
* we must not save again later.)
*/
if (p != fpproc)
if (p != cpuinfo.fpproc)
panic("fpe without being the FP user");
savefpstate(p->p_md.md_fpstate);
fpproc = NULL;
cpuinfo.fpproc = NULL;
/* tf->tf_psr &= ~PSR_EF; */ /* share_fpu will do this */
fpu_cleanup(p, p->p_md.md_fpstate);
/* fpu_cleanup posts signals if needed */

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm_machdep.c,v 1.40 1998/09/09 11:17:31 thorpej Exp $ */
/* $NetBSD: vm_machdep.c,v 1.41 1998/09/30 18:38:57 pk Exp $ */
/*
* Copyright (c) 1996
@ -201,12 +201,12 @@ vunmapbuf(bp, len)
*/
void
cpu_fork(p1, p2)
register struct proc *p1, *p2;
struct proc *p1, *p2;
{
register struct pcb *opcb = &p1->p_addr->u_pcb;
register struct pcb *npcb = &p2->p_addr->u_pcb;
register struct trapframe *tf2;
register struct rwindow *rp;
struct pcb *opcb = &p1->p_addr->u_pcb;
struct pcb *npcb = &p2->p_addr->u_pcb;
struct trapframe *tf2;
struct rwindow *rp;
/*
* Save all user registers to p1's stack or, in the case of
@ -223,8 +223,10 @@ cpu_fork(p1, p2)
opcb->pcb_psr = getpsr();
bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb));
if (p1->p_md.md_fpstate) {
if (p1 == fpproc)
if (p1 == cpuinfo.fpproc)
savefpstate(p1->p_md.md_fpstate);
else if (p1->p_md.md_fpumid != -1)
panic("FPU on module %d; fix this", p1->p_md.md_fpumid);
p2->p_md.md_fpstate = malloc(sizeof(struct fpstate),
M_SUBPROC, M_WAITOK);
bcopy(p1->p_md.md_fpstate, p2->p_md.md_fpstate,
@ -232,6 +234,8 @@ cpu_fork(p1, p2)
} else
p2->p_md.md_fpstate = NULL;
p2->p_md.md_fpumid = -1;
/*
* Setup (kernel) stack frame that will by-pass the child
* out of the kernel. (The trap frame invariably resides at
@ -322,12 +326,12 @@ void
cpu_exit(p)
struct proc *p;
{
register struct fpstate *fs;
struct fpstate *fs;
if ((fs = p->p_md.md_fpstate) != NULL) {
if (p == fpproc) {
if (p == cpuinfo.fpproc) {
savefpstate(fs);
fpproc = NULL;
cpuinfo.fpproc = NULL;
}
free((void *)fs, M_SUBPROC);
}
@ -357,7 +361,7 @@ cpu_coredump(p, vp, cred, chdr)
md_core.md_tf = *p->p_md.md_tf;
if (p->p_md.md_fpstate) {
if (p == fpproc)
if (p == cpuinfo.fpproc)
savefpstate(p->p_md.md_fpstate);
md_core.md_fpstate = *p->p_md.md_fpstate;
} else