xref: /onnv-gate/usr/src/cmd/mdb/common/kmdb/kaif_start.c (revision 3446:5903aece022d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52011Shyw  * Common Development and Distribution License (the "License").
62011Shyw  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3446Smrj  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * The main CPU-control loops, used to control masters and slaves.
300Sstevel@tonic-gate  */
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate 
340Sstevel@tonic-gate #include <kmdb/kaif.h>
350Sstevel@tonic-gate #include <kmdb/kaif_start.h>
360Sstevel@tonic-gate #include <kmdb/kmdb_asmutil.h>
370Sstevel@tonic-gate #include <kmdb/kmdb_dpi_impl.h>
380Sstevel@tonic-gate #include <kmdb/kmdb_kdi.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #define	KAIF_SLAVE_CMD_SPIN	0
410Sstevel@tonic-gate #define	KAIF_SLAVE_CMD_SWITCH	1
420Sstevel@tonic-gate #define	KAIF_SLAVE_CMD_RESUME	2
430Sstevel@tonic-gate #define	KAIF_SLAVE_CMD_FLUSH	3
440Sstevel@tonic-gate #define	KAIF_SLAVE_CMD_REBOOT	4
452011Shyw #if defined(__sparc)
462011Shyw #define	KAIF_SLAVE_CMD_ACK	5
472011Shyw #endif
482011Shyw 
490Sstevel@tonic-gate 
500Sstevel@tonic-gate /*
510Sstevel@tonic-gate  * Used to synchronize attempts to set kaif_master_cpuid.  kaif_master_cpuid may
520Sstevel@tonic-gate  * be read without kaif_master_lock, and may be written by the current master
530Sstevel@tonic-gate  * CPU.
540Sstevel@tonic-gate  */
550Sstevel@tonic-gate int kaif_master_cpuid = KAIF_MASTER_CPUID_UNSET;
560Sstevel@tonic-gate static uintptr_t kaif_master_lock = 0;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /*
590Sstevel@tonic-gate  * Used to ensure that all CPUs leave the debugger together. kaif_loop_lock must
600Sstevel@tonic-gate  * be held to write kaif_looping, but need not be held to read it.
610Sstevel@tonic-gate  */
620Sstevel@tonic-gate static volatile uint_t kaif_looping;
630Sstevel@tonic-gate static uintptr_t kaif_loop_lock;
640Sstevel@tonic-gate 
650Sstevel@tonic-gate static volatile int kaif_slave_cmd;
660Sstevel@tonic-gate static volatile int kaif_slave_tgt;	/* target cpuid for CMD_SWITCH */
670Sstevel@tonic-gate 
680Sstevel@tonic-gate static void
kaif_lock_enter(uintptr_t * lock)690Sstevel@tonic-gate kaif_lock_enter(uintptr_t *lock)
700Sstevel@tonic-gate {
710Sstevel@tonic-gate 	while (cas(lock, 0, 1) != 0)
720Sstevel@tonic-gate 		continue;
730Sstevel@tonic-gate 	membar_producer();
740Sstevel@tonic-gate }
750Sstevel@tonic-gate 
760Sstevel@tonic-gate static void
kaif_lock_exit(uintptr_t * lock)770Sstevel@tonic-gate kaif_lock_exit(uintptr_t *lock)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	*lock = 0;
800Sstevel@tonic-gate 	membar_producer();
810Sstevel@tonic-gate }
820Sstevel@tonic-gate 
83*3446Smrj static void
kaif_start_slaves(int cmd)84*3446Smrj kaif_start_slaves(int cmd)
85*3446Smrj {
86*3446Smrj 	kaif_slave_cmd = cmd;
87*3446Smrj 	kmdb_kdi_start_slaves();
88*3446Smrj }
89*3446Smrj 
900Sstevel@tonic-gate static int
kaif_master_loop(kaif_cpusave_t * cpusave)910Sstevel@tonic-gate kaif_master_loop(kaif_cpusave_t *cpusave)
920Sstevel@tonic-gate {
930Sstevel@tonic-gate 	int notflushed, i;
940Sstevel@tonic-gate 
950Sstevel@tonic-gate #if defined(__sparc)
960Sstevel@tonic-gate 	kaif_prom_rearm();
970Sstevel@tonic-gate #endif
980Sstevel@tonic-gate 	kaif_trap_set_debugger();
990Sstevel@tonic-gate 
100*3446Smrj 	/*
101*3446Smrj 	 * If we re-entered due to a ::switch, we need to tell the slave CPUs
102*3446Smrj 	 * to sleep again.
103*3446Smrj 	 */
104*3446Smrj 	kmdb_kdi_stop_slaves(cpusave->krs_cpu_id, 0);
105*3446Smrj 
1060Sstevel@tonic-gate master_loop:
1070Sstevel@tonic-gate 	switch (kmdb_dpi_reenter()) {
1080Sstevel@tonic-gate 	case KMDB_DPI_CMD_SWITCH_CPU:
1090Sstevel@tonic-gate 		/*
1100Sstevel@tonic-gate 		 * We assume that the target CPU is a valid slave.  There's no
1110Sstevel@tonic-gate 		 * easy way to complain here, so we'll assume that the caller
1120Sstevel@tonic-gate 		 * has done the proper checking.
1130Sstevel@tonic-gate 		 */
1140Sstevel@tonic-gate 		if (kmdb_dpi_switch_target == cpusave->krs_cpu_id)
1150Sstevel@tonic-gate 			break;
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 		kaif_slave_tgt = kaif_master_cpuid = kmdb_dpi_switch_target;
1180Sstevel@tonic-gate 		cpusave->krs_cpu_state = KAIF_CPU_STATE_SLAVE;
1190Sstevel@tonic-gate 		membar_producer();
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 		/*
1220Sstevel@tonic-gate 		 * Switch back to the saved trap table before we switch CPUs --
1230Sstevel@tonic-gate 		 * we need to make sure that only one CPU is on the debugger's
1240Sstevel@tonic-gate 		 * table at a time.
1250Sstevel@tonic-gate 		 */
1260Sstevel@tonic-gate 		kaif_trap_set_saved(cpusave);
1270Sstevel@tonic-gate 
128*3446Smrj 		kaif_start_slaves(KAIF_SLAVE_CMD_SWITCH);
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 		/* The new master is now awake */
1310Sstevel@tonic-gate 		return (KAIF_CPU_CMD_SWITCH);
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate 	case KMDB_DPI_CMD_RESUME_ALL:
1340Sstevel@tonic-gate 	case KMDB_DPI_CMD_RESUME_UNLOAD:
1350Sstevel@tonic-gate 		/*
1360Sstevel@tonic-gate 		 * Resume everyone, clean up for next entry.
1370Sstevel@tonic-gate 		 */
1380Sstevel@tonic-gate 		kaif_master_cpuid = KAIF_MASTER_CPUID_UNSET;
1390Sstevel@tonic-gate 		membar_producer();
140*3446Smrj 		kaif_start_slaves(KAIF_SLAVE_CMD_RESUME);
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 		if (kmdb_dpi_work_required())
1430Sstevel@tonic-gate 			kmdb_dpi_wrintr_fire();
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 		kaif_trap_set_saved(cpusave);
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 		return (KAIF_CPU_CMD_RESUME);
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	case KMDB_DPI_CMD_RESUME_MASTER:
1500Sstevel@tonic-gate 		/*
1510Sstevel@tonic-gate 		 * Single-CPU resume, which is performed on the debugger's
1520Sstevel@tonic-gate 		 * trap table (so no need to switch back).
1530Sstevel@tonic-gate 		 */
1540Sstevel@tonic-gate 		return (KAIF_CPU_CMD_RESUME_MASTER);
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	case KMDB_DPI_CMD_FLUSH_CACHES:
157*3446Smrj 		kaif_start_slaves(KAIF_SLAVE_CMD_FLUSH);
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 		/*
1600Sstevel@tonic-gate 		 * Wait for the other cpus to finish flushing their caches.
1610Sstevel@tonic-gate 		 */
1620Sstevel@tonic-gate 		do {
1630Sstevel@tonic-gate 			notflushed = 0;
1640Sstevel@tonic-gate 			for (i = 0; i < kaif_ncpusave; i++) {
1650Sstevel@tonic-gate 				kaif_cpusave_t *save = &kaif_cpusave[i];
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate 				if (save->krs_cpu_state ==
1680Sstevel@tonic-gate 				    KAIF_CPU_STATE_SLAVE &&
1690Sstevel@tonic-gate 				    !save->krs_cpu_flushed) {
1700Sstevel@tonic-gate 					notflushed++;
1710Sstevel@tonic-gate 					break;
1720Sstevel@tonic-gate 				}
1730Sstevel@tonic-gate 			}
1740Sstevel@tonic-gate 		} while (notflushed > 0);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 		kaif_slave_cmd = KAIF_SLAVE_CMD_SPIN;
1770Sstevel@tonic-gate 		break;
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
1800Sstevel@tonic-gate 	case KMDB_DPI_CMD_REBOOT:
1810Sstevel@tonic-gate 		/*
1820Sstevel@tonic-gate 		 * Reboot must be initiated by CPU 0.  I could ask why, but I'm
1830Sstevel@tonic-gate 		 * afraid that I don't want to know the answer.
1840Sstevel@tonic-gate 		 */
1850Sstevel@tonic-gate 		if (cpusave->krs_cpu_id == 0)
186*3446Smrj 			kmdb_kdi_reboot();
1870Sstevel@tonic-gate 
188*3446Smrj 		kaif_start_slaves(KAIF_SLAVE_CMD_REBOOT);
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 		/*
1910Sstevel@tonic-gate 		 * Spin forever, waiting for CPU 0 (apparently a slave) to
1920Sstevel@tonic-gate 		 * reboot the system.
1930Sstevel@tonic-gate 		 */
1940Sstevel@tonic-gate 		for (;;)
1950Sstevel@tonic-gate 			continue;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 		/*NOTREACHED*/
1980Sstevel@tonic-gate 		break;
1990Sstevel@tonic-gate #endif
2000Sstevel@tonic-gate 	}
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate 	goto master_loop;
2030Sstevel@tonic-gate }
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate static int
kaif_slave_loop(kaif_cpusave_t * cpusave)2060Sstevel@tonic-gate kaif_slave_loop(kaif_cpusave_t *cpusave)
2070Sstevel@tonic-gate {
2080Sstevel@tonic-gate 	int slavecmd, rv;
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate #if defined(__sparc)
2110Sstevel@tonic-gate 	/*
2120Sstevel@tonic-gate 	 * If the user elects to drop to OBP from the debugger, some OBP
2130Sstevel@tonic-gate 	 * implementations will cross-call the slaves.  We have to turn
2140Sstevel@tonic-gate 	 * IE back on so we can receive the cross-calls.  If we don't,
2150Sstevel@tonic-gate 	 * some OBP implementations will wait forever.
2160Sstevel@tonic-gate 	 */
2170Sstevel@tonic-gate 	interrupts_on();
2180Sstevel@tonic-gate #endif
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	/* Wait for duty to call */
2210Sstevel@tonic-gate 	for (;;) {
2220Sstevel@tonic-gate 		slavecmd = kaif_slave_cmd;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 		if (slavecmd == KAIF_SLAVE_CMD_SWITCH &&
2250Sstevel@tonic-gate 		    kaif_slave_tgt == cpusave->krs_cpu_id) {
2260Sstevel@tonic-gate 			kaif_slave_cmd = KAIF_SLAVE_CMD_SPIN;
2270Sstevel@tonic-gate 			cpusave->krs_cpu_state = KAIF_CPU_STATE_MASTER;
2280Sstevel@tonic-gate 			rv = KAIF_CPU_CMD_SWITCH;
2290Sstevel@tonic-gate 			break;
2300Sstevel@tonic-gate 
2310Sstevel@tonic-gate 		} else if (slavecmd == KAIF_SLAVE_CMD_FLUSH) {
2320Sstevel@tonic-gate 			kmdb_kdi_flush_caches();
2330Sstevel@tonic-gate 			cpusave->krs_cpu_flushed = 1;
2340Sstevel@tonic-gate 			continue;
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate #if defined(__i386) || defined(__amd64)
2370Sstevel@tonic-gate 		} else if (slavecmd == KAIF_SLAVE_CMD_REBOOT &&
2380Sstevel@tonic-gate 		    cpusave->krs_cpu_id == 0) {
239*3446Smrj 			rv = 0;
240*3446Smrj 			kmdb_kdi_reboot();
2410Sstevel@tonic-gate 			break;
2420Sstevel@tonic-gate #endif
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 		} else if (slavecmd == KAIF_SLAVE_CMD_RESUME) {
2450Sstevel@tonic-gate 			rv = KAIF_CPU_CMD_RESUME;
2460Sstevel@tonic-gate 			break;
2472011Shyw #if defined(__sparc)
2482011Shyw 		} else if (slavecmd == KAIF_SLAVE_CMD_ACK) {
2492011Shyw 			cpusave->krs_cpu_acked = 1;
2502011Shyw 		} else if (cpusave->krs_cpu_acked &&
2512011Shyw 			slavecmd == KAIF_SLAVE_CMD_SPIN) {
2522011Shyw 			cpusave->krs_cpu_acked = 0;
2532011Shyw #endif
2540Sstevel@tonic-gate 		}
255*3446Smrj 
256*3446Smrj 		kmdb_kdi_slave_wait();
2570Sstevel@tonic-gate 	}
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate #if defined(__sparc)
2600Sstevel@tonic-gate 	interrupts_off();
2610Sstevel@tonic-gate #endif
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	return (rv);
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate static void
kaif_select_master(kaif_cpusave_t * cpusave)2670Sstevel@tonic-gate kaif_select_master(kaif_cpusave_t *cpusave)
2680Sstevel@tonic-gate {
2690Sstevel@tonic-gate 	kaif_lock_enter(&kaif_master_lock);
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 	if (kaif_master_cpuid == KAIF_MASTER_CPUID_UNSET) {
2720Sstevel@tonic-gate 		/* This is the master. */
2730Sstevel@tonic-gate 		kaif_master_cpuid = cpusave->krs_cpu_id;
2740Sstevel@tonic-gate 		cpusave->krs_cpu_state = KAIF_CPU_STATE_MASTER;
2750Sstevel@tonic-gate 		kaif_slave_cmd = KAIF_SLAVE_CMD_SPIN;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 		membar_producer();
2780Sstevel@tonic-gate 
279*3446Smrj 		kmdb_kdi_stop_slaves(cpusave->krs_cpu_id, 1);
2800Sstevel@tonic-gate 	} else {
2810Sstevel@tonic-gate 		/* The master was already chosen - go be a slave */
2820Sstevel@tonic-gate 		cpusave->krs_cpu_state = KAIF_CPU_STATE_SLAVE;
2830Sstevel@tonic-gate 		membar_producer();
2840Sstevel@tonic-gate 	}
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	kaif_lock_exit(&kaif_master_lock);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate int
kaif_main_loop(kaif_cpusave_t * cpusave)2900Sstevel@tonic-gate kaif_main_loop(kaif_cpusave_t *cpusave)
2910Sstevel@tonic-gate {
2920Sstevel@tonic-gate 	int cmd;
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 	if (kaif_master_cpuid == KAIF_MASTER_CPUID_UNSET) {
2950Sstevel@tonic-gate 		if (!kmdb_dpi_resume_requested &&
2960Sstevel@tonic-gate 		    kmdb_kdi_get_unload_request()) {
2970Sstevel@tonic-gate 			/*
2980Sstevel@tonic-gate 			 * Special case: Unload requested before first debugger
2990Sstevel@tonic-gate 			 * entry.  Don't stop the world, as there's nothing to
3000Sstevel@tonic-gate 			 * clean up that can't be handled by the running kernel.
3010Sstevel@tonic-gate 			 */
3020Sstevel@tonic-gate 			cpusave->krs_cpu_state = KAIF_CPU_STATE_NONE;
3030Sstevel@tonic-gate 			return (KAIF_CPU_CMD_RESUME);
3040Sstevel@tonic-gate 		}
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate 		kaif_select_master(cpusave);
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate #ifdef __sparc
3090Sstevel@tonic-gate 		if (kaif_master_cpuid == cpusave->krs_cpu_id) {
3100Sstevel@tonic-gate 			/*
3110Sstevel@tonic-gate 			 * Everyone has arrived, so we can disarm the post-PROM
3120Sstevel@tonic-gate 			 * entry point.
3130Sstevel@tonic-gate 			 */
3140Sstevel@tonic-gate 			*kaif_promexitarmp = 0;
3150Sstevel@tonic-gate 			membar_producer();
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate #endif
3180Sstevel@tonic-gate 	} else if (kaif_master_cpuid == cpusave->krs_cpu_id) {
3190Sstevel@tonic-gate 		cpusave->krs_cpu_state = KAIF_CPU_STATE_MASTER;
3200Sstevel@tonic-gate 	} else {
3210Sstevel@tonic-gate 		cpusave->krs_cpu_state = KAIF_CPU_STATE_SLAVE;
3220Sstevel@tonic-gate 	}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	cpusave->krs_cpu_flushed = 0;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	kaif_lock_enter(&kaif_loop_lock);
3270Sstevel@tonic-gate 	kaif_looping++;
3280Sstevel@tonic-gate 	kaif_lock_exit(&kaif_loop_lock);
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	/*
3310Sstevel@tonic-gate 	 * We know who the master and slaves are, so now they can go off
3320Sstevel@tonic-gate 	 * to their respective loops.
3330Sstevel@tonic-gate 	 */
3340Sstevel@tonic-gate 	do {
3350Sstevel@tonic-gate 		if (kaif_master_cpuid == cpusave->krs_cpu_id)
3360Sstevel@tonic-gate 			cmd = kaif_master_loop(cpusave);
3370Sstevel@tonic-gate 		else
3380Sstevel@tonic-gate 			cmd = kaif_slave_loop(cpusave);
3390Sstevel@tonic-gate 	} while (cmd == KAIF_CPU_CMD_SWITCH);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	kaif_lock_enter(&kaif_loop_lock);
3420Sstevel@tonic-gate 	kaif_looping--;
3430Sstevel@tonic-gate 	kaif_lock_exit(&kaif_loop_lock);
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	cpusave->krs_cpu_state = KAIF_CPU_STATE_NONE;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	if (cmd == KAIF_CPU_CMD_RESUME) {
3480Sstevel@tonic-gate 		/*
3490Sstevel@tonic-gate 		 * By this point, the master has directed the slaves to resume,
3500Sstevel@tonic-gate 		 * and everyone is making their way to this point.  We're going
3510Sstevel@tonic-gate 		 * to block here until all CPUs leave the master and slave
3520Sstevel@tonic-gate 		 * loops.  When all have arrived, we'll turn them all loose.
3530Sstevel@tonic-gate 		 * This barrier is required for two reasons:
3540Sstevel@tonic-gate 		 *
3550Sstevel@tonic-gate 		 * 1. There exists a race condition whereby a CPU could reenter
3560Sstevel@tonic-gate 		 *    the debugger while another CPU is still in the slave loop
3570Sstevel@tonic-gate 		 *    from this debugger entry.  This usually happens when the
3580Sstevel@tonic-gate 		 *    current master releases the slaves, and makes it back to
3590Sstevel@tonic-gate 		 *    the world before the slaves notice the release.  The
3600Sstevel@tonic-gate 		 *    former master then triggers a debugger entry, and attempts
3610Sstevel@tonic-gate 		 *    to stop the slaves for this entry before they've even
3620Sstevel@tonic-gate 		 *    resumed from the last one.  When the slaves arrive here,
3630Sstevel@tonic-gate 		 *    they'll have re-disabled interrupts, and will thus ignore
3640Sstevel@tonic-gate 		 *    cross-calls until they finish resuming.
3650Sstevel@tonic-gate 		 *
3660Sstevel@tonic-gate 		 * 2. At the time of this writing, there exists a SPARC bug that
3670Sstevel@tonic-gate 		 *    causes an apparently unsolicited interrupt vector trap
3680Sstevel@tonic-gate 		 *    from OBP to one of the slaves.  This wouldn't normally be
3690Sstevel@tonic-gate 		 *    a problem but for the fact that the cross-called CPU
3700Sstevel@tonic-gate 		 *    encounters some sort of failure while in OBP.  OBP
3710Sstevel@tonic-gate 		 *    recovers by executing the debugger-hook word, which sends
3720Sstevel@tonic-gate 		 *    the slave back into the debugger, triggering a debugger
3730Sstevel@tonic-gate 		 *    fault.  This problem seems to only happen during resume,
3740Sstevel@tonic-gate 		 *    the result being that all CPUs save for the cross-called
3750Sstevel@tonic-gate 		 *    one make it back into the world, while the cross-called
3760Sstevel@tonic-gate 		 *    one is stuck at the debugger fault prompt.  Leave the
3770Sstevel@tonic-gate 		 *    world in that state too long, and you'll get a mondo
3780Sstevel@tonic-gate 		 *    timeout panic.  If we hold everyone here, we can give the
3790Sstevel@tonic-gate 		 *    the user a chance to trigger a panic for further analysis.
3800Sstevel@tonic-gate 		 *    To trigger the bug, "pool_unlock:b :c" and "while : ; do
3810Sstevel@tonic-gate 		 *    psrset -p ; done".
3820Sstevel@tonic-gate 		 *
3830Sstevel@tonic-gate 		 * When the second item is fixed, the barrier can move into
3840Sstevel@tonic-gate 		 * kaif_select_master(), immediately prior to the setting of
3850Sstevel@tonic-gate 		 * kaif_master_cpuid.
3860Sstevel@tonic-gate 		 */
3870Sstevel@tonic-gate 		while (kaif_looping != 0)
3880Sstevel@tonic-gate 			continue;
3890Sstevel@tonic-gate 	}
3900Sstevel@tonic-gate 
3910Sstevel@tonic-gate 	return (cmd);
3920Sstevel@tonic-gate }
3932011Shyw 
3942011Shyw 
3952011Shyw #if defined(__sparc)
3962011Shyw 
3972011Shyw static int slave_loop_barrier_failures = 0;	/* for debug */
3982011Shyw 
3992011Shyw /*
4002011Shyw  * There exist a race condition observed by some
4012011Shyw  * platforms where the kmdb master cpu exits to OBP via
4022011Shyw  * prom_enter_mon (e.g. "$q" command) and then later re-enter
4032011Shyw  * kmdb (typing "go") while the slaves are still proceeding
4042011Shyw  * from the OBP idle-loop back to the kmdb slave loop. The
4052011Shyw  * problem arises when the master cpu now back in kmdb proceed
4062011Shyw  * to re-enter OBP (e.g. doing a prom_read() from the kmdb main
4072011Shyw  * loop) while the slaves are still trying to get out of (the
4082011Shyw  * previous trip in) OBP into the safety of the kmdb slave loop.
4092011Shyw  * This routine forces the slaves to explicitly acknowledge
4102011Shyw  * that they are back in the slave loop. The master cpu can
4112011Shyw  * call this routine to ensure that all slave cpus are back
4122011Shyw  * in the slave loop before proceeding.
4132011Shyw  */
4142011Shyw void
kaif_slave_loop_barrier(void)4152011Shyw kaif_slave_loop_barrier(void)
4162011Shyw {
4172011Shyw 	extern void kdi_usecwait(clock_t);
4182011Shyw 	int i;
4192011Shyw 	int not_acked;
4202011Shyw 	int timeout_count = 0;
4212011Shyw 
422*3446Smrj 	kaif_start_slaves(KAIF_SLAVE_CMD_ACK);
4232011Shyw 
4242011Shyw 	/*
4252011Shyw 	 * Wait for slave cpus to explicitly acknowledge
4262011Shyw 	 * that they are spinning in the slave loop.
4272011Shyw 	 */
4282011Shyw 	do {
4292011Shyw 		not_acked = 0;
4302011Shyw 		for (i = 0; i < kaif_ncpusave; i++) {
4312011Shyw 			kaif_cpusave_t *save = &kaif_cpusave[i];
4322011Shyw 
4332011Shyw 			if (save->krs_cpu_state ==
4342011Shyw 			    KAIF_CPU_STATE_SLAVE &&
4352011Shyw 			    !save->krs_cpu_acked) {
4362011Shyw 				not_acked++;
4372011Shyw 				break;
4382011Shyw 			}
4392011Shyw 		}
4402011Shyw 
4412011Shyw 		if (not_acked == 0)
4422011Shyw 			break;
4432011Shyw 
4442011Shyw 		/*
4452011Shyw 		 * Play it safe and do a timeout delay.
4462011Shyw 		 * We will do at most kaif_ncpusave delays before
4472011Shyw 		 * bailing out of this barrier.
4482011Shyw 		 */
4492011Shyw 		kdi_usecwait(200);
4502011Shyw 
4512011Shyw 	} while (++timeout_count < kaif_ncpusave);
4522011Shyw 
4532011Shyw 	if (not_acked > 0)
4542011Shyw 		/*
4552011Shyw 		 * we cannot establish a barrier with all
4562011Shyw 		 * the slave cpus coming back from OBP
4572011Shyw 		 * Record this fact for future debugging
4582011Shyw 		 */
4592011Shyw 		slave_loop_barrier_failures++;
4602011Shyw 
4612011Shyw 	kaif_slave_cmd = KAIF_SLAVE_CMD_SPIN;
4622011Shyw }
4632011Shyw #endif
464