Finish FPU context switching on SMP systems.

This commit is contained in:
pk 2003-01-03 15:12:02 +00:00
parent 7f468ee029
commit ff451161e2
4 changed files with 65 additions and 39 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.7 2000/05/26 21:20:16 thorpej Exp $ */
/* $NetBSD: proc.h,v 1.8 2003/01/03 15:12:02 pk Exp $ */
/*
* Copyright (c) 1992, 1993
@ -51,7 +51,7 @@ struct mdproc {
struct trapframe *md_tf; /* trap/syscall registers */
struct fpstate *md_fpstate; /* fpu state, if any; always resident */
u_long md_flags;
int md_fpumid; /* Module ID of last FPU used */
struct cpu_info *md_fpu; /* Module holding FPU state */
};
/* md_flags */

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.211 2003/01/03 11:57:47 mrg Exp $ */
/* $NetBSD: machdep.c,v 1.212 2003/01/03 15:12:02 pk Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@ -407,18 +407,26 @@ setregs(p, pack, stack)
*/
psr = tf->tf_psr & (PSR_S | PSR_CWP);
if ((fs = p->p_md.md_fpstate) != NULL) {
struct cpu_info *cpi;
/*
* We hold an FPU state. If we own *the* FPU chip state
* We hold an FPU state. If we own *some* FPU chip state
* 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 == cpuinfo.fpproc) {
savefpstate(fs);
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;
if ((cpi = p->p_md.md_fpu) != NULL) {
if (cpi->fpproc != p)
panic("FPU(%d): fpproc %p",
cpi->ci_cpuid, cpi->fpproc);
if (p == cpuinfo.fpproc)
savefpstate(fs);
#if defined(MULTIPROCESSOR)
else
xcall((xcall_func_t)savefpstate,
(int)fs, 0, 0, 0, 1 << cpi->ci_cpuid);
#endif
cpi->fpproc = NULL;
}
p->p_md.md_fpu = NULL;
free((void *)fs, M_SUBPROC);
p->p_md.md_fpstate = NULL;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: trap.c,v 1.119 2002/12/31 13:17:23 pk Exp $ */
/* $NetBSD: trap.c,v 1.120 2003/01/03 15:12:03 pk Exp $ */
/*
* Copyright (c) 1996
@ -468,34 +468,32 @@ badtrap:
KERNEL_PROC_UNLOCK(p);
break;
}
#if notyet
simple_lock(&cpuinfo.fplock);
#if 1
if (cpuinfo.fpproc != p) { /* we do not have it */
struct cpu_info *cpi;
if (cpuinfo.fpproc != NULL) { /* someone else had it*/
savefpstate(cpuinfo.fpproc->p_md.md_fpstate);
cpuinfo.fpproc->p_md.md_fpumid = -1;
cpuinfo.fpproc->p_md.md_fpu = NULL;
}
/*
* On MP machines, some of the other FPUs might
* still have our state. Tell the owning processor
* to save the process' FPU state.
*/
cpi = p->p_md.md_fpumid;
if (cpi != NULL) {
if (cpi->mid == cpuinfo.mid)
panic("FPU on module %d", mid);
LOCK_XPMSG();
simple_lock(&cpi->fplock);
simple_lock(&cpi->msg.lock);
cpi->msg.tag = XPMSG_SAVEFPU;
raise_ipi_wait_and_unlock(cpi);
UNLOCK_XPMSG();
if ((cpi = p->p_md.md_fpu) != NULL) {
if (cpi->ci_cpuid == cpuinfo.ci_cpuid)
panic("FPU(%d): state for %p",
cpi->ci_cpuid, p);
#if defined(MULTIPROCESSOR)
xcall((xcall_func_t)savefpstate,
(int)fs, 0, 0, 0, 1 << cpi->ci_cpuid);
#endif
cpi->fpproc = NULL;
}
loadfpstate(fs);
cpuinfo.fpproc = p; /* now we do have it */
p->p_md.md_fpumid = cpuinfo.mid;
p->p_md.md_fpu = curcpu();
}
simple_unlock(&cpuinfo.fplock);
#else
if (cpuinfo.fpproc != p) { /* we do not have it */
int mid;
@ -808,7 +806,7 @@ mem_access_fault(type, ser, v, pc, psr, tf)
if (cpuinfo.fpproc != p)
panic("FPU enabled but wrong proc (1)");
savefpstate(p->p_md.md_fpstate);
p->p_md.md_fpumid = -1;
p->p_md.md_fpu = NULL;
cpuinfo.fpproc = NULL;
tf->tf_psr &= ~PSR_EF;
setpsr(getpsr() & ~PSR_EF);
@ -984,7 +982,7 @@ mem_access_fault4m(type, sfsr, sfva, tf)
if (cpuinfo.fpproc != p)
panic("FPU enabled but wrong proc (2)");
savefpstate(p->p_md.md_fpstate);
p->p_md.md_fpumid = -1;
p->p_md.md_fpu = NULL;
cpuinfo.fpproc = NULL;
tf->tf_psr &= ~PSR_EF;
setpsr(getpsr() & ~PSR_EF);

View File

@ -1,4 +1,4 @@
/* $NetBSD: vm_machdep.c,v 1.64 2002/12/16 16:59:13 pk Exp $ */
/* $NetBSD: vm_machdep.c,v 1.65 2003/01/03 15:12:03 pk Exp $ */
/*
* Copyright (c) 1996
@ -231,11 +231,21 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
#endif
bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb));
if (p1->p_md.md_fpstate) {
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);
if (p1->p_md.md_fpstate != NULL) {
struct cpu_info *cpi;
if ((cpi = p1->p_md.md_fpu) != NULL) {
if (cpi->fpproc != p1)
panic("FPU(%d): fpproc %p",
cpi->ci_cpuid, cpi->fpproc);
if (p1 == cpuinfo.fpproc)
savefpstate(p1->p_md.md_fpstate);
#if defined(MULTIPROCESSOR)
else
xcall((xcall_func_t)savefpstate,
(int)p1->p_md.md_fpstate, 0, 0, 0,
1 << cpi->ci_cpuid);
#endif
}
p2->p_md.md_fpstate = malloc(sizeof(struct fpstate),
M_SUBPROC, M_WAITOK);
bcopy(p1->p_md.md_fpstate, p2->p_md.md_fpstate,
@ -243,7 +253,7 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
} else
p2->p_md.md_fpstate = NULL;
p2->p_md.md_fpumid = -1;
p2->p_md.md_fpu = NULL;
/*
* Setup (kernel) stack frame that will by-pass the child
@ -303,9 +313,19 @@ cpu_exit(p)
struct fpstate *fs;
if ((fs = p->p_md.md_fpstate) != NULL) {
if (p == cpuinfo.fpproc) {
savefpstate(fs);
cpuinfo.fpproc = NULL;
struct cpu_info *cpi;
if ((cpi = p->p_md.md_fpu) != NULL) {
if (cpi->fpproc != p)
panic("FPU(%d): fpproc %p",
cpi->ci_cpuid, cpi->fpproc);
if (p == cpuinfo.fpproc)
savefpstate(fs);
#if defined(MULTIPROCESSOR)
else
xcall((xcall_func_t)savefpstate,
(int)fs, 0, 0, 0, 1 << cpi->ci_cpuid);
#endif
cpi->fpproc = NULL;
}
free((void *)fs, M_SUBPROC);
}