? fpusave_lwp.diff ? conf/GENERIC.MPLD Index: include/intr.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/include/intr.h,v retrieving revision 1.11 diff -p -r1.11 intr.h *** include/intr.h 28 Apr 2008 20:23:36 -0000 1.11 --- include/intr.h 26 Jan 2011 06:13:48 -0000 *************** *** 59,65 **** * IPL_SERIAL must protect them all. */ ! #define IPL_ZS IPL_HIGH #if defined(_KERNEL) && !defined(_LOCORE) void * --- 59,65 ---- * IPL_SERIAL must protect them all. */ ! #define IPL_ZS 13 #if defined(_KERNEL) && !defined(_LOCORE) void * Index: sparc/cpu.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpu.c,v retrieving revision 1.225 diff -p -r1.225 cpu.c *** sparc/cpu.c 22 Jan 2011 12:13:25 -0000 1.225 --- sparc/cpu.c 26 Jan 2011 06:13:48 -0000 *************** int go_smp_cpus = 0; /* non-primary CPUs *** 175,180 **** --- 175,193 ---- */ static kmutex_t xpmsg_mutex; + #ifdef DIAGNOSTIC + static struct evcnt ipi_timeout_100ms = + EVCNT_INITIALIZER(EVCNT_TYPE_MISC, 0, "ipi", "100ms timeout"); + static struct evcnt ipi_timeout_250ms = + EVCNT_INITIALIZER(EVCNT_TYPE_MISC, 0, "ipi", "250ms timeout"); + static struct evcnt ipi_timeout_500ms = + EVCNT_INITIALIZER(EVCNT_TYPE_MISC, 0, "ipi", "500ms timeout"); + + EVCNT_ATTACH_STATIC(ipi_timeout_100ms); + EVCNT_ATTACH_STATIC(ipi_timeout_250ms); + EVCNT_ATTACH_STATIC(ipi_timeout_500ms); + #endif + #endif /* MULTIPROCESSOR */ /* *************** void *** 578,593 **** xcall(xcall_func_t func, xcall_trap_t trap, int arg0, int arg1, int arg2, u_int cpuset) { struct cpu_info *cpi; ! int n, i, done, callself, mybit; volatile struct xpmsg_func *p; int fasttrap; int is_noop = func == (xcall_func_t)sparc_noop; mybit = (1 << cpuinfo.ci_cpuid); callself = func && (cpuset & mybit) != 0; cpuset &= ~mybit; /* Mask any CPUs that are not ready */ cpuset &= cpu_ready_mask; --- 591,641 ---- xcall(xcall_func_t func, xcall_trap_t trap, int arg0, int arg1, int arg2, u_int cpuset) { + struct timeval cur, ipitimeout; struct cpu_info *cpi; ! int i, n, callself, mybit; volatile struct xpmsg_func *p; + u_int failed_cpuset = 0; int fasttrap; int is_noop = func == (xcall_func_t)sparc_noop; + bool timeout = false, done; + struct timeval timeout_val = { + .tv_sec = 1, + .tv_usec = 0, + }; + #ifdef DIAGNOSTIC + struct timeval timeout_100ms, val_100ms = { + .tv_sec = 0, + .tv_usec = 100 * 1000, + }; + bool done_timeout_100ms = false; + + struct timeval timeout_250ms, val_250ms = { + .tv_sec = 0, + .tv_usec = 250 * 1000, + }; + bool done_timeout_250ms = false; + + struct timeval timeout_500ms, val_500ms = { + .tv_sec = 0, + .tv_usec = 500 * 1000, + }; + bool done_timeout_500ms = false; + #endif mybit = (1 << cpuinfo.ci_cpuid); callself = func && (cpuset & mybit) != 0; cpuset &= ~mybit; + /* + * If we're cold, just (maybe) call ourselves. + */ + if (cold) { + if (callself) + (*func)(arg0, arg1, arg2); + return; + } + /* Mask any CPUs that are not ready */ cpuset &= cpu_ready_mask; *************** xcall(xcall_func_t func, xcall_trap_t tr *** 620,661 **** /* * Second, call ourselves. */ - p = &cpuinfo.msg.u.xpmsg_func; if (callself) (*func)(arg0, arg1, arg2); /* * Lastly, start looping, waiting for all CPUs to register that they * have completed (bailing if it takes "too long", being loud about * this in the process). */ ! done = is_noop; ! i = 100000; /* time-out, not too long, but still an _AGE_ */ ! while (!done) { ! if (--i < 0) { ! printf_nolog("xcall(cpu%d,%p): couldn't ping cpus:", ! cpu_number(), func); } ! done = 1; for (CPU_INFO_FOREACH(n, cpi)) { if ((cpuset & (1 << n)) == 0) continue; if (cpi->msg.complete == 0) { ! if (i < 0) { ! printf_nolog(" cpu%d", cpi->ci_cpuid); } else { ! done = 0; break; } } } } ! if (i < 0) ! printf_nolog("\n"); mutex_spin_exit(&xpmsg_mutex); } /* --- 668,762 ---- /* * Second, call ourselves. */ if (callself) (*func)(arg0, arg1, arg2); + if (is_noop) + goto out; + /* * Lastly, start looping, waiting for all CPUs to register that they * have completed (bailing if it takes "too long", being loud about * this in the process). */ ! microtime(&cur); ! timeradd(&cur, &timeout_val, &ipitimeout); ! #ifdef DIAGNOSTIC ! timeradd(&cur, &val_100ms, &timeout_100ms); ! timeradd(&cur, &val_250ms, &timeout_250ms); ! timeradd(&cur, &val_500ms, &timeout_500ms); ! #endif ! done = false; ! i = 0; ! while (!done && !timeout) { ! microtime(&cur); ! timeout = timercmp(&cur, &ipitimeout, >); ! ! if (i++ > 10000000) { ! timeout = true; ! break; } ! #ifdef DIAGNOSTIC ! if (!done_timeout_100ms && timercmp(&cur, &timeout_100ms, >)) ! done_timeout_100ms = true; ! else if (!done_timeout_250ms && timercmp(&cur, &timeout_250ms, >)) ! done_timeout_250ms = true; ! else if (!done_timeout_500ms && timercmp(&cur, &timeout_500ms, >)) ! done_timeout_500ms = true; ! #endif ! done = true; for (CPU_INFO_FOREACH(n, cpi)) { if ((cpuset & (1 << n)) == 0) continue; if (cpi->msg.complete == 0) { ! if (timeout) { ! failed_cpuset |= (1 << n); } else { ! done = false; break; } } } } ! ! #ifdef DIAGNOSTIC ! if (done_timeout_100ms) ! ipi_timeout_100ms.ev_count++; ! if (done_timeout_250ms) ! ipi_timeout_250ms.ev_count++; ! if (done_timeout_500ms) ! ipi_timeout_500ms.ev_count++; ! #endif ! ! out: mutex_spin_exit(&xpmsg_mutex); + + + if (!timeout) + return; + + /* + * Let's make this a hard panic for now, and figure out why it happens. + * We're waiting a whole second (timeout_val) so it shouldn't. + * + * We call mp_pause_cpus() so we can capture their state *now* as opposed + * to after we've written all the below to the console. + */ + #ifdef DDB + mp_pause_cpus_ddb(); + #else + mp_pause_cpus(); + #endif + printf_nolog("xcall(cpu%d,%p) from %p: couldn't ping cpus:", + cpu_number(), fasttrap ? trap : func, __builtin_return_address(0)); + for (CPU_INFO_FOREACH(n, cpi)) + if ((failed_cpuset & (1 << n)) == 0) + printf_nolog(" cpu%d", cpi->ci_cpuid); + printf_nolog("%s\n", i == 10000000 ? " [hard 10M timeout]" : ""); + panic("failed to ping cpus"); } /* *************** fsrtoname(int impl, int vers, int fver) *** 2073,2080 **** #include "ioconf.h" - void cpu_debug_dump(void); - /* * Dump CPU information from ddb. */ --- 2174,2179 ---- *************** cpu_debug_dump(void) *** 2097,2100 **** --- 2196,2230 ---- ci->curpcb); } } + + #if defined(MULTIPROCESSOR) + /* + * Dump CPU xcall from ddb. + */ + void + cpu_xcall_dump(void) + { + struct cpu_info *ci; + CPU_INFO_ITERATOR cii; + + db_printf("%-4s %-8s %-8s %-8s %-8s %-8s " + "%-4s %-4s %-4s\n", + "CPU#", "FUNC", "TRAP", "ARG0", "ARG1", "ARG2", + "TAG", "RECV", "COMPL"); + for (CPU_INFO_FOREACH(cii, ci)) { + db_printf("%-4d %-8p %-8p %#-8x %#-8x %#-8x " + "%-4d %-4d %-4d\n", + ci->ci_cpuid, + ci->msg.u.xpmsg_func.func, + ci->msg.u.xpmsg_func.trap, + ci->msg.u.xpmsg_func.arg0, + ci->msg.u.xpmsg_func.arg1, + ci->msg.u.xpmsg_func.arg2, + ci->msg.tag, + ci->msg.received, + ci->msg.complete); + } + } + #endif + #endif Index: sparc/cpuvar.h =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/cpuvar.h,v retrieving revision 1.84 diff -p -r1.84 cpuvar.h *** sparc/cpuvar.h 13 Jan 2011 05:20:27 -0000 1.84 --- sparc/cpuvar.h 26 Jan 2011 06:13:48 -0000 *************** extern u_int cpu_ready_mask; /* the set *** 492,496 **** --- 492,505 ---- #define cpuinfo (*(struct cpu_info *)CPUINFO_VA) + #if defined(DDB) + /* + * These are called by ddb mach functions. + */ + void cpu_debug_dump(void); + #if defined(MULTIPROCESSOR) + void cpu_xcall_dump(void); + #endif + #endif #endif /* _sparc_cpuvar_h */ Index: sparc/db_interface.c =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/sparc/db_interface.c,v retrieving revision 1.87 diff -p -r1.87 db_interface.c *** sparc/db_interface.c 6 Nov 2010 11:46:02 -0000 1.87 --- sparc/db_interface.c 26 Jan 2011 06:13:48 -0000 *************** void db_dump_pcb(db_expr_t, bool, db_exp *** 201,206 **** --- 201,207 ---- void db_uvmhistdump(db_expr_t, bool, db_expr_t, const char *); #ifdef MULTIPROCESSOR void db_cpu_cmd(db_expr_t, bool, db_expr_t, const char *); + void db_xcall_cmd(db_expr_t, bool, db_expr_t, const char *); #endif void db_page_cmd(db_expr_t, bool, db_expr_t, const char *); *************** db_page_cmd(db_expr_t addr, bool have_ad *** 447,453 **** } #if defined(MULTIPROCESSOR) - extern void cpu_debug_dump(void); /* XXX */ void db_cpu_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) --- 448,453 ---- *************** db_cpu_cmd(db_expr_t addr, bool have_add *** 482,487 **** --- 482,493 ---- ddb_cpuinfo = ci; } + void + db_xcall_cmd(db_expr_t addr, bool have_addr, db_expr_t count, const char *modif) + { + cpu_xcall_dump(); + } + #endif /* MULTIPROCESSOR */ const struct db_command db_machine_command_table[] = { *************** const struct db_command db_machine_comma *** 500,505 **** --- 506,513 ---- #ifdef MULTIPROCESSOR { DDB_ADD_CMD("cpu", db_cpu_cmd, 0, "switch to another cpu's registers", "cpu-no", NULL) }, + { DDB_ADD_CMD("xcall", db_xcall_cmd, 0, + "show xcall information on all cpus", NULL, NULL) }, #endif { DDB_ADD_CMD(NULL, NULL, 0, NULL,NULL,NULL) } }; Index: stand/ofwboot/srt0.s =================================================================== RCS file: /cvsroot/src/sys/arch/sparc/stand/ofwboot/srt0.s,v retrieving revision 1.6 diff -p -r1.6 srt0.s *** stand/ofwboot/srt0.s 17 Oct 2007 19:57:16 -0000 1.6 --- stand/ofwboot/srt0.s 26 Jan 2011 06:13:48 -0000 *************** _C_LABEL(itlb_va_to_pa): *** 216,221 **** --- 216,223 ---- nop /* return PA of matching entry */ ldxa [%o1] ASI_IMMU_TLB_DATA, %o0 + /* USIII erratum #19, USIII+/USIIIi erratum #1 */ + ldxa [%o1] ASI_IMMU_TLB_DATA, %o0 sllx %o0, 23, %o0 srlx %o0, PGSHIFT+23, %o0 sllx %o0, PGSHIFT, %o0 *************** _C_LABEL(dtlb_va_to_pa): *** 249,254 **** --- 251,258 ---- nop /* return PA of matching entry */ ldxa [%o1] ASI_DMMU_TLB_DATA, %o0 + /* USIII erratum #19, USIII+/USIIIi erratum #1 */ + ldxa [%o1] ASI_DMMU_TLB_DATA, %o0 sllx %o0, 23, %o0 srlx %o0, PGSHIFT+23, %o0 sllx %o0, PGSHIFT, %o0