xref: /titanic_51/usr/src/uts/i86pc/os/machdep.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
30*7c478bd9Sstevel@tonic-gate #include <sys/t_lock.h>
31*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
32*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/signal.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/systm.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/user.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/mman.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/vm.h>
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate #include <sys/disp.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/class.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #include <sys/proc.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/buf.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
47*7c478bd9Sstevel@tonic-gate #include <sys/uadmin.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/callb.h>
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #include <sys/cred.h>
51*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #include <sys/procfs.h>
55*7c478bd9Sstevel@tonic-gate #include <sys/acct.h>
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h>
58*7c478bd9Sstevel@tonic-gate #include <sys/dnlc.h>
59*7c478bd9Sstevel@tonic-gate #include <sys/var.h>
60*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
61*7c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
62*7c478bd9Sstevel@tonic-gate #include <sys/debug.h>
63*7c478bd9Sstevel@tonic-gate #include <sys/kdi_impl.h>
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #include <sys/dumphdr.h>
66*7c478bd9Sstevel@tonic-gate #include <sys/bootconf.h>
67*7c478bd9Sstevel@tonic-gate #include <sys/varargs.h>
68*7c478bd9Sstevel@tonic-gate #include <sys/promif.h>
69*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate #include <sys/consdev.h>
72*7c478bd9Sstevel@tonic-gate #include <sys/frame.h>
73*7c478bd9Sstevel@tonic-gate 
74*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
75*7c478bd9Sstevel@tonic-gate #include <sys/ddidmareq.h>
76*7c478bd9Sstevel@tonic-gate #include <sys/psw.h>
77*7c478bd9Sstevel@tonic-gate #include <sys/regset.h>
78*7c478bd9Sstevel@tonic-gate #include <sys/privregs.h>
79*7c478bd9Sstevel@tonic-gate #include <sys/clock.h>
80*7c478bd9Sstevel@tonic-gate #include <sys/tss.h>
81*7c478bd9Sstevel@tonic-gate #include <sys/cpu.h>
82*7c478bd9Sstevel@tonic-gate #include <sys/stack.h>
83*7c478bd9Sstevel@tonic-gate #include <sys/trap.h>
84*7c478bd9Sstevel@tonic-gate #include <sys/pic.h>
85*7c478bd9Sstevel@tonic-gate #include <sys/mmu.h>
86*7c478bd9Sstevel@tonic-gate #include <vm/hat.h>
87*7c478bd9Sstevel@tonic-gate #include <vm/anon.h>
88*7c478bd9Sstevel@tonic-gate #include <vm/as.h>
89*7c478bd9Sstevel@tonic-gate #include <vm/page.h>
90*7c478bd9Sstevel@tonic-gate #include <vm/seg.h>
91*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h>
92*7c478bd9Sstevel@tonic-gate #include <vm/seg_map.h>
93*7c478bd9Sstevel@tonic-gate #include <vm/seg_vn.h>
94*7c478bd9Sstevel@tonic-gate #include <vm/seg_kp.h>
95*7c478bd9Sstevel@tonic-gate #include <vm/hat_i86.h>
96*7c478bd9Sstevel@tonic-gate #include <sys/swap.h>
97*7c478bd9Sstevel@tonic-gate #include <sys/thread.h>
98*7c478bd9Sstevel@tonic-gate #include <sys/sysconf.h>
99*7c478bd9Sstevel@tonic-gate #include <sys/vm_machparam.h>
100*7c478bd9Sstevel@tonic-gate #include <sys/archsystm.h>
101*7c478bd9Sstevel@tonic-gate #include <sys/machsystm.h>
102*7c478bd9Sstevel@tonic-gate #include <sys/machlock.h>
103*7c478bd9Sstevel@tonic-gate #include <sys/x_call.h>
104*7c478bd9Sstevel@tonic-gate #include <sys/instance.h>
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
107*7c478bd9Sstevel@tonic-gate #include <sys/smp_impldefs.h>
108*7c478bd9Sstevel@tonic-gate #include <sys/psm_types.h>
109*7c478bd9Sstevel@tonic-gate #include <sys/atomic.h>
110*7c478bd9Sstevel@tonic-gate #include <sys/panic.h>
111*7c478bd9Sstevel@tonic-gate #include <sys/cpuvar.h>
112*7c478bd9Sstevel@tonic-gate #include <sys/dtrace.h>
113*7c478bd9Sstevel@tonic-gate #include <sys/bl.h>
114*7c478bd9Sstevel@tonic-gate #include <sys/nvpair.h>
115*7c478bd9Sstevel@tonic-gate #include <sys/x86_archext.h>
116*7c478bd9Sstevel@tonic-gate #include <sys/pool_pset.h>
117*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
118*7c478bd9Sstevel@tonic-gate #include <sys/kdi.h>
119*7c478bd9Sstevel@tonic-gate 
120*7c478bd9Sstevel@tonic-gate #ifdef	TRAPTRACE
121*7c478bd9Sstevel@tonic-gate #include <sys/traptrace.h>
122*7c478bd9Sstevel@tonic-gate #endif	/* TRAPTRACE */
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT
125*7c478bd9Sstevel@tonic-gate extern void audit_enterprom(int);
126*7c478bd9Sstevel@tonic-gate extern void audit_exitprom(int);
127*7c478bd9Sstevel@tonic-gate #endif
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate /*
130*7c478bd9Sstevel@tonic-gate  * The panicbuf array is used to record messages and state:
131*7c478bd9Sstevel@tonic-gate  */
132*7c478bd9Sstevel@tonic-gate char panicbuf[PANICBUFSIZE];
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate /*
135*7c478bd9Sstevel@tonic-gate  * maxphys - used during physio
136*7c478bd9Sstevel@tonic-gate  * klustsize - used for klustering by swapfs and specfs
137*7c478bd9Sstevel@tonic-gate  */
138*7c478bd9Sstevel@tonic-gate int maxphys = 56 * 1024;    /* XXX See vm_subr.c - max b_count in physio */
139*7c478bd9Sstevel@tonic-gate int klustsize = 56 * 1024;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate caddr_t	p0_va;		/* Virtual address for accessing physical page 0 */
142*7c478bd9Sstevel@tonic-gate int	pokefault = 0;
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate /*
145*7c478bd9Sstevel@tonic-gate  * defined here, though unused on x86,
146*7c478bd9Sstevel@tonic-gate  * to make kstat_fr.c happy.
147*7c478bd9Sstevel@tonic-gate  */
148*7c478bd9Sstevel@tonic-gate int vac;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate void stop_other_cpus();
151*7c478bd9Sstevel@tonic-gate void debug_enter(char *);
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate int	procset = 1;
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate /*
156*7c478bd9Sstevel@tonic-gate  * Flags set by mdboot if we're panicking and we invoke mdboot on a CPU which
157*7c478bd9Sstevel@tonic-gate  * is not the boot CPU.  When set, panic_idle() on the boot CPU will invoke
158*7c478bd9Sstevel@tonic-gate  * mdboot with the corresponding arguments.
159*7c478bd9Sstevel@tonic-gate  */
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate #define	BOOT_WAIT	-1		/* Flag indicating we should idle */
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate volatile int cpu_boot_cmd = BOOT_WAIT;
164*7c478bd9Sstevel@tonic-gate volatile int cpu_boot_fcn = BOOT_WAIT;
165*7c478bd9Sstevel@tonic-gate 
166*7c478bd9Sstevel@tonic-gate extern void pm_cfb_check_and_powerup(void);
167*7c478bd9Sstevel@tonic-gate extern void pm_cfb_rele(void);
168*7c478bd9Sstevel@tonic-gate 
169*7c478bd9Sstevel@tonic-gate /*
170*7c478bd9Sstevel@tonic-gate  * Machine dependent code to reboot.
171*7c478bd9Sstevel@tonic-gate  * "mdep" is interpreted as a character pointer; if non-null, it is a pointer
172*7c478bd9Sstevel@tonic-gate  * to a string to be used as the argument string when rebooting.
173*7c478bd9Sstevel@tonic-gate  */
174*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
175*7c478bd9Sstevel@tonic-gate void
176*7c478bd9Sstevel@tonic-gate mdboot(int cmd, int fcn, char *mdep)
177*7c478bd9Sstevel@tonic-gate {
178*7c478bd9Sstevel@tonic-gate 	extern void mtrr_resync(void);
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 	/*
181*7c478bd9Sstevel@tonic-gate 	 * The PSMI guarantees the implementor of psm_shutdown that it will
182*7c478bd9Sstevel@tonic-gate 	 * only be called on the boot CPU.  This was needed by Corollary
183*7c478bd9Sstevel@tonic-gate 	 * because the hardware does not allow other CPUs to reset the
184*7c478bd9Sstevel@tonic-gate 	 * boot CPU.  So before rebooting, we switch over to the boot CPU.
185*7c478bd9Sstevel@tonic-gate 	 * If we are panicking, the other CPUs are at high spl spinning in
186*7c478bd9Sstevel@tonic-gate 	 * panic_idle(), so we set the cpu_boot_* variables and wait for
187*7c478bd9Sstevel@tonic-gate 	 * the boot CPU to re-invoke mdboot() for us.
188*7c478bd9Sstevel@tonic-gate 	 */
189*7c478bd9Sstevel@tonic-gate 	if (!panicstr) {
190*7c478bd9Sstevel@tonic-gate 		kpreempt_disable();
191*7c478bd9Sstevel@tonic-gate 		affinity_set(getbootcpuid());
192*7c478bd9Sstevel@tonic-gate 	} else if (CPU->cpu_id != getbootcpuid()) {
193*7c478bd9Sstevel@tonic-gate 		cpu_boot_cmd = cmd;
194*7c478bd9Sstevel@tonic-gate 		cpu_boot_fcn = fcn;
195*7c478bd9Sstevel@tonic-gate 		for (;;);
196*7c478bd9Sstevel@tonic-gate 	}
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 	/*
199*7c478bd9Sstevel@tonic-gate 	 * XXX - rconsvp is set to NULL to ensure that output messages
200*7c478bd9Sstevel@tonic-gate 	 * are sent to the underlying "hardware" device using the
201*7c478bd9Sstevel@tonic-gate 	 * monitor's printf routine since we are in the process of
202*7c478bd9Sstevel@tonic-gate 	 * either rebooting or halting the machine.
203*7c478bd9Sstevel@tonic-gate 	 */
204*7c478bd9Sstevel@tonic-gate 	rconsvp = NULL;
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	/*
207*7c478bd9Sstevel@tonic-gate 	 * Print the reboot message now, before pausing other cpus.
208*7c478bd9Sstevel@tonic-gate 	 * There is a race condition in the printing support that
209*7c478bd9Sstevel@tonic-gate 	 * can deadlock multiprocessor machines.
210*7c478bd9Sstevel@tonic-gate 	 */
211*7c478bd9Sstevel@tonic-gate 	if (!(fcn == AD_HALT || fcn == AD_POWEROFF))
212*7c478bd9Sstevel@tonic-gate 		prom_printf("rebooting...\n");
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 	/*
215*7c478bd9Sstevel@tonic-gate 	 * We can't bring up the console from above lock level, so do it now
216*7c478bd9Sstevel@tonic-gate 	 */
217*7c478bd9Sstevel@tonic-gate 	pm_cfb_check_and_powerup();
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	/* make sure there are no more changes to the device tree */
220*7c478bd9Sstevel@tonic-gate 	devtree_freeze();
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 	/*
223*7c478bd9Sstevel@tonic-gate 	 * stop other cpus and raise our priority.  since there is only
224*7c478bd9Sstevel@tonic-gate 	 * one active cpu after this, and our priority will be too high
225*7c478bd9Sstevel@tonic-gate 	 * for us to be preempted, we're essentially single threaded
226*7c478bd9Sstevel@tonic-gate 	 * from here on out.
227*7c478bd9Sstevel@tonic-gate 	 */
228*7c478bd9Sstevel@tonic-gate 	(void) spl6();
229*7c478bd9Sstevel@tonic-gate 	if (!panicstr) {
230*7c478bd9Sstevel@tonic-gate 		mutex_enter(&cpu_lock);
231*7c478bd9Sstevel@tonic-gate 		pause_cpus(NULL);
232*7c478bd9Sstevel@tonic-gate 		mutex_exit(&cpu_lock);
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	/*
236*7c478bd9Sstevel@tonic-gate 	 * try and reset leaf devices.  reset_leaves() should only
237*7c478bd9Sstevel@tonic-gate 	 * be called when there are no other threads that could be
238*7c478bd9Sstevel@tonic-gate 	 * accessing devices
239*7c478bd9Sstevel@tonic-gate 	 */
240*7c478bd9Sstevel@tonic-gate 	reset_leaves();
241*7c478bd9Sstevel@tonic-gate 
242*7c478bd9Sstevel@tonic-gate 	(void) spl8();
243*7c478bd9Sstevel@tonic-gate 	(*psm_shutdownf)(cmd, fcn);
244*7c478bd9Sstevel@tonic-gate 
245*7c478bd9Sstevel@tonic-gate 	mtrr_resync();
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 	if (fcn == AD_HALT || fcn == AD_POWEROFF)
248*7c478bd9Sstevel@tonic-gate 		halt((char *)NULL);
249*7c478bd9Sstevel@tonic-gate 	else
250*7c478bd9Sstevel@tonic-gate 		prom_reboot("");
251*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate /* mdpreboot - may be called prior to mdboot while root fs still mounted */
255*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
256*7c478bd9Sstevel@tonic-gate void
257*7c478bd9Sstevel@tonic-gate mdpreboot(int cmd, int fcn, char *mdep)
258*7c478bd9Sstevel@tonic-gate {
259*7c478bd9Sstevel@tonic-gate 	(*psm_preshutdownf)(cmd, fcn);
260*7c478bd9Sstevel@tonic-gate }
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate void
263*7c478bd9Sstevel@tonic-gate idle_other_cpus()
264*7c478bd9Sstevel@tonic-gate {
265*7c478bd9Sstevel@tonic-gate 	int cpuid = CPU->cpu_id;
266*7c478bd9Sstevel@tonic-gate 	cpuset_t xcset;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid < NCPU);
269*7c478bd9Sstevel@tonic-gate 	CPUSET_ALL_BUT(xcset, cpuid);
270*7c478bd9Sstevel@tonic-gate 	xc_capture_cpus(xcset);
271*7c478bd9Sstevel@tonic-gate }
272*7c478bd9Sstevel@tonic-gate 
273*7c478bd9Sstevel@tonic-gate void
274*7c478bd9Sstevel@tonic-gate resume_other_cpus()
275*7c478bd9Sstevel@tonic-gate {
276*7c478bd9Sstevel@tonic-gate 	ASSERT(CPU->cpu_id < NCPU);
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	xc_release_cpus();
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate extern void	mp_halt(char *);
282*7c478bd9Sstevel@tonic-gate 
283*7c478bd9Sstevel@tonic-gate void
284*7c478bd9Sstevel@tonic-gate stop_other_cpus()
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate 	int cpuid = CPU->cpu_id;
287*7c478bd9Sstevel@tonic-gate 	cpuset_t xcset;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	ASSERT(cpuid < NCPU);
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	/*
292*7c478bd9Sstevel@tonic-gate 	 * xc_trycall will attempt to make all other CPUs execute mp_halt,
293*7c478bd9Sstevel@tonic-gate 	 * and will return immediately regardless of whether or not it was
294*7c478bd9Sstevel@tonic-gate 	 * able to make them do it.
295*7c478bd9Sstevel@tonic-gate 	 */
296*7c478bd9Sstevel@tonic-gate 	CPUSET_ALL_BUT(xcset, cpuid);
297*7c478bd9Sstevel@tonic-gate 	xc_trycall(NULL, NULL, NULL, xcset, (int (*)())mp_halt);
298*7c478bd9Sstevel@tonic-gate }
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate /*
301*7c478bd9Sstevel@tonic-gate  *	Machine dependent abort sequence handling
302*7c478bd9Sstevel@tonic-gate  */
303*7c478bd9Sstevel@tonic-gate void
304*7c478bd9Sstevel@tonic-gate abort_sequence_enter(char *msg)
305*7c478bd9Sstevel@tonic-gate {
306*7c478bd9Sstevel@tonic-gate 	if (abort_enable == 0) {
307*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT
308*7c478bd9Sstevel@tonic-gate 		if (audit_active)
309*7c478bd9Sstevel@tonic-gate 			audit_enterprom(0);
310*7c478bd9Sstevel@tonic-gate #endif /* C2_AUDIT */
311*7c478bd9Sstevel@tonic-gate 		return;
312*7c478bd9Sstevel@tonic-gate 	}
313*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT
314*7c478bd9Sstevel@tonic-gate 	if (audit_active)
315*7c478bd9Sstevel@tonic-gate 		audit_enterprom(1);
316*7c478bd9Sstevel@tonic-gate #endif /* C2_AUDIT */
317*7c478bd9Sstevel@tonic-gate 	debug_enter(msg);
318*7c478bd9Sstevel@tonic-gate #ifdef C2_AUDIT
319*7c478bd9Sstevel@tonic-gate 	if (audit_active)
320*7c478bd9Sstevel@tonic-gate 		audit_exitprom(1);
321*7c478bd9Sstevel@tonic-gate #endif /* C2_AUDIT */
322*7c478bd9Sstevel@tonic-gate }
323*7c478bd9Sstevel@tonic-gate 
324*7c478bd9Sstevel@tonic-gate /*
325*7c478bd9Sstevel@tonic-gate  * Enter debugger.  Called when the user types ctrl-alt-d or whenever
326*7c478bd9Sstevel@tonic-gate  * code wants to enter the debugger and possibly resume later.
327*7c478bd9Sstevel@tonic-gate  */
328*7c478bd9Sstevel@tonic-gate void
329*7c478bd9Sstevel@tonic-gate debug_enter(
330*7c478bd9Sstevel@tonic-gate 	char	*msg)		/* message to print, possibly NULL */
331*7c478bd9Sstevel@tonic-gate {
332*7c478bd9Sstevel@tonic-gate 	if (dtrace_debugger_init != NULL)
333*7c478bd9Sstevel@tonic-gate 		(*dtrace_debugger_init)();
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	if (msg)
336*7c478bd9Sstevel@tonic-gate 		prom_printf("%s\n", msg);
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 	if (boothowto & RB_DEBUG)
339*7c478bd9Sstevel@tonic-gate 		kdi_dvec_enter();
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate 	if (dtrace_debugger_fini != NULL)
342*7c478bd9Sstevel@tonic-gate 		(*dtrace_debugger_fini)();
343*7c478bd9Sstevel@tonic-gate }
344*7c478bd9Sstevel@tonic-gate 
345*7c478bd9Sstevel@tonic-gate void
346*7c478bd9Sstevel@tonic-gate reset(void)
347*7c478bd9Sstevel@tonic-gate {
348*7c478bd9Sstevel@tonic-gate 	ushort_t *bios_memchk;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	/*
351*7c478bd9Sstevel@tonic-gate 	 * Can't use psm_map_phys before the hat is initialized.
352*7c478bd9Sstevel@tonic-gate 	 */
353*7c478bd9Sstevel@tonic-gate 	if (khat_running) {
354*7c478bd9Sstevel@tonic-gate 		bios_memchk = (ushort_t *)psm_map_phys(0x472,
355*7c478bd9Sstevel@tonic-gate 		    sizeof (ushort_t), PROT_READ | PROT_WRITE);
356*7c478bd9Sstevel@tonic-gate 		if (bios_memchk)
357*7c478bd9Sstevel@tonic-gate 			*bios_memchk = 0x1234;	/* bios memory check disable */
358*7c478bd9Sstevel@tonic-gate 	}
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	pc_reset();
361*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
362*7c478bd9Sstevel@tonic-gate }
363*7c478bd9Sstevel@tonic-gate 
364*7c478bd9Sstevel@tonic-gate /*
365*7c478bd9Sstevel@tonic-gate  * Halt the machine and return to the monitor
366*7c478bd9Sstevel@tonic-gate  */
367*7c478bd9Sstevel@tonic-gate void
368*7c478bd9Sstevel@tonic-gate halt(char *s)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate 	stop_other_cpus();	/* send stop signal to other CPUs */
371*7c478bd9Sstevel@tonic-gate 	if (s)
372*7c478bd9Sstevel@tonic-gate 		prom_printf("(%s) \n", s);
373*7c478bd9Sstevel@tonic-gate 	prom_exit_to_mon();
374*7c478bd9Sstevel@tonic-gate 	/*NOTREACHED*/
375*7c478bd9Sstevel@tonic-gate }
376*7c478bd9Sstevel@tonic-gate 
377*7c478bd9Sstevel@tonic-gate /*
378*7c478bd9Sstevel@tonic-gate  * Enter monitor.  Called via cross-call from stop_other_cpus().
379*7c478bd9Sstevel@tonic-gate  */
380*7c478bd9Sstevel@tonic-gate void
381*7c478bd9Sstevel@tonic-gate mp_halt(char *msg)
382*7c478bd9Sstevel@tonic-gate {
383*7c478bd9Sstevel@tonic-gate 	if (msg)
384*7c478bd9Sstevel@tonic-gate 		prom_printf("%s\n", msg);
385*7c478bd9Sstevel@tonic-gate 
386*7c478bd9Sstevel@tonic-gate 	/*CONSTANTCONDITION*/
387*7c478bd9Sstevel@tonic-gate 	while (1)
388*7c478bd9Sstevel@tonic-gate 		;
389*7c478bd9Sstevel@tonic-gate }
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate /*
392*7c478bd9Sstevel@tonic-gate  * Initiate interrupt redistribution.
393*7c478bd9Sstevel@tonic-gate  */
394*7c478bd9Sstevel@tonic-gate void
395*7c478bd9Sstevel@tonic-gate i_ddi_intr_redist_all_cpus()
396*7c478bd9Sstevel@tonic-gate {
397*7c478bd9Sstevel@tonic-gate }
398*7c478bd9Sstevel@tonic-gate 
399*7c478bd9Sstevel@tonic-gate /*
400*7c478bd9Sstevel@tonic-gate  * XXX These probably ought to live somewhere else
401*7c478bd9Sstevel@tonic-gate  * XXX They are called from mem.c
402*7c478bd9Sstevel@tonic-gate  */
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate /*
405*7c478bd9Sstevel@tonic-gate  * Convert page frame number to an OBMEM page frame number
406*7c478bd9Sstevel@tonic-gate  * (i.e. put in the type bits -- zero for this implementation)
407*7c478bd9Sstevel@tonic-gate  */
408*7c478bd9Sstevel@tonic-gate pfn_t
409*7c478bd9Sstevel@tonic-gate impl_obmem_pfnum(pfn_t pf)
410*7c478bd9Sstevel@tonic-gate {
411*7c478bd9Sstevel@tonic-gate 	return (pf);
412*7c478bd9Sstevel@tonic-gate }
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate #ifdef	NM_DEBUG
415*7c478bd9Sstevel@tonic-gate int nmi_test = 0;	/* checked in intentry.s during clock int */
416*7c478bd9Sstevel@tonic-gate int nmtest = -1;
417*7c478bd9Sstevel@tonic-gate nmfunc1(arg, rp)
418*7c478bd9Sstevel@tonic-gate int	arg;
419*7c478bd9Sstevel@tonic-gate struct regs *rp;
420*7c478bd9Sstevel@tonic-gate {
421*7c478bd9Sstevel@tonic-gate 	printf("nmi called with arg = %x, regs = %x\n", arg, rp);
422*7c478bd9Sstevel@tonic-gate 	nmtest += 50;
423*7c478bd9Sstevel@tonic-gate 	if (arg == nmtest) {
424*7c478bd9Sstevel@tonic-gate 		printf("ip = %x\n", rp->r_pc);
425*7c478bd9Sstevel@tonic-gate 		return (1);
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 	return (0);
428*7c478bd9Sstevel@tonic-gate }
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate #endif
431*7c478bd9Sstevel@tonic-gate 
432*7c478bd9Sstevel@tonic-gate #include <sys/bootsvcs.h>
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate /* Hacked up initialization for initial kernel check out is HERE. */
435*7c478bd9Sstevel@tonic-gate /* The basic steps are: */
436*7c478bd9Sstevel@tonic-gate /*	kernel bootfuncs definition/initialization for KADB */
437*7c478bd9Sstevel@tonic-gate /*	kadb bootfuncs pointer initialization */
438*7c478bd9Sstevel@tonic-gate /*	putchar/getchar (interrupts disabled) */
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate /* kadb bootfuncs pointer initialization */
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate int
443*7c478bd9Sstevel@tonic-gate sysp_getchar()
444*7c478bd9Sstevel@tonic-gate {
445*7c478bd9Sstevel@tonic-gate 	int i;
446*7c478bd9Sstevel@tonic-gate 	int s;
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	if (cons_polledio == NULL) {
449*7c478bd9Sstevel@tonic-gate 		/* Uh oh */
450*7c478bd9Sstevel@tonic-gate 		prom_printf("getchar called with no console\n");
451*7c478bd9Sstevel@tonic-gate 		for (;;)
452*7c478bd9Sstevel@tonic-gate 			/* LOOP FOREVER */;
453*7c478bd9Sstevel@tonic-gate 	}
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate 	s = clear_int_flag();
456*7c478bd9Sstevel@tonic-gate 	i = cons_polledio->cons_polledio_getchar(
457*7c478bd9Sstevel@tonic-gate 		cons_polledio->cons_polledio_argument);
458*7c478bd9Sstevel@tonic-gate 	restore_int_flag(s);
459*7c478bd9Sstevel@tonic-gate 	return (i);
460*7c478bd9Sstevel@tonic-gate }
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate void
463*7c478bd9Sstevel@tonic-gate sysp_putchar(int c)
464*7c478bd9Sstevel@tonic-gate {
465*7c478bd9Sstevel@tonic-gate 	int s;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 	/*
468*7c478bd9Sstevel@tonic-gate 	 * We have no alternative but to drop the output on the floor.
469*7c478bd9Sstevel@tonic-gate 	 */
470*7c478bd9Sstevel@tonic-gate 	if (cons_polledio == NULL)
471*7c478bd9Sstevel@tonic-gate 		return;
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 	s = clear_int_flag();
474*7c478bd9Sstevel@tonic-gate 	cons_polledio->cons_polledio_putchar(
475*7c478bd9Sstevel@tonic-gate 		cons_polledio->cons_polledio_argument, c);
476*7c478bd9Sstevel@tonic-gate 	restore_int_flag(s);
477*7c478bd9Sstevel@tonic-gate }
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate int
480*7c478bd9Sstevel@tonic-gate sysp_ischar()
481*7c478bd9Sstevel@tonic-gate {
482*7c478bd9Sstevel@tonic-gate 	int i;
483*7c478bd9Sstevel@tonic-gate 	int s;
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	if (cons_polledio == NULL)
486*7c478bd9Sstevel@tonic-gate 		return (0);
487*7c478bd9Sstevel@tonic-gate 
488*7c478bd9Sstevel@tonic-gate 	s = clear_int_flag();
489*7c478bd9Sstevel@tonic-gate 	i = cons_polledio->cons_polledio_ischar(
490*7c478bd9Sstevel@tonic-gate 		cons_polledio->cons_polledio_argument);
491*7c478bd9Sstevel@tonic-gate 	restore_int_flag(s);
492*7c478bd9Sstevel@tonic-gate 	return (i);
493*7c478bd9Sstevel@tonic-gate }
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate int
496*7c478bd9Sstevel@tonic-gate goany(void)
497*7c478bd9Sstevel@tonic-gate {
498*7c478bd9Sstevel@tonic-gate 	prom_printf("Type any key to continue ");
499*7c478bd9Sstevel@tonic-gate 	(void) prom_getchar();
500*7c478bd9Sstevel@tonic-gate 	prom_printf("\n");
501*7c478bd9Sstevel@tonic-gate 	return (1);
502*7c478bd9Sstevel@tonic-gate }
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate static struct boot_syscalls kern_sysp = {
505*7c478bd9Sstevel@tonic-gate 	sysp_getchar,	/*	unchar	(*getchar)();	7  */
506*7c478bd9Sstevel@tonic-gate 	sysp_putchar,	/*	int	(*putchar)();	8  */
507*7c478bd9Sstevel@tonic-gate 	sysp_ischar,	/*	int	(*ischar)();	9  */
508*7c478bd9Sstevel@tonic-gate };
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate void
511*7c478bd9Sstevel@tonic-gate kadb_uses_kernel()
512*7c478bd9Sstevel@tonic-gate {
513*7c478bd9Sstevel@tonic-gate 	/*
514*7c478bd9Sstevel@tonic-gate 	 * This routine is now totally misnamed, since it does not in fact
515*7c478bd9Sstevel@tonic-gate 	 * control kadb's I/O; it only controls the kernel's prom_* I/O.
516*7c478bd9Sstevel@tonic-gate 	 */
517*7c478bd9Sstevel@tonic-gate 	sysp = &kern_sysp;
518*7c478bd9Sstevel@tonic-gate }
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate /*
521*7c478bd9Sstevel@tonic-gate  *	the interface to the outside world
522*7c478bd9Sstevel@tonic-gate  */
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate /*
525*7c478bd9Sstevel@tonic-gate  * poll_port -- wait for a register to achieve a
526*7c478bd9Sstevel@tonic-gate  *		specific state.  Arguments are a mask of bits we care about,
527*7c478bd9Sstevel@tonic-gate  *		and two sub-masks.  To return normally, all the bits in the
528*7c478bd9Sstevel@tonic-gate  *		first sub-mask must be ON, all the bits in the second sub-
529*7c478bd9Sstevel@tonic-gate  *		mask must be OFF.  If about seconds pass without the register
530*7c478bd9Sstevel@tonic-gate  *		achieving the desired bit configuration, we return 1, else
531*7c478bd9Sstevel@tonic-gate  *		0.
532*7c478bd9Sstevel@tonic-gate  */
533*7c478bd9Sstevel@tonic-gate int
534*7c478bd9Sstevel@tonic-gate poll_port(ushort_t port, ushort_t mask, ushort_t onbits, ushort_t offbits)
535*7c478bd9Sstevel@tonic-gate {
536*7c478bd9Sstevel@tonic-gate 	int i;
537*7c478bd9Sstevel@tonic-gate 	ushort_t maskval;
538*7c478bd9Sstevel@tonic-gate 
539*7c478bd9Sstevel@tonic-gate 	for (i = 500000; i; i--) {
540*7c478bd9Sstevel@tonic-gate 		maskval = inb(port) & mask;
541*7c478bd9Sstevel@tonic-gate 		if (((maskval & onbits) == onbits) &&
542*7c478bd9Sstevel@tonic-gate 			((maskval & offbits) == 0))
543*7c478bd9Sstevel@tonic-gate 			return (0);
544*7c478bd9Sstevel@tonic-gate 		drv_usecwait(10);
545*7c478bd9Sstevel@tonic-gate 	}
546*7c478bd9Sstevel@tonic-gate 	return (1);
547*7c478bd9Sstevel@tonic-gate }
548*7c478bd9Sstevel@tonic-gate 
549*7c478bd9Sstevel@tonic-gate /*
550*7c478bd9Sstevel@tonic-gate  * set_idle_cpu is called from idle() when a CPU becomes idle.
551*7c478bd9Sstevel@tonic-gate  */
552*7c478bd9Sstevel@tonic-gate /*LINTED: static unused */
553*7c478bd9Sstevel@tonic-gate static uint_t last_idle_cpu;
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
556*7c478bd9Sstevel@tonic-gate void
557*7c478bd9Sstevel@tonic-gate set_idle_cpu(int cpun)
558*7c478bd9Sstevel@tonic-gate {
559*7c478bd9Sstevel@tonic-gate 	last_idle_cpu = cpun;
560*7c478bd9Sstevel@tonic-gate 	(*psm_set_idle_cpuf)(cpun);
561*7c478bd9Sstevel@tonic-gate }
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate /*
564*7c478bd9Sstevel@tonic-gate  * unset_idle_cpu is called from idle() when a CPU is no longer idle.
565*7c478bd9Sstevel@tonic-gate  */
566*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
567*7c478bd9Sstevel@tonic-gate void
568*7c478bd9Sstevel@tonic-gate unset_idle_cpu(int cpun)
569*7c478bd9Sstevel@tonic-gate {
570*7c478bd9Sstevel@tonic-gate 	(*psm_unset_idle_cpuf)(cpun);
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate /*
574*7c478bd9Sstevel@tonic-gate  * This routine is almost correct now, but not quite.  It still needs the
575*7c478bd9Sstevel@tonic-gate  * equivalent concept of "hres_last_tick", just like on the sparc side.
576*7c478bd9Sstevel@tonic-gate  * The idea is to take a snapshot of the hi-res timer while doing the
577*7c478bd9Sstevel@tonic-gate  * hrestime_adj updates under hres_lock in locore, so that the small
578*7c478bd9Sstevel@tonic-gate  * interval between interrupt assertion and interrupt processing is
579*7c478bd9Sstevel@tonic-gate  * accounted for correctly.  Once we have this, the code below should
580*7c478bd9Sstevel@tonic-gate  * be modified to subtract off hres_last_tick rather than hrtime_base.
581*7c478bd9Sstevel@tonic-gate  *
582*7c478bd9Sstevel@tonic-gate  * I'd have done this myself, but I don't have source to all of the
583*7c478bd9Sstevel@tonic-gate  * vendor-specific hi-res timer routines (grrr...).  The generic hook I
584*7c478bd9Sstevel@tonic-gate  * need is something like "gethrtime_unlocked()", which would be just like
585*7c478bd9Sstevel@tonic-gate  * gethrtime() but would assume that you're already holding CLOCK_LOCK().
586*7c478bd9Sstevel@tonic-gate  * This is what the GET_HRTIME() macro is for on sparc (although it also
587*7c478bd9Sstevel@tonic-gate  * serves the function of making time available without a function call
588*7c478bd9Sstevel@tonic-gate  * so you don't take a register window overflow while traps are disabled).
589*7c478bd9Sstevel@tonic-gate  */
590*7c478bd9Sstevel@tonic-gate void
591*7c478bd9Sstevel@tonic-gate pc_gethrestime(timestruc_t *tp)
592*7c478bd9Sstevel@tonic-gate {
593*7c478bd9Sstevel@tonic-gate 	int lock_prev;
594*7c478bd9Sstevel@tonic-gate 	timestruc_t now;
595*7c478bd9Sstevel@tonic-gate 	int nslt;		/* nsec since last tick */
596*7c478bd9Sstevel@tonic-gate 	int adj;		/* amount of adjustment to apply */
597*7c478bd9Sstevel@tonic-gate 
598*7c478bd9Sstevel@tonic-gate loop:
599*7c478bd9Sstevel@tonic-gate 	lock_prev = hres_lock;
600*7c478bd9Sstevel@tonic-gate 	now = hrestime;
601*7c478bd9Sstevel@tonic-gate 	nslt = (int)(gethrtime() - hres_last_tick);
602*7c478bd9Sstevel@tonic-gate 	if (nslt < 0) {
603*7c478bd9Sstevel@tonic-gate 		/*
604*7c478bd9Sstevel@tonic-gate 		 * nslt < 0 means a tick came between sampling
605*7c478bd9Sstevel@tonic-gate 		 * gethrtime() and hres_last_tick; restart the loop
606*7c478bd9Sstevel@tonic-gate 		 */
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate 		goto loop;
609*7c478bd9Sstevel@tonic-gate 	}
610*7c478bd9Sstevel@tonic-gate 	now.tv_nsec += nslt;
611*7c478bd9Sstevel@tonic-gate 	if (hrestime_adj != 0) {
612*7c478bd9Sstevel@tonic-gate 		if (hrestime_adj > 0) {
613*7c478bd9Sstevel@tonic-gate 			adj = (nslt >> ADJ_SHIFT);
614*7c478bd9Sstevel@tonic-gate 			if (adj > hrestime_adj)
615*7c478bd9Sstevel@tonic-gate 				adj = (int)hrestime_adj;
616*7c478bd9Sstevel@tonic-gate 		} else {
617*7c478bd9Sstevel@tonic-gate 			adj = -(nslt >> ADJ_SHIFT);
618*7c478bd9Sstevel@tonic-gate 			if (adj < hrestime_adj)
619*7c478bd9Sstevel@tonic-gate 				adj = (int)hrestime_adj;
620*7c478bd9Sstevel@tonic-gate 		}
621*7c478bd9Sstevel@tonic-gate 		now.tv_nsec += adj;
622*7c478bd9Sstevel@tonic-gate 	}
623*7c478bd9Sstevel@tonic-gate 	while ((unsigned long)now.tv_nsec >= NANOSEC) {
624*7c478bd9Sstevel@tonic-gate 
625*7c478bd9Sstevel@tonic-gate 		/*
626*7c478bd9Sstevel@tonic-gate 		 * We might have a large adjustment or have been in the
627*7c478bd9Sstevel@tonic-gate 		 * debugger for a long time; take care of (at most) four
628*7c478bd9Sstevel@tonic-gate 		 * of those missed seconds (tv_nsec is 32 bits, so
629*7c478bd9Sstevel@tonic-gate 		 * anything >4s will be wrapping around).  However,
630*7c478bd9Sstevel@tonic-gate 		 * anything more than 2 seconds out of sync will trigger
631*7c478bd9Sstevel@tonic-gate 		 * timedelta from clock() to go correct the time anyway,
632*7c478bd9Sstevel@tonic-gate 		 * so do what we can, and let the big crowbar do the
633*7c478bd9Sstevel@tonic-gate 		 * rest.  A similar correction while loop exists inside
634*7c478bd9Sstevel@tonic-gate 		 * hres_tick(); in all cases we'd like tv_nsec to
635*7c478bd9Sstevel@tonic-gate 		 * satisfy 0 <= tv_nsec < NANOSEC to avoid confusing
636*7c478bd9Sstevel@tonic-gate 		 * user processes, but if tv_sec's a little behind for a
637*7c478bd9Sstevel@tonic-gate 		 * little while, that's OK; time still monotonically
638*7c478bd9Sstevel@tonic-gate 		 * increases.
639*7c478bd9Sstevel@tonic-gate 		 */
640*7c478bd9Sstevel@tonic-gate 
641*7c478bd9Sstevel@tonic-gate 		now.tv_nsec -= NANOSEC;
642*7c478bd9Sstevel@tonic-gate 		now.tv_sec++;
643*7c478bd9Sstevel@tonic-gate 	}
644*7c478bd9Sstevel@tonic-gate 	if ((hres_lock & ~1) != lock_prev)
645*7c478bd9Sstevel@tonic-gate 		goto loop;
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 	*tp = now;
648*7c478bd9Sstevel@tonic-gate }
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate void
651*7c478bd9Sstevel@tonic-gate gethrestime_lasttick(timespec_t *tp)
652*7c478bd9Sstevel@tonic-gate {
653*7c478bd9Sstevel@tonic-gate 	int s;
654*7c478bd9Sstevel@tonic-gate 
655*7c478bd9Sstevel@tonic-gate 	s = hr_clock_lock();
656*7c478bd9Sstevel@tonic-gate 	*tp = hrestime;
657*7c478bd9Sstevel@tonic-gate 	hr_clock_unlock(s);
658*7c478bd9Sstevel@tonic-gate }
659*7c478bd9Sstevel@tonic-gate 
660*7c478bd9Sstevel@tonic-gate time_t
661*7c478bd9Sstevel@tonic-gate gethrestime_sec(void)
662*7c478bd9Sstevel@tonic-gate {
663*7c478bd9Sstevel@tonic-gate 	timestruc_t now;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	gethrestime(&now);
666*7c478bd9Sstevel@tonic-gate 	return (now.tv_sec);
667*7c478bd9Sstevel@tonic-gate }
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate /*
670*7c478bd9Sstevel@tonic-gate  * Initialize a kernel thread's stack
671*7c478bd9Sstevel@tonic-gate  */
672*7c478bd9Sstevel@tonic-gate 
673*7c478bd9Sstevel@tonic-gate caddr_t
674*7c478bd9Sstevel@tonic-gate thread_stk_init(caddr_t stk)
675*7c478bd9Sstevel@tonic-gate {
676*7c478bd9Sstevel@tonic-gate 	ASSERT(((uintptr_t)stk & (STACK_ALIGN - 1)) == 0);
677*7c478bd9Sstevel@tonic-gate 	return (stk - SA(MINFRAME));
678*7c478bd9Sstevel@tonic-gate }
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate /*
681*7c478bd9Sstevel@tonic-gate  * Initialize lwp's kernel stack.
682*7c478bd9Sstevel@tonic-gate  */
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE
685*7c478bd9Sstevel@tonic-gate /*
686*7c478bd9Sstevel@tonic-gate  * There's a tricky interdependency here between use of sysenter and
687*7c478bd9Sstevel@tonic-gate  * TRAPTRACE which needs recording to avoid future confusion (this is
688*7c478bd9Sstevel@tonic-gate  * about the third time I've re-figured this out ..)
689*7c478bd9Sstevel@tonic-gate  *
690*7c478bd9Sstevel@tonic-gate  * Here's how debugging lcall works with TRAPTRACE.
691*7c478bd9Sstevel@tonic-gate  *
692*7c478bd9Sstevel@tonic-gate  * 1 We're in userland with a breakpoint on the lcall instruction.
693*7c478bd9Sstevel@tonic-gate  * 2 We execute the instruction - the instruction pushes the userland
694*7c478bd9Sstevel@tonic-gate  *   %ss, %esp, %efl, %cs, %eip on the stack and zips into the kernel
695*7c478bd9Sstevel@tonic-gate  *   via the call gate.
696*7c478bd9Sstevel@tonic-gate  * 3 The hardware raises a debug trap in kernel mode, the hardware
697*7c478bd9Sstevel@tonic-gate  *   pushes %efl, %cs, %eip and gets to dbgtrap via the idt.
698*7c478bd9Sstevel@tonic-gate  * 4 dbgtrap pushes the error code and trapno and calls cmntrap
699*7c478bd9Sstevel@tonic-gate  * 5 cmntrap finishes building a trap frame
700*7c478bd9Sstevel@tonic-gate  * 6 The TRACE_REGS macros in cmntrap copy a REGSIZE worth chunk
701*7c478bd9Sstevel@tonic-gate  *   off the stack into the traptrace buffer.
702*7c478bd9Sstevel@tonic-gate  *
703*7c478bd9Sstevel@tonic-gate  * This means that the traptrace buffer contains the wrong values in
704*7c478bd9Sstevel@tonic-gate  * %esp and %ss, but everything else in there is correct.
705*7c478bd9Sstevel@tonic-gate  *
706*7c478bd9Sstevel@tonic-gate  * Here's how debugging sysenter works with TRAPTRACE.
707*7c478bd9Sstevel@tonic-gate  *
708*7c478bd9Sstevel@tonic-gate  * a We're in userland with a breakpoint on the sysenter instruction.
709*7c478bd9Sstevel@tonic-gate  * b We execute the instruction - the instruction pushes -nothing-
710*7c478bd9Sstevel@tonic-gate  *   on the stack, but sets %cs, %eip, %ss, %esp to prearranged
711*7c478bd9Sstevel@tonic-gate  *   values to take us to sys_sysenter, at the top of the lwp's
712*7c478bd9Sstevel@tonic-gate  *   stack.
713*7c478bd9Sstevel@tonic-gate  * c goto 3
714*7c478bd9Sstevel@tonic-gate  *
715*7c478bd9Sstevel@tonic-gate  * At this point, because we got into the kernel without the requisite
716*7c478bd9Sstevel@tonic-gate  * five pushes on the stack, if we didn't make extra room, we'd
717*7c478bd9Sstevel@tonic-gate  * end up with the TRACE_REGS macro fetching the saved %ss and %esp
718*7c478bd9Sstevel@tonic-gate  * values from negative (unmapped) stack addresses -- which really bites.
719*7c478bd9Sstevel@tonic-gate  * That's why we do the '-= 8' below.
720*7c478bd9Sstevel@tonic-gate  *
721*7c478bd9Sstevel@tonic-gate  * XXX	Note that reading "up" lwp0's stack works because t0 is declared
722*7c478bd9Sstevel@tonic-gate  *	right next to t0stack in locore.s
723*7c478bd9Sstevel@tonic-gate  */
724*7c478bd9Sstevel@tonic-gate #endif
725*7c478bd9Sstevel@tonic-gate 
726*7c478bd9Sstevel@tonic-gate caddr_t
727*7c478bd9Sstevel@tonic-gate lwp_stk_init(klwp_t *lwp, caddr_t stk)
728*7c478bd9Sstevel@tonic-gate {
729*7c478bd9Sstevel@tonic-gate 	caddr_t oldstk;
730*7c478bd9Sstevel@tonic-gate 	struct pcb *pcb = &lwp->lwp_pcb;
731*7c478bd9Sstevel@tonic-gate 
732*7c478bd9Sstevel@tonic-gate 	oldstk = stk;
733*7c478bd9Sstevel@tonic-gate 	stk -= SA(sizeof (struct regs) + SA(MINFRAME));
734*7c478bd9Sstevel@tonic-gate #ifdef TRAPTRACE
735*7c478bd9Sstevel@tonic-gate 	stk -= 2 * sizeof (greg_t); /* space for phony %ss:%sp (see above) */
736*7c478bd9Sstevel@tonic-gate #endif
737*7c478bd9Sstevel@tonic-gate 	stk = (caddr_t)((uintptr_t)stk & ~(STACK_ALIGN - 1ul));
738*7c478bd9Sstevel@tonic-gate 	bzero(stk, oldstk - stk);
739*7c478bd9Sstevel@tonic-gate 	lwp->lwp_regs = (void *)(stk + SA(MINFRAME));
740*7c478bd9Sstevel@tonic-gate 
741*7c478bd9Sstevel@tonic-gate 	/*
742*7c478bd9Sstevel@tonic-gate 	 * Arrange that the virtualized %fs and %gs GDT descriptors
743*7c478bd9Sstevel@tonic-gate 	 * have a well-defined initial state (present, ring 3
744*7c478bd9Sstevel@tonic-gate 	 * and of type data).
745*7c478bd9Sstevel@tonic-gate 	 */
746*7c478bd9Sstevel@tonic-gate #if defined(__amd64)
747*7c478bd9Sstevel@tonic-gate 	if (lwp_getdatamodel(lwp) == DATAMODEL_NATIVE)
748*7c478bd9Sstevel@tonic-gate 		pcb->pcb_fsdesc = pcb->pcb_gsdesc = zero_udesc;
749*7c478bd9Sstevel@tonic-gate 	else
750*7c478bd9Sstevel@tonic-gate 		pcb->pcb_fsdesc = pcb->pcb_gsdesc = zero_u32desc;
751*7c478bd9Sstevel@tonic-gate #elif defined(__i386)
752*7c478bd9Sstevel@tonic-gate 	pcb->pcb_fsdesc = pcb->pcb_gsdesc = zero_udesc;
753*7c478bd9Sstevel@tonic-gate #endif	/* __i386 */
754*7c478bd9Sstevel@tonic-gate 	lwp_installctx(lwp);
755*7c478bd9Sstevel@tonic-gate 	return (stk);
756*7c478bd9Sstevel@tonic-gate }
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
759*7c478bd9Sstevel@tonic-gate void
760*7c478bd9Sstevel@tonic-gate lwp_stk_fini(klwp_t *lwp)
761*7c478bd9Sstevel@tonic-gate {}
762*7c478bd9Sstevel@tonic-gate 
763*7c478bd9Sstevel@tonic-gate /*
764*7c478bd9Sstevel@tonic-gate  * If we're not the panic CPU, we wait in panic_idle for reboot.  If we're
765*7c478bd9Sstevel@tonic-gate  * the boot CPU, then we are responsible for actually doing the reboot, so
766*7c478bd9Sstevel@tonic-gate  * we watch for cpu_boot_cmd to be set.
767*7c478bd9Sstevel@tonic-gate  */
768*7c478bd9Sstevel@tonic-gate static void
769*7c478bd9Sstevel@tonic-gate panic_idle(void)
770*7c478bd9Sstevel@tonic-gate {
771*7c478bd9Sstevel@tonic-gate 	splx(ipltospl(CLOCK_LEVEL));
772*7c478bd9Sstevel@tonic-gate 	(void) setjmp(&curthread->t_pcb);
773*7c478bd9Sstevel@tonic-gate 
774*7c478bd9Sstevel@tonic-gate 	if (CPU->cpu_id == getbootcpuid()) {
775*7c478bd9Sstevel@tonic-gate 		while (cpu_boot_cmd == BOOT_WAIT || cpu_boot_fcn == BOOT_WAIT)
776*7c478bd9Sstevel@tonic-gate 			drv_usecwait(10);
777*7c478bd9Sstevel@tonic-gate 
778*7c478bd9Sstevel@tonic-gate 		mdboot(cpu_boot_cmd, cpu_boot_fcn, NULL);
779*7c478bd9Sstevel@tonic-gate 	}
780*7c478bd9Sstevel@tonic-gate 
781*7c478bd9Sstevel@tonic-gate 	for (;;);
782*7c478bd9Sstevel@tonic-gate }
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate /*
785*7c478bd9Sstevel@tonic-gate  * Stop the other CPUs by cross-calling them and forcing them to enter
786*7c478bd9Sstevel@tonic-gate  * the panic_idle() loop above.
787*7c478bd9Sstevel@tonic-gate  */
788*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
789*7c478bd9Sstevel@tonic-gate void
790*7c478bd9Sstevel@tonic-gate panic_stopcpus(cpu_t *cp, kthread_t *t, int spl)
791*7c478bd9Sstevel@tonic-gate {
792*7c478bd9Sstevel@tonic-gate 	processorid_t i;
793*7c478bd9Sstevel@tonic-gate 	cpuset_t xcset;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 	(void) splzs();
796*7c478bd9Sstevel@tonic-gate 
797*7c478bd9Sstevel@tonic-gate 	CPUSET_ALL_BUT(xcset, cp->cpu_id);
798*7c478bd9Sstevel@tonic-gate 	xc_trycall(NULL, NULL, NULL, xcset, (int (*)())panic_idle);
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < NCPU; i++) {
801*7c478bd9Sstevel@tonic-gate 		if (i != cp->cpu_id && cpu[i] != NULL &&
802*7c478bd9Sstevel@tonic-gate 		    (cpu[i]->cpu_flags & CPU_EXISTS))
803*7c478bd9Sstevel@tonic-gate 			cpu[i]->cpu_flags |= CPU_QUIESCED;
804*7c478bd9Sstevel@tonic-gate 	}
805*7c478bd9Sstevel@tonic-gate }
806*7c478bd9Sstevel@tonic-gate 
807*7c478bd9Sstevel@tonic-gate /*
808*7c478bd9Sstevel@tonic-gate  * Platform callback following each entry to panicsys().
809*7c478bd9Sstevel@tonic-gate  */
810*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
811*7c478bd9Sstevel@tonic-gate void
812*7c478bd9Sstevel@tonic-gate panic_enter_hw(int spl)
813*7c478bd9Sstevel@tonic-gate {
814*7c478bd9Sstevel@tonic-gate 	/* Nothing to do here */
815*7c478bd9Sstevel@tonic-gate }
816*7c478bd9Sstevel@tonic-gate 
817*7c478bd9Sstevel@tonic-gate /*
818*7c478bd9Sstevel@tonic-gate  * Platform-specific code to execute after panicstr is set: we invoke
819*7c478bd9Sstevel@tonic-gate  * the PSM entry point to indicate that a panic has occurred.
820*7c478bd9Sstevel@tonic-gate  */
821*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
822*7c478bd9Sstevel@tonic-gate void
823*7c478bd9Sstevel@tonic-gate panic_quiesce_hw(panic_data_t *pdp)
824*7c478bd9Sstevel@tonic-gate {
825*7c478bd9Sstevel@tonic-gate 	psm_notifyf(PSM_PANIC_ENTER);
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate #ifdef	TRAPTRACE
828*7c478bd9Sstevel@tonic-gate 	/*
829*7c478bd9Sstevel@tonic-gate 	 * Turn off TRAPTRACE
830*7c478bd9Sstevel@tonic-gate 	 */
831*7c478bd9Sstevel@tonic-gate 	TRAPTRACE_FREEZE;
832*7c478bd9Sstevel@tonic-gate #endif	/* TRAPTRACE */
833*7c478bd9Sstevel@tonic-gate }
834*7c478bd9Sstevel@tonic-gate 
835*7c478bd9Sstevel@tonic-gate /*
836*7c478bd9Sstevel@tonic-gate  * Platform callback prior to writing crash dump.
837*7c478bd9Sstevel@tonic-gate  */
838*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
839*7c478bd9Sstevel@tonic-gate void
840*7c478bd9Sstevel@tonic-gate panic_dump_hw(int spl)
841*7c478bd9Sstevel@tonic-gate {
842*7c478bd9Sstevel@tonic-gate 	/* Nothing to do here */
843*7c478bd9Sstevel@tonic-gate }
844*7c478bd9Sstevel@tonic-gate 
845*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
846*7c478bd9Sstevel@tonic-gate void
847*7c478bd9Sstevel@tonic-gate plat_tod_fault(enum tod_fault_type tod_bad)
848*7c478bd9Sstevel@tonic-gate {
849*7c478bd9Sstevel@tonic-gate }
850*7c478bd9Sstevel@tonic-gate 
851*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
852*7c478bd9Sstevel@tonic-gate int
853*7c478bd9Sstevel@tonic-gate blacklist(int cmd, const char *scheme, nvlist_t *fmri, const char *class)
854*7c478bd9Sstevel@tonic-gate {
855*7c478bd9Sstevel@tonic-gate 	return (ENOTSUP);
856*7c478bd9Sstevel@tonic-gate }
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate /*
859*7c478bd9Sstevel@tonic-gate  * The underlying console output routines are protected by raising IPL in case
860*7c478bd9Sstevel@tonic-gate  * we are still calling into the early boot services.  Once we start calling
861*7c478bd9Sstevel@tonic-gate  * the kernel console emulator, it will disable interrupts completely during
862*7c478bd9Sstevel@tonic-gate  * character rendering (see sysp_putchar, for example).  Refer to the comments
863*7c478bd9Sstevel@tonic-gate  * and code in common/os/console.c for more information on these callbacks.
864*7c478bd9Sstevel@tonic-gate  */
865*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
866*7c478bd9Sstevel@tonic-gate int
867*7c478bd9Sstevel@tonic-gate console_enter(int busy)
868*7c478bd9Sstevel@tonic-gate {
869*7c478bd9Sstevel@tonic-gate 	return (splzs());
870*7c478bd9Sstevel@tonic-gate }
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
873*7c478bd9Sstevel@tonic-gate void
874*7c478bd9Sstevel@tonic-gate console_exit(int busy, int spl)
875*7c478bd9Sstevel@tonic-gate {
876*7c478bd9Sstevel@tonic-gate 	splx(spl);
877*7c478bd9Sstevel@tonic-gate }
878*7c478bd9Sstevel@tonic-gate 
879*7c478bd9Sstevel@tonic-gate /*
880*7c478bd9Sstevel@tonic-gate  * Allocate a region of virtual address space, unmapped.
881*7c478bd9Sstevel@tonic-gate  * Stubbed out except on sparc, at least for now.
882*7c478bd9Sstevel@tonic-gate  */
883*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/
884*7c478bd9Sstevel@tonic-gate void *
885*7c478bd9Sstevel@tonic-gate boot_virt_alloc(void *addr, size_t size)
886*7c478bd9Sstevel@tonic-gate {
887*7c478bd9Sstevel@tonic-gate 	return (addr);
888*7c478bd9Sstevel@tonic-gate }
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate volatile unsigned long	tenmicrodata;
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate void
893*7c478bd9Sstevel@tonic-gate tenmicrosec(void)
894*7c478bd9Sstevel@tonic-gate {
895*7c478bd9Sstevel@tonic-gate 	extern int	tsc_gethrtime_initted;
896*7c478bd9Sstevel@tonic-gate 	int		i;
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate 	if (tsc_gethrtime_initted) {
899*7c478bd9Sstevel@tonic-gate 		hrtime_t start, end;
900*7c478bd9Sstevel@tonic-gate 		start = end =  gethrtime();
901*7c478bd9Sstevel@tonic-gate 		while ((end - start) < (10 * (NANOSEC / MICROSEC))) {
902*7c478bd9Sstevel@tonic-gate 			SMT_PAUSE();
903*7c478bd9Sstevel@tonic-gate 			end = gethrtime();
904*7c478bd9Sstevel@tonic-gate 		}
905*7c478bd9Sstevel@tonic-gate 	} else {
906*7c478bd9Sstevel@tonic-gate 		/*
907*7c478bd9Sstevel@tonic-gate 		 * Artificial loop to induce delay.
908*7c478bd9Sstevel@tonic-gate 		 */
909*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < microdata; i++)
910*7c478bd9Sstevel@tonic-gate 			tenmicrodata = microdata;
911*7c478bd9Sstevel@tonic-gate 	}
912*7c478bd9Sstevel@tonic-gate }
913