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 * Copyright (c) 1992, 1993
@ -51,7 +51,7 @@ struct mdproc {
struct trapframe *md_tf; /* trap/syscall registers */ struct trapframe *md_tf; /* trap/syscall registers */
struct fpstate *md_fpstate; /* fpu state, if any; always resident */ struct fpstate *md_fpstate; /* fpu state, if any; always resident */
u_long md_flags; u_long md_flags;
int md_fpumid; /* Module ID of last FPU used */ struct cpu_info *md_fpu; /* Module holding FPU state */
}; };
/* md_flags */ /* 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. * 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); psr = tf->tf_psr & (PSR_S | PSR_CWP);
if ((fs = p->p_md.md_fpstate) != NULL) { 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 * 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. * to save it. In any case, get rid of our FPU state.
*/ */
if (p == cpuinfo.fpproc) { if ((cpi = p->p_md.md_fpu) != NULL) {
savefpstate(fs); if (cpi->fpproc != p)
cpuinfo.fpproc = NULL; panic("FPU(%d): fpproc %p",
} else if (p->p_md.md_fpumid != -1) cpi->ci_cpuid, cpi->fpproc);
panic("setreg: own FPU on module %d; fix this", if (p == cpuinfo.fpproc)
p->p_md.md_fpumid); savefpstate(fs);
p->p_md.md_fpumid = -1; #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); free((void *)fs, M_SUBPROC);
p->p_md.md_fpstate = NULL; 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 * Copyright (c) 1996
@ -468,34 +468,32 @@ badtrap:
KERNEL_PROC_UNLOCK(p); KERNEL_PROC_UNLOCK(p);
break; break;
} }
#if notyet #if 1
simple_lock(&cpuinfo.fplock);
if (cpuinfo.fpproc != p) { /* we do not have it */ if (cpuinfo.fpproc != p) { /* we do not have it */
struct cpu_info *cpi;
if (cpuinfo.fpproc != NULL) { /* someone else had it*/ if (cpuinfo.fpproc != NULL) { /* someone else had it*/
savefpstate(cpuinfo.fpproc->p_md.md_fpstate); 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 * On MP machines, some of the other FPUs might
* still have our state. Tell the owning processor * still have our state. Tell the owning processor
* to save the process' FPU state. * to save the process' FPU state.
*/ */
cpi = p->p_md.md_fpumid; if ((cpi = p->p_md.md_fpu) != NULL) {
if (cpi != NULL) { if (cpi->ci_cpuid == cpuinfo.ci_cpuid)
if (cpi->mid == cpuinfo.mid) panic("FPU(%d): state for %p",
panic("FPU on module %d", mid); cpi->ci_cpuid, p);
LOCK_XPMSG(); #if defined(MULTIPROCESSOR)
simple_lock(&cpi->fplock); xcall((xcall_func_t)savefpstate,
simple_lock(&cpi->msg.lock); (int)fs, 0, 0, 0, 1 << cpi->ci_cpuid);
cpi->msg.tag = XPMSG_SAVEFPU; #endif
raise_ipi_wait_and_unlock(cpi); cpi->fpproc = NULL;
UNLOCK_XPMSG();
} }
loadfpstate(fs); loadfpstate(fs);
cpuinfo.fpproc = p; /* now we do have it */ 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 #else
if (cpuinfo.fpproc != p) { /* we do not have it */ if (cpuinfo.fpproc != p) { /* we do not have it */
int mid; int mid;
@ -808,7 +806,7 @@ mem_access_fault(type, ser, v, pc, psr, tf)
if (cpuinfo.fpproc != p) if (cpuinfo.fpproc != p)
panic("FPU enabled but wrong proc (1)"); panic("FPU enabled but wrong proc (1)");
savefpstate(p->p_md.md_fpstate); savefpstate(p->p_md.md_fpstate);
p->p_md.md_fpumid = -1; p->p_md.md_fpu = NULL;
cpuinfo.fpproc = NULL; cpuinfo.fpproc = NULL;
tf->tf_psr &= ~PSR_EF; tf->tf_psr &= ~PSR_EF;
setpsr(getpsr() & ~PSR_EF); setpsr(getpsr() & ~PSR_EF);
@ -984,7 +982,7 @@ mem_access_fault4m(type, sfsr, sfva, tf)
if (cpuinfo.fpproc != p) if (cpuinfo.fpproc != p)
panic("FPU enabled but wrong proc (2)"); panic("FPU enabled but wrong proc (2)");
savefpstate(p->p_md.md_fpstate); savefpstate(p->p_md.md_fpstate);
p->p_md.md_fpumid = -1; p->p_md.md_fpu = NULL;
cpuinfo.fpproc = NULL; cpuinfo.fpproc = NULL;
tf->tf_psr &= ~PSR_EF; tf->tf_psr &= ~PSR_EF;
setpsr(getpsr() & ~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 * Copyright (c) 1996
@ -231,11 +231,21 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
#endif #endif
bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb)); bcopy((caddr_t)opcb, (caddr_t)npcb, sizeof(struct pcb));
if (p1->p_md.md_fpstate) { if (p1->p_md.md_fpstate != NULL) {
if (p1 == cpuinfo.fpproc) struct cpu_info *cpi;
savefpstate(p1->p_md.md_fpstate); if ((cpi = p1->p_md.md_fpu) != NULL) {
else if (p1->p_md.md_fpumid != -1) if (cpi->fpproc != p1)
panic("FPU on module %d; fix this", p1->p_md.md_fpumid); 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), p2->p_md.md_fpstate = malloc(sizeof(struct fpstate),
M_SUBPROC, M_WAITOK); M_SUBPROC, M_WAITOK);
bcopy(p1->p_md.md_fpstate, p2->p_md.md_fpstate, bcopy(p1->p_md.md_fpstate, p2->p_md.md_fpstate,
@ -243,7 +253,7 @@ cpu_fork(p1, p2, stack, stacksize, func, arg)
} else } else
p2->p_md.md_fpstate = NULL; 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 * Setup (kernel) stack frame that will by-pass the child
@ -303,9 +313,19 @@ cpu_exit(p)
struct fpstate *fs; struct fpstate *fs;
if ((fs = p->p_md.md_fpstate) != NULL) { if ((fs = p->p_md.md_fpstate) != NULL) {
if (p == cpuinfo.fpproc) { struct cpu_info *cpi;
savefpstate(fs); if ((cpi = p->p_md.md_fpu) != NULL) {
cpuinfo.fpproc = 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); free((void *)fs, M_SUBPROC);
} }