Index: include/cpu.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/include/cpu.h,v retrieving revision 1.89 diff -p -r1.89 cpu.h *** include/cpu.h 3 Jan 2010 23:03:21 -0000 1.89 --- include/cpu.h 12 Jan 2011 11:42:23 -0000 *************** void schedintr(void *); *** 193,198 **** --- 193,199 ---- /* locore.s */ struct fpstate; + void ipi_savefpstate(struct fpstate *); void savefpstate(struct fpstate *); void loadfpstate(struct fpstate *); int probeget(void *, int); Index: sparc/cpu.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpu.c,v retrieving revision 1.223 diff -p -r1.223 cpu.c *** sparc/cpu.c 22 Jun 2010 18:29:02 -0000 1.223 --- sparc/cpu.c 12 Jan 2011 11:42:23 -0000 *************** __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.22 *** 64,70 **** --- 64,72 ---- #include #include #include + #include #include + #include #include *************** CFATTACH_DECL(cpu_cpuunit, sizeof(struct *** 119,124 **** --- 121,127 ---- cpu_cpuunit_match, cpu_cpuunit_attach, NULL, NULL); #endif /* SUN4D */ + static void cpu_init_evcnt(struct cpu_info *cpi); static void cpu_attach(struct cpu_softc *, int, int); static const char *fsrtoname(int, int, int); *************** cpu_cpuunit_attach(struct device *parent *** 293,298 **** --- 296,316 ---- } #endif /* SUN4D */ + static void + cpu_init_evcnt(struct cpu_info *cpi) + { + + /* + * Setup the per-cpu savefpstate counters. The "savefp null" + * counter should go away when the NULL struct fpstate * bug + * is fixed. + */ + evcnt_attach_dynamic(&cpi->ci_savefpstate, EVCNT_TYPE_MISC, + NULL, cpu_name(cpi), "savefp ipi"); + evcnt_attach_dynamic(&cpi->ci_savefpstate_null, EVCNT_TYPE_MISC, + NULL, cpu_name(cpi), "savefp null ipi"); + } + /* * Attach the CPU. * Discover interesting goop about the virtual address cache *************** cpu_attach(struct cpu_softc *sc, int nod *** 341,350 **** --- 359,371 ---- #if defined(MULTIPROCESSOR) if (cpu_attach_count > 1) { cpu_attach_non_boot(sc, cpi, node); + cpu_init_evcnt(cpi); return; } #endif /* MULTIPROCESSOR */ + cpu_init_evcnt(cpi); + /* Stuff to only run on the boot CPU */ cpu_setup(); snprintf(buf, sizeof buf, "%s @ %s MHz, %s FPU", Index: sparc/cpuvar.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpuvar.h,v retrieving revision 1.83 diff -p -r1.83 cpuvar.h *** sparc/cpuvar.h 23 Jan 2010 16:06:57 -0000 1.83 --- sparc/cpuvar.h 12 Jan 2011 11:42:23 -0000 *************** struct xpmsg { *** 127,132 **** --- 127,139 ---- struct cpu_info { struct cpu_data ci_data; /* MI per-cpu data */ + /* + * Primary Inter-processor message area. Keep this aligned + * to a cache line boundary if possible, as the structure + * itself is one (normal 32 byte) cache-line. + */ + struct xpmsg msg __aligned(32); + /* Scheduler flags */ int ci_want_ast; int ci_want_resched; *************** struct cpu_info { *** 142,150 **** */ struct cpu_info * volatile ci_self; - /* Primary Inter-processor message area */ - struct xpmsg msg; - int ci_cpuid; /* CPU index (see cpus[] array) */ /* Context administration */ --- 149,154 ---- *************** struct cpu_info { *** 334,339 **** --- 338,345 ---- struct evcnt ci_lev10; struct evcnt ci_lev14; + struct evcnt ci_savefpstate; + struct evcnt ci_savefpstate_null; }; /* Index: sparc/genassym.cf =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/genassym.cf,v retrieving revision 1.61 diff -p -r1.61 genassym.cf *** sparc/genassym.cf 20 Dec 2010 00:25:44 -0000 1.61 --- sparc/genassym.cf 12 Jan 2011 11:42:23 -0000 *************** define CPUINFO_IDLESPIN offsetof(struct *** 166,171 **** --- 166,173 ---- define CPUINFO_MTX_COUNT offsetof(struct cpu_info, ci_mtx_count) define CPUINFO_MTX_OLDSPL offsetof(struct cpu_info, ci_mtx_oldspl) define CPUINFO_IDEPTH offsetof(struct cpu_info, ci_idepth) + define CPUINFO_SAVEFPSTATE offsetof(struct cpu_info, ci_savefpstate) + define CPUINFO_SAVEFPSTATE_NULL offsetof(struct cpu_info, ci_savefpstate_null) # PTE bits and related information define PG_W PG_W Index: sparc/locore.s =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/locore.s,v retrieving revision 1.258 diff -p -r1.258 locore.s *** sparc/locore.s 20 Dec 2010 00:25:44 -0000 1.258 --- sparc/locore.s 12 Jan 2011 11:42:24 -0000 *************** Lkcerr: *** 5841,5852 **** /* NOTREACHED */ /* ! * savefpstate(f) struct fpstate *f; * * Store the current FPU state. The first `st %fsr' may cause a trap; * our trap handler knows how to recover (by `returning' to savefpcont). */ ENTRY(savefpstate) rd %psr, %o1 ! enable FP before we begin set PSR_EF, %o2 or %o1, %o2, %o1 --- 5841,5869 ---- /* NOTREACHED */ /* ! * savefpstate(struct fpstate *f); ! * ipi_savefpstate(struct fpstate *f); * * Store the current FPU state. The first `st %fsr' may cause a trap; * our trap handler knows how to recover (by `returning' to savefpcont). + * + * The IPI version just deals with updating event counters first. */ + Lpanic_savefpstate: + .asciz "cpu%d: NULL fpstate" + _ALIGN + + ENTRY(ipi_savefpstate) + sethi %hi(CPUINFO_VA), %o5 + ldd [%o5 + CPUINFO_SAVEFPSTATE], %o2 + inccc %o3 + addx %o2, 0, %o2 + std %o2, [%o5 + CPUINFO_SAVEFPSTATE] + ENTRY(savefpstate) + cmp %o0, 0 + bz Lfp_null_fpstate + nop rd %psr, %o1 ! enable FP before we begin set PSR_EF, %o2 or %o1, %o2, %o1 *************** Lfp_finish: *** 5889,5894 **** --- 5906,5932 ---- std %f30, [%o0 + FS_REGS + (4*30)] /* + * We really should panic here but while we figure out what the bug is + * that a remote CPU gets a NULL struct fpstate *, this lets the system + * work at least seemingly stably. + */ + Lfp_null_fpstate: + #if 1 + sethi %hi(CPUINFO_VA), %o5 + ldd [%o5 + CPUINFO_SAVEFPSTATE_NULL], %o2 + inccc %o3 + addx %o2, 0, %o2 + retl + std %o2, [%o5 + CPUINFO_SAVEFPSTATE_NULL] + #else + ld [%o5 + CPUINFO_CPUNO], %o1 + sethi %hi(Lpanic_savefpstate), %o0 + call _C_LABEL(panic) + or %o0, %lo(Lpanic_savefpstate), %o0 + #endif + 1: + + /* * Store the (now known nonempty) FP queue. * We have to reread the fsr each time in order to get the new QNE bit. */ Index: sparc/machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/machdep.c,v retrieving revision 1.303 diff -p -r1.303 machdep.c *** sparc/machdep.c 20 Dec 2010 00:25:44 -0000 1.303 --- sparc/machdep.c 12 Jan 2011 11:42:24 -0000 *************** setregs(struct lwp *l, struct exec_packa *** 376,382 **** savefpstate(fs); #if defined(MULTIPROCESSOR) else ! XCALL1(savefpstate, fs, 1 << cpi->ci_cpuid); #endif cpi->fplwp = NULL; } --- 376,382 ---- savefpstate(fs); #if defined(MULTIPROCESSOR) else ! XCALL1(ipi_savefpstate, fs, 1 << cpi->ci_cpuid); #endif cpi->fplwp = NULL; } Index: sparc/trap.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/trap.c,v retrieving revision 1.184 diff -p -r1.184 trap.c *** sparc/trap.c 20 Dec 2010 00:25:44 -0000 1.184 --- sparc/trap.c 12 Jan 2011 11:42:24 -0000 *************** badtrap: *** 477,483 **** panic("FPU(%d): state for %p", cpi->ci_cpuid, l); #if defined(MULTIPROCESSOR) ! XCALL1(savefpstate, fs, 1 << cpi->ci_cpuid); #endif cpi->fplwp = NULL; } --- 477,483 ---- panic("FPU(%d): state for %p", cpi->ci_cpuid, l); #if defined(MULTIPROCESSOR) ! XCALL1(ipi_savefpstate, fs, 1 << cpi->ci_cpuid); #endif cpi->fplwp = NULL; } Index: sparc/vm_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/vm_machdep.c,v retrieving revision 1.101 diff -p -r1.101 vm_machdep.c *** sparc/vm_machdep.c 21 Nov 2009 04:16:52 -0000 1.101 --- sparc/vm_machdep.c 12 Jan 2011 11:42:24 -0000 *************** cpu_lwp_fork(struct lwp *l1, struct lwp *** 228,234 **** savefpstate(l1->l_md.md_fpstate); #if defined(MULTIPROCESSOR) else ! XCALL1(savefpstate, l1->l_md.md_fpstate, 1 << cpi->ci_cpuid); #endif } --- 228,234 ---- savefpstate(l1->l_md.md_fpstate); #if defined(MULTIPROCESSOR) else ! XCALL1(ipi_savefpstate, l1->l_md.md_fpstate, 1 << cpi->ci_cpuid); #endif } *************** cpu_lwp_free(struct lwp *l, int proc) *** 306,312 **** savefpstate(fs); #if defined(MULTIPROCESSOR) else ! XCALL1(savefpstate, fs, 1 << cpi->ci_cpuid); #endif cpi->fplwp = NULL; } --- 306,312 ---- savefpstate(fs); #if defined(MULTIPROCESSOR) else ! XCALL1(ipi_savefpstate, fs, 1 << cpi->ci_cpuid); #endif cpi->fplwp = NULL; }