xref: /onnv-gate/usr/src/uts/i86pc/os/cpr_impl.c (revision 5295:a21f2449e5f9)
1*5295Srandyf /*
2*5295Srandyf  * CDDL HEADER START
3*5295Srandyf  *
4*5295Srandyf  * The contents of this file are subject to the terms of the
5*5295Srandyf  * Common Development and Distribution License (the "License").
6*5295Srandyf  * You may not use this file except in compliance with the License.
7*5295Srandyf  *
8*5295Srandyf  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5295Srandyf  * or http://www.opensolaris.org/os/licensing.
10*5295Srandyf  * See the License for the specific language governing permissions
11*5295Srandyf  * and limitations under the License.
12*5295Srandyf  *
13*5295Srandyf  * When distributing Covered Code, include this CDDL HEADER in each
14*5295Srandyf  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5295Srandyf  * If applicable, add the following below this CDDL HEADER, with the
16*5295Srandyf  * fields enclosed by brackets "[]" replaced with your own identifying
17*5295Srandyf  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5295Srandyf  *
19*5295Srandyf  * CDDL HEADER END
20*5295Srandyf  */
21*5295Srandyf /*
22*5295Srandyf  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5295Srandyf  * Use is subject to license terms.
24*5295Srandyf  */
25*5295Srandyf 
26*5295Srandyf #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5295Srandyf 
28*5295Srandyf /*
29*5295Srandyf  * Platform specific implementation code
30*5295Srandyf  * Currently only suspend to RAM is supported (ACPI S3)
31*5295Srandyf  */
32*5295Srandyf 
33*5295Srandyf #define	SUNDDI_IMPL
34*5295Srandyf 
35*5295Srandyf #include <sys/types.h>
36*5295Srandyf #include <sys/promif.h>
37*5295Srandyf #include <sys/prom_isa.h>
38*5295Srandyf #include <sys/prom_plat.h>
39*5295Srandyf #include <sys/cpuvar.h>
40*5295Srandyf #include <sys/pte.h>
41*5295Srandyf #include <vm/hat.h>
42*5295Srandyf #include <vm/page.h>
43*5295Srandyf #include <vm/as.h>
44*5295Srandyf #include <sys/cpr.h>
45*5295Srandyf #include <sys/kmem.h>
46*5295Srandyf #include <sys/clock.h>
47*5295Srandyf #include <sys/kmem.h>
48*5295Srandyf #include <sys/panic.h>
49*5295Srandyf #include <vm/seg_kmem.h>
50*5295Srandyf #include <sys/cpu_module.h>
51*5295Srandyf #include <sys/callb.h>
52*5295Srandyf #include <sys/machsystm.h>
53*5295Srandyf #include <sys/vmsystm.h>
54*5295Srandyf #include <sys/systm.h>
55*5295Srandyf #include <sys/archsystm.h>
56*5295Srandyf #include <sys/stack.h>
57*5295Srandyf #include <sys/fs/ufs_fs.h>
58*5295Srandyf #include <sys/memlist.h>
59*5295Srandyf #include <sys/bootconf.h>
60*5295Srandyf #include <sys/thread.h>
61*5295Srandyf #include <sys/x_call.h>
62*5295Srandyf #include <sys/smp_impldefs.h>
63*5295Srandyf #include <vm/vm_dep.h>
64*5295Srandyf #include <sys/psm.h>
65*5295Srandyf #include <sys/epm.h>
66*5295Srandyf #include <sys/cpr_wakecode.h>
67*5295Srandyf #include <sys/x86_archext.h>
68*5295Srandyf #include <sys/reboot.h>
69*5295Srandyf #include <sys/acpi/acpi.h>
70*5295Srandyf #include <sys/acpica.h>
71*5295Srandyf 
72*5295Srandyf #define	AFMT	"%lx"
73*5295Srandyf 
74*5295Srandyf extern int	flushes_require_xcalls;
75*5295Srandyf extern cpuset_t	cpu_ready_set;
76*5295Srandyf 
77*5295Srandyf #if defined(__amd64)
78*5295Srandyf extern void	*wc_long_mode_64(void);
79*5295Srandyf #endif	/* __amd64 */
80*5295Srandyf extern int	tsc_gethrtime_enable;
81*5295Srandyf extern	void	i_cpr_start_cpu(void);
82*5295Srandyf 
83*5295Srandyf ushort_t	cpr_mach_type = CPR_MACHTYPE_X86;
84*5295Srandyf void		(*cpr_start_cpu_func)(void) = i_cpr_start_cpu;
85*5295Srandyf 
86*5295Srandyf static wc_cpu_t	*wc_other_cpus = NULL;
87*5295Srandyf static cpuset_t procset = 1;
88*5295Srandyf 
89*5295Srandyf static void
90*5295Srandyf init_real_mode_platter(int cpun, uint32_t offset, uint_t cr4, wc_desctbr_t gdt);
91*5295Srandyf 
92*5295Srandyf static int i_cpr_platform_alloc(psm_state_request_t *req);
93*5295Srandyf static void i_cpr_platform_free(psm_state_request_t *req);
94*5295Srandyf static int i_cpr_save_apic(psm_state_request_t *req);
95*5295Srandyf static int i_cpr_restore_apic(psm_state_request_t *req);
96*5295Srandyf 
97*5295Srandyf #if defined(__amd64)
98*5295Srandyf static void restore_stack(wc_cpu_t *cpup);
99*5295Srandyf static void save_stack(wc_cpu_t *cpup);
100*5295Srandyf void (*save_stack_func)(wc_cpu_t *) = save_stack;
101*5295Srandyf #endif	/* __amd64 */
102*5295Srandyf 
103*5295Srandyf /*
104*5295Srandyf  * restart paused slave cpus
105*5295Srandyf  */
106*5295Srandyf void
107*5295Srandyf i_cpr_machdep_setup(void)
108*5295Srandyf {
109*5295Srandyf 	if (ncpus > 1) {
110*5295Srandyf 		CPR_DEBUG(CPR_DEBUG1, ("MP restarted...\n"));
111*5295Srandyf 		mutex_enter(&cpu_lock);
112*5295Srandyf 		start_cpus();
113*5295Srandyf 		mutex_exit(&cpu_lock);
114*5295Srandyf 	}
115*5295Srandyf }
116*5295Srandyf 
117*5295Srandyf 
118*5295Srandyf /*
119*5295Srandyf  * Stop all interrupt activities in the system
120*5295Srandyf  */
121*5295Srandyf void
122*5295Srandyf i_cpr_stop_intr(void)
123*5295Srandyf {
124*5295Srandyf 	(void) spl7();
125*5295Srandyf }
126*5295Srandyf 
127*5295Srandyf /*
128*5295Srandyf  * Set machine up to take interrupts
129*5295Srandyf  */
130*5295Srandyf void
131*5295Srandyf i_cpr_enable_intr(void)
132*5295Srandyf {
133*5295Srandyf 	(void) spl0();
134*5295Srandyf }
135*5295Srandyf 
136*5295Srandyf /*
137*5295Srandyf  * Save miscellaneous information which needs to be written to the
138*5295Srandyf  * state file.  This information is required to re-initialize
139*5295Srandyf  * kernel/prom handshaking.
140*5295Srandyf  */
141*5295Srandyf void
142*5295Srandyf i_cpr_save_machdep_info(void)
143*5295Srandyf {
144*5295Srandyf 	int notcalled = 0;
145*5295Srandyf 	ASSERT(notcalled);
146*5295Srandyf }
147*5295Srandyf 
148*5295Srandyf 
149*5295Srandyf void
150*5295Srandyf i_cpr_set_tbr(void)
151*5295Srandyf {
152*5295Srandyf }
153*5295Srandyf 
154*5295Srandyf 
155*5295Srandyf processorid_t
156*5295Srandyf i_cpr_bootcpuid(void)
157*5295Srandyf {
158*5295Srandyf 	return (0);
159*5295Srandyf }
160*5295Srandyf 
161*5295Srandyf /*
162*5295Srandyf  * cpu0 should contain bootcpu info
163*5295Srandyf  */
164*5295Srandyf cpu_t *
165*5295Srandyf i_cpr_bootcpu(void)
166*5295Srandyf {
167*5295Srandyf 	ASSERT(MUTEX_HELD(&cpu_lock));
168*5295Srandyf 
169*5295Srandyf 	return (cpu_get(i_cpr_bootcpuid()));
170*5295Srandyf }
171*5295Srandyf 
172*5295Srandyf /*
173*5295Srandyf  *	Save context for the specified CPU
174*5295Srandyf  */
175*5295Srandyf void *
176*5295Srandyf i_cpr_save_context(void *arg)
177*5295Srandyf {
178*5295Srandyf 	long	index = (long)arg;
179*5295Srandyf 	psm_state_request_t *papic_state;
180*5295Srandyf 	int resuming;
181*5295Srandyf 	int	ret;
182*5295Srandyf 
183*5295Srandyf 	PMD(PMD_SX, ("i_cpr_save_context() index = %ld\n", index))
184*5295Srandyf 
185*5295Srandyf 	ASSERT(index < NCPU);
186*5295Srandyf 
187*5295Srandyf 	papic_state = &(wc_other_cpus + index)->wc_apic_state;
188*5295Srandyf 
189*5295Srandyf 	ret = i_cpr_platform_alloc(papic_state);
190*5295Srandyf 	ASSERT(ret == 0);
191*5295Srandyf 
192*5295Srandyf 	ret = i_cpr_save_apic(papic_state);
193*5295Srandyf 	ASSERT(ret == 0);
194*5295Srandyf 
195*5295Srandyf 	/*
196*5295Srandyf 	 * wc_save_context returns twice, once when susending and
197*5295Srandyf 	 * once when resuming,  wc_save_context() returns 0 when
198*5295Srandyf 	 * suspending and non-zero upon resume
199*5295Srandyf 	 */
200*5295Srandyf 	resuming = (wc_save_context(wc_other_cpus + index) == 0);
201*5295Srandyf 
202*5295Srandyf 	PMD(PMD_SX, ("i_cpr_save_context: wc_save_context returns %d\n",
203*5295Srandyf 	    resuming))
204*5295Srandyf 
205*5295Srandyf 	/*
206*5295Srandyf 	 * do NOT call any functions after this point, because doing so
207*5295Srandyf 	 * will modify the stack that we are running on
208*5295Srandyf 	 */
209*5295Srandyf 
210*5295Srandyf 	if (resuming) {
211*5295Srandyf 
212*5295Srandyf 		ret = i_cpr_restore_apic(papic_state);
213*5295Srandyf 		ASSERT(ret == 0);
214*5295Srandyf 
215*5295Srandyf 		i_cpr_platform_free(papic_state);
216*5295Srandyf 
217*5295Srandyf 		/*
218*5295Srandyf 		 * Setting the bit in cpu_ready_set must be the last operation
219*5295Srandyf 		 * in processor initialization; the boot CPU will continue to
220*5295Srandyf 		 * boot once it sees this bit set for all active CPUs.
221*5295Srandyf 		 */
222*5295Srandyf 		CPUSET_ATOMIC_ADD(cpu_ready_set, CPU->cpu_id);
223*5295Srandyf 
224*5295Srandyf 		PMD(PMD_SX,
225*5295Srandyf 		    ("cpu_release() cpu_ready_set = %lx, CPU->cpu_id = %d\n",
226*5295Srandyf 		    cpu_ready_set, CPU->cpu_id))
227*5295Srandyf 	}
228*5295Srandyf 	return (NULL);
229*5295Srandyf }
230*5295Srandyf 
231*5295Srandyf static ushort_t *warm_reset_vector = NULL;
232*5295Srandyf 
233*5295Srandyf static ushort_t *
234*5295Srandyf map_warm_reset_vector()
235*5295Srandyf {
236*5295Srandyf 	/*LINTED*/
237*5295Srandyf 	if (!(warm_reset_vector = (ushort_t *)psm_map_phys(WARM_RESET_VECTOR,
238*5295Srandyf 	    sizeof (ushort_t *), PROT_READ|PROT_WRITE)))
239*5295Srandyf 		return (NULL);
240*5295Srandyf 
241*5295Srandyf 	/*
242*5295Srandyf 	 * setup secondary cpu bios boot up vector
243*5295Srandyf 	 */
244*5295Srandyf 	*warm_reset_vector = (ushort_t)((caddr_t)
245*5295Srandyf 	    /*LINTED*/
246*5295Srandyf 	    ((struct rm_platter *)rm_platter_va)->rm_code - rm_platter_va
247*5295Srandyf 	    + ((ulong_t)rm_platter_va & 0xf));
248*5295Srandyf 	warm_reset_vector++;
249*5295Srandyf 	*warm_reset_vector = (ushort_t)(rm_platter_pa >> 4);
250*5295Srandyf 
251*5295Srandyf 	--warm_reset_vector;
252*5295Srandyf 	return (warm_reset_vector);
253*5295Srandyf }
254*5295Srandyf 
255*5295Srandyf void
256*5295Srandyf i_cpr_pre_resume_cpus()
257*5295Srandyf {
258*5295Srandyf 	/*
259*5295Srandyf 	 * this is a cut down version of start_other_cpus()
260*5295Srandyf 	 * just do the initialization to wake the other cpus
261*5295Srandyf 	 */
262*5295Srandyf 	unsigned who;
263*5295Srandyf 	int cpuid = i_cpr_bootcpuid();
264*5295Srandyf 	int started_cpu;
265*5295Srandyf 	uint32_t		code_length = 0;
266*5295Srandyf 	caddr_t			wakevirt = rm_platter_va;
267*5295Srandyf 	/*LINTED*/
268*5295Srandyf 	wakecode_t		*wp = (wakecode_t *)wakevirt;
269*5295Srandyf 	char *str = "i_cpr_pre_resume_cpus";
270*5295Srandyf 	extern int get_tsc_ready();
271*5295Srandyf 	int err;
272*5295Srandyf 
273*5295Srandyf 	/*LINTED*/
274*5295Srandyf 	rm_platter_t *real_mode_platter = (rm_platter_t *)rm_platter_va;
275*5295Srandyf 
276*5295Srandyf 	/*
277*5295Srandyf 	 * Copy the real mode code at "real_mode_start" to the
278*5295Srandyf 	 * page at rm_platter_va.
279*5295Srandyf 	 */
280*5295Srandyf 	warm_reset_vector = map_warm_reset_vector();
281*5295Srandyf 	if (warm_reset_vector == NULL) {
282*5295Srandyf 		PMD(PMD_SX, ("i_cpr_pre_resume_cpus() returning #2\n"))
283*5295Srandyf 		return;
284*5295Srandyf 	}
285*5295Srandyf 
286*5295Srandyf 	flushes_require_xcalls = 1;
287*5295Srandyf 
288*5295Srandyf 	/*
289*5295Srandyf 	 * We lock our affinity to the master CPU to ensure that all slave CPUs
290*5295Srandyf 	 * do their TSC syncs with the same CPU.
291*5295Srandyf 	 */
292*5295Srandyf 
293*5295Srandyf 	affinity_set(CPU_CURRENT);
294*5295Srandyf 
295*5295Srandyf 	cpu_ready_set = 0;
296*5295Srandyf 
297*5295Srandyf 	for (who = 0; who < ncpus; who++) {
298*5295Srandyf 
299*5295Srandyf 		wc_cpu_t	*cpup = wc_other_cpus + who;
300*5295Srandyf 		wc_desctbr_t	gdt;
301*5295Srandyf 
302*5295Srandyf 		if (who == cpuid)
303*5295Srandyf 			continue;
304*5295Srandyf 
305*5295Srandyf 		if (!CPU_IN_SET(mp_cpus, who))
306*5295Srandyf 			continue;
307*5295Srandyf 
308*5295Srandyf 		PMD(PMD_SX, ("%s() waking up %d cpu\n", str, who))
309*5295Srandyf 
310*5295Srandyf 		bcopy(cpup, &(wp->wc_cpu), sizeof (wc_cpu_t));
311*5295Srandyf 
312*5295Srandyf 		gdt.base = cpup->wc_gdt_base;
313*5295Srandyf 		gdt.limit = cpup->wc_gdt_limit;
314*5295Srandyf 
315*5295Srandyf #if defined(__amd64)
316*5295Srandyf 		code_length = (uint32_t)wc_long_mode_64 - (uint32_t)wc_rm_start;
317*5295Srandyf #else
318*5295Srandyf 		code_length = 0;
319*5295Srandyf #endif
320*5295Srandyf 
321*5295Srandyf 		init_real_mode_platter(who, code_length, cpup->wc_cr4, gdt);
322*5295Srandyf 
323*5295Srandyf 		started_cpu = 1;
324*5295Srandyf 
325*5295Srandyf 		if ((err = mach_cpuid_start(who, rm_platter_va)) != 0) {
326*5295Srandyf 			cmn_err(CE_WARN, "cpu%d: failed to start during "
327*5295Srandyf 			    "suspend/resume error %d", who, err);
328*5295Srandyf 			continue;
329*5295Srandyf 		}
330*5295Srandyf 
331*5295Srandyf 		PMD(PMD_SX, ("%s() #1 waiting for procset 0x%lx\n", str,
332*5295Srandyf 		    (ulong_t)procset))
333*5295Srandyf 
334*5295Srandyf /*
335*5295Srandyf  * This conditional compile only affects the MP case.
336*5295Srandyf  */
337*5295Srandyf #ifdef	MP_PM
338*5295Srandyf 		for (delays = 0; !CPU_IN_SET(procset, who); delays++) {
339*5295Srandyf 			if (delays == 500) {
340*5295Srandyf 				/*
341*5295Srandyf 				 * After five seconds, things are probably
342*5295Srandyf 				 * looking a bit bleak - explain the hang.
343*5295Srandyf 				 */
344*5295Srandyf 				cmn_err(CE_NOTE, "cpu%d: started, "
345*5295Srandyf 				    "but not running in the kernel yet", who);
346*5295Srandyf 				PMD(PMD_SX, ("%s() %d cpu started "
347*5295Srandyf 				    "but not running in the kernel yet\n",
348*5295Srandyf 				    str, who))
349*5295Srandyf 			} else if (delays > 2000) {
350*5295Srandyf 				/*
351*5295Srandyf 				 * We waited at least 20 seconds, bail ..
352*5295Srandyf 				 */
353*5295Srandyf 				cmn_err(CE_WARN, "cpu%d: timed out", who);
354*5295Srandyf 				PMD(PMD_SX, ("%s() %d cpu timed out\n",
355*5295Srandyf 				    str, who))
356*5295Srandyf 				started_cpu = 0;
357*5295Srandyf 			}
358*5295Srandyf 
359*5295Srandyf 			/*
360*5295Srandyf 			 * wait at least 10ms, then check again..
361*5295Srandyf 			 */
362*5295Srandyf 			delay(USEC_TO_TICK_ROUNDUP(10000));
363*5295Srandyf 		}
364*5295Srandyf #else
365*5295Srandyf 		while (!CPU_IN_SET(procset, who)) {
366*5295Srandyf 			;
367*5295Srandyf 		}
368*5295Srandyf 
369*5295Srandyf #endif	/*	MP_PM	*/
370*5295Srandyf 
371*5295Srandyf 		PMD(PMD_SX, ("%s() %d cpu started\n", str, who))
372*5295Srandyf 
373*5295Srandyf 		if (!started_cpu)
374*5295Srandyf 			continue;
375*5295Srandyf 
376*5295Srandyf 		PMD(PMD_SX, ("%s() tsc_ready = %d\n", str,
377*5295Srandyf 		    get_tsc_ready()))
378*5295Srandyf 
379*5295Srandyf 		if (tsc_gethrtime_enable) {
380*5295Srandyf 			PMD(PMD_SX, ("%s() calling tsc_sync_master\n", str))
381*5295Srandyf 			tsc_sync_master(who);
382*5295Srandyf 		}
383*5295Srandyf 
384*5295Srandyf 
385*5295Srandyf 		PMD(PMD_SX, ("%s() waiting for cpu_ready_set %ld\n", str,
386*5295Srandyf 		    cpu_ready_set))
387*5295Srandyf 		/*
388*5295Srandyf 		 * Wait for cpu to declare that it is ready, we want the
389*5295Srandyf 		 * cpus to start serially instead of in parallel, so that
390*5295Srandyf 		 * they do not contend with each other in wc_rm_start()
391*5295Srandyf 		 */
392*5295Srandyf 		while (!CPU_IN_SET(cpu_ready_set, who)) {
393*5295Srandyf 			PMD(PMD_SX, ("%s() waiting for "
394*5295Srandyf 			    "cpu_ready_set %ld\n", str, cpu_ready_set))
395*5295Srandyf 			;
396*5295Srandyf 		}
397*5295Srandyf 
398*5295Srandyf 		/*
399*5295Srandyf 		 * do not need to re-initialize dtrace using dtrace_cpu_init
400*5295Srandyf 		 * function
401*5295Srandyf 		 */
402*5295Srandyf 		PMD(PMD_SX, ("%s() cpu %d now ready\n", str, who))
403*5295Srandyf 	}
404*5295Srandyf 
405*5295Srandyf 	affinity_clear();
406*5295Srandyf 
407*5295Srandyf 	PMD(PMD_SX, ("%s() all cpus now ready\n", str))
408*5295Srandyf }
409*5295Srandyf 
410*5295Srandyf static void
411*5295Srandyf unmap_warm_reset_vector(ushort_t *warm_reset_vector)
412*5295Srandyf {
413*5295Srandyf 	psm_unmap_phys((caddr_t)warm_reset_vector, sizeof (ushort_t *));
414*5295Srandyf }
415*5295Srandyf 
416*5295Srandyf /*
417*5295Srandyf  * We need to setup a 1:1 (virtual to physical) mapping for the
418*5295Srandyf  * page containing the wakeup code.
419*5295Srandyf  */
420*5295Srandyf static struct as *save_as;	/* when switching to kas */
421*5295Srandyf 
422*5295Srandyf static void
423*5295Srandyf unmap_wakeaddr_1to1(uint64_t wakephys)
424*5295Srandyf {
425*5295Srandyf 	uintptr_t	wp = (uintptr_t)wakephys;
426*5295Srandyf 	hat_setup(save_as->a_hat, 0);	/* switch back from kernel hat */
427*5295Srandyf 	hat_unload(kas.a_hat, (caddr_t)wp, PAGESIZE, HAT_UNLOAD);
428*5295Srandyf }
429*5295Srandyf 
430*5295Srandyf void
431*5295Srandyf i_cpr_post_resume_cpus()
432*5295Srandyf {
433*5295Srandyf 	uint64_t	wakephys = rm_platter_pa;
434*5295Srandyf 
435*5295Srandyf 	if (warm_reset_vector != NULL)
436*5295Srandyf 		unmap_warm_reset_vector(warm_reset_vector);
437*5295Srandyf 
438*5295Srandyf 	hat_unload(kas.a_hat, (caddr_t)(uintptr_t)rm_platter_pa, MMU_PAGESIZE,
439*5295Srandyf 	    HAT_UNLOAD);
440*5295Srandyf 
441*5295Srandyf 	/*
442*5295Srandyf 	 * cmi_post_mpstartup() is only required upon boot not upon
443*5295Srandyf 	 * resume from RAM
444*5295Srandyf 	 */
445*5295Srandyf 
446*5295Srandyf 	PT(PT_UNDO1to1);
447*5295Srandyf 	/* Tear down 1:1 mapping for wakeup code */
448*5295Srandyf 	unmap_wakeaddr_1to1(wakephys);
449*5295Srandyf }
450*5295Srandyf 
451*5295Srandyf /* ARGSUSED */
452*5295Srandyf void
453*5295Srandyf i_cpr_handle_xc(int flag)
454*5295Srandyf {
455*5295Srandyf }
456*5295Srandyf 
457*5295Srandyf int
458*5295Srandyf i_cpr_reusable_supported(void)
459*5295Srandyf {
460*5295Srandyf 	return (0);
461*5295Srandyf }
462*5295Srandyf static void
463*5295Srandyf map_wakeaddr_1to1(uint64_t wakephys)
464*5295Srandyf {
465*5295Srandyf 	uintptr_t	wp = (uintptr_t)wakephys;
466*5295Srandyf 	hat_devload(kas.a_hat, (caddr_t)wp, PAGESIZE, btop(wakephys),
467*5295Srandyf 	    (PROT_READ|PROT_WRITE|PROT_EXEC|HAT_STORECACHING_OK|HAT_NOSYNC),
468*5295Srandyf 	    HAT_LOAD);
469*5295Srandyf 	save_as = curthread->t_procp->p_as;
470*5295Srandyf 	hat_setup(kas.a_hat, 0);	/* switch to kernel-only hat */
471*5295Srandyf }
472*5295Srandyf 
473*5295Srandyf 
474*5295Srandyf void
475*5295Srandyf prt_other_cpus()
476*5295Srandyf {
477*5295Srandyf 	int	who;
478*5295Srandyf 
479*5295Srandyf 	if (ncpus == 1) {
480*5295Srandyf 		PMD(PMD_SX, ("prt_other_cpus() other cpu table empty for "
481*5295Srandyf 		    "uniprocessor machine\n"))
482*5295Srandyf 		return;
483*5295Srandyf 	}
484*5295Srandyf 
485*5295Srandyf 	for (who = 0; who < ncpus; who++) {
486*5295Srandyf 
487*5295Srandyf 		wc_cpu_t	*cpup = wc_other_cpus + who;
488*5295Srandyf 
489*5295Srandyf 		PMD(PMD_SX, ("prt_other_cpus() who = %d, gdt=%p:%x, "
490*5295Srandyf 		    "idt=%p:%x, ldt=%lx, tr=%lx, kgsbase="
491*5295Srandyf 		    AFMT ", sp=%lx\n", who,
492*5295Srandyf 		    (void *)cpup->wc_gdt_base, cpup->wc_gdt_limit,
493*5295Srandyf 		    (void *)cpup->wc_idt_base, cpup->wc_idt_limit,
494*5295Srandyf 		    (long)cpup->wc_ldt, (long)cpup->wc_tr,
495*5295Srandyf 		    (long)cpup->wc_kgsbase, (long)cpup->wc_rsp))
496*5295Srandyf 	}
497*5295Srandyf }
498*5295Srandyf 
499*5295Srandyf /*
500*5295Srandyf  * Power down the system.
501*5295Srandyf  */
502*5295Srandyf int
503*5295Srandyf i_cpr_power_down(int sleeptype)
504*5295Srandyf {
505*5295Srandyf 	caddr_t		wakevirt = rm_platter_va;
506*5295Srandyf 	uint64_t	wakephys = rm_platter_pa;
507*5295Srandyf 	uint_t		saved_intr;
508*5295Srandyf 	uint32_t	code_length = 0;
509*5295Srandyf 	wc_desctbr_t	gdt;
510*5295Srandyf 	/*LINTED*/
511*5295Srandyf 	wakecode_t	*wp = (wakecode_t *)wakevirt;
512*5295Srandyf 	/*LINTED*/
513*5295Srandyf 	rm_platter_t	*wcpp = (rm_platter_t *)wakevirt;
514*5295Srandyf 	wc_cpu_t	*cpup = &(wp->wc_cpu);
515*5295Srandyf 	dev_info_t	*ppm;
516*5295Srandyf 	int		ret = 0;
517*5295Srandyf 	power_req_t	power_req;
518*5295Srandyf 	char *str =	"i_cpr_power_down";
519*5295Srandyf #if defined(__amd64)
520*5295Srandyf 	/*LINTED*/
521*5295Srandyf 	rm_platter_t *real_mode_platter = (rm_platter_t *)rm_platter_va;
522*5295Srandyf #endif
523*5295Srandyf 	extern int	cpr_suspend_succeeded;
524*5295Srandyf 	extern void	kernel_wc_code();
525*5295Srandyf 	extern ulong_t	intr_clear(void);
526*5295Srandyf 	extern void	intr_restore(ulong_t);
527*5295Srandyf 
528*5295Srandyf 	ASSERT(sleeptype == CPR_TORAM);
529*5295Srandyf 	ASSERT(CPU->cpu_id == 0);
530*5295Srandyf 
531*5295Srandyf 	if ((ppm = PPM(ddi_root_node())) == NULL) {
532*5295Srandyf 		PMD(PMD_SX, ("%s: root node not claimed\n", str))
533*5295Srandyf 		return (ENOTTY);
534*5295Srandyf 	}
535*5295Srandyf 
536*5295Srandyf 	PMD(PMD_SX, ("Entering %s()\n", str))
537*5295Srandyf 
538*5295Srandyf 	PT(PT_IC);
539*5295Srandyf 	saved_intr = intr_clear();
540*5295Srandyf 
541*5295Srandyf 	PT(PT_1to1);
542*5295Srandyf 	/* Setup 1:1 mapping for wakeup code */
543*5295Srandyf 	map_wakeaddr_1to1(wakephys);
544*5295Srandyf 
545*5295Srandyf 	PMD(PMD_SX, ("ncpus=%d\n", ncpus))
546*5295Srandyf 
547*5295Srandyf 	PMD(PMD_SX, ("wc_rm_end - wc_rm_start=%lx WC_CODESIZE=%x\n",
548*5295Srandyf 	    ((size_t)((uint_t)wc_rm_end - (uint_t)wc_rm_start)), WC_CODESIZE))
549*5295Srandyf 
550*5295Srandyf 	PMD(PMD_SX, ("wakevirt=%p, wakephys=%x\n",
551*5295Srandyf 	    (void *)wakevirt, (uint_t)wakephys))
552*5295Srandyf 
553*5295Srandyf 	ASSERT(((size_t)((uint_t)wc_rm_end - (uint_t)wc_rm_start)) <
554*5295Srandyf 	    WC_CODESIZE);
555*5295Srandyf 
556*5295Srandyf 	bzero(wakevirt, PAGESIZE);
557*5295Srandyf 
558*5295Srandyf 	/* Copy code to rm_platter */
559*5295Srandyf 	bcopy((caddr_t)wc_rm_start, wakevirt,
560*5295Srandyf 	    (size_t)((uint_t)wc_rm_end - (uint_t)wc_rm_start));
561*5295Srandyf 
562*5295Srandyf 	prt_other_cpus();
563*5295Srandyf 
564*5295Srandyf #if defined(__amd64)
565*5295Srandyf 
566*5295Srandyf 	PMD(PMD_SX, ("real_mode_platter->rm_cr4=%lx, getcr4()=%lx\n",
567*5295Srandyf 	    (ulong_t)real_mode_platter->rm_cr4, (ulong_t)getcr4()))
568*5295Srandyf 	PMD(PMD_SX, ("real_mode_platter->rm_pdbr=%lx, getcr3()=%lx\n",
569*5295Srandyf 	    (ulong_t)real_mode_platter->rm_pdbr, getcr3()))
570*5295Srandyf 
571*5295Srandyf 	real_mode_platter->rm_cr4 = getcr4();
572*5295Srandyf 	real_mode_platter->rm_pdbr = getcr3();
573*5295Srandyf 
574*5295Srandyf 	rmp_gdt_init(real_mode_platter);
575*5295Srandyf 
576*5295Srandyf 	/*
577*5295Srandyf 	 * Since the CPU needs to jump to protected mode using an identity
578*5295Srandyf 	 * mapped address, we need to calculate it here.
579*5295Srandyf 	 */
580*5295Srandyf 	real_mode_platter->rm_longmode64_addr = rm_platter_pa +
581*5295Srandyf 	    ((uint32_t)wc_long_mode_64 - (uint32_t)wc_rm_start);
582*5295Srandyf 
583*5295Srandyf 	PMD(PMD_SX, ("real_mode_platter->rm_cr4=%lx, getcr4()=%lx\n",
584*5295Srandyf 	    (ulong_t)real_mode_platter->rm_cr4, getcr4()))
585*5295Srandyf 
586*5295Srandyf 	PMD(PMD_SX, ("real_mode_platter->rm_pdbr=%lx, getcr3()=%lx\n",
587*5295Srandyf 	    (ulong_t)real_mode_platter->rm_pdbr, getcr3()))
588*5295Srandyf 
589*5295Srandyf 	PMD(PMD_SX, ("real_mode_platter->rm_longmode64_addr=%lx\n",
590*5295Srandyf 	    (ulong_t)real_mode_platter->rm_longmode64_addr))
591*5295Srandyf 
592*5295Srandyf #endif
593*5295Srandyf 
594*5295Srandyf 	PMD(PMD_SX, ("mp_cpus=%lx\n", (ulong_t)mp_cpus))
595*5295Srandyf 
596*5295Srandyf 	PT(PT_SC);
597*5295Srandyf 	if (wc_save_context(cpup)) {
598*5295Srandyf 
599*5295Srandyf 		ret = i_cpr_platform_alloc(&(wc_other_cpus->wc_apic_state));
600*5295Srandyf 		if (ret != 0)
601*5295Srandyf 			return (ret);
602*5295Srandyf 
603*5295Srandyf 		ret = i_cpr_save_apic(&(wc_other_cpus->wc_apic_state));
604*5295Srandyf 		PMD(PMD_SX, ("%s: i_cpr_save_apic() returned %d\n", str, ret))
605*5295Srandyf 		if (ret != 0)
606*5295Srandyf 			return (ret);
607*5295Srandyf 
608*5295Srandyf 		PMD(PMD_SX, ("wakephys=%x, kernel_wc_code=%p\n",
609*5295Srandyf 		    (uint_t)wakephys, (void *)&kernel_wc_code))
610*5295Srandyf 		PMD(PMD_SX, ("virtaddr=%lx, retaddr=%lx\n",
611*5295Srandyf 		    (long)cpup->wc_virtaddr, (long)cpup->wc_retaddr))
612*5295Srandyf 		PMD(PMD_SX, ("ebx=%x, edi=%x, esi=%x, ebp=%x, esp=%x\n",
613*5295Srandyf 		    cpup->wc_ebx, cpup->wc_edi, cpup->wc_esi, cpup->wc_ebp,
614*5295Srandyf 		    cpup->wc_esp))
615*5295Srandyf 		PMD(PMD_SX, ("cr0=%lx, cr3=%lx, cr4=%lx\n",
616*5295Srandyf 		    (long)cpup->wc_cr0, (long)cpup->wc_cr3,
617*5295Srandyf 		    (long)cpup->wc_cr4))
618*5295Srandyf 		PMD(PMD_SX, ("cs=%x, ds=%x, es=%x, ss=%x, fs=%lx, gs=%lx, "
619*5295Srandyf 		    "flgs=%lx\n", cpup->wc_cs, cpup->wc_ds, cpup->wc_es,
620*5295Srandyf 		    cpup->wc_ss, (long)cpup->wc_fs, (long)cpup->wc_gs,
621*5295Srandyf 		    (long)cpup->wc_eflags))
622*5295Srandyf 
623*5295Srandyf 		PMD(PMD_SX, ("gdt=%p:%x, idt=%p:%x, ldt=%lx, tr=%lx, "
624*5295Srandyf 		    "kgbase=%lx\n", (void *)cpup->wc_gdt_base,
625*5295Srandyf 		    cpup->wc_gdt_limit, (void *)cpup->wc_idt_base,
626*5295Srandyf 		    cpup->wc_idt_limit, (long)cpup->wc_ldt,
627*5295Srandyf 		    (long)cpup->wc_tr, (long)cpup->wc_kgsbase))
628*5295Srandyf 
629*5295Srandyf 		gdt.base = cpup->wc_gdt_base;
630*5295Srandyf 		gdt.limit = cpup->wc_gdt_limit;
631*5295Srandyf 
632*5295Srandyf #if defined(__amd64)
633*5295Srandyf 		code_length = (uint32_t)wc_long_mode_64 -
634*5295Srandyf 		    (uint32_t)wc_rm_start;
635*5295Srandyf #else
636*5295Srandyf 		code_length = 0;
637*5295Srandyf #endif
638*5295Srandyf 
639*5295Srandyf 		init_real_mode_platter(0, code_length, cpup->wc_cr4, gdt);
640*5295Srandyf 
641*5295Srandyf #if defined(__amd64)
642*5295Srandyf 		PMD(PMD_SX, ("real_mode_platter->rm_cr4=%lx, getcr4()=%lx\n",
643*5295Srandyf 		    (ulong_t)wcpp->rm_cr4, getcr4()))
644*5295Srandyf 
645*5295Srandyf 		PMD(PMD_SX, ("real_mode_platter->rm_pdbr=%lx, getcr3()=%lx\n",
646*5295Srandyf 		    (ulong_t)wcpp->rm_pdbr, getcr3()))
647*5295Srandyf 
648*5295Srandyf 		PMD(PMD_SX, ("real_mode_platter->rm_longmode64_addr=%lx\n",
649*5295Srandyf 		    (ulong_t)wcpp->rm_longmode64_addr))
650*5295Srandyf 
651*5295Srandyf 		PMD(PMD_SX,
652*5295Srandyf 		    ("real_mode_platter->rm_temp_gdt[TEMPGDT_KCODE64]=%lx\n",
653*5295Srandyf 		    (ulong_t)wcpp->rm_temp_gdt[TEMPGDT_KCODE64]))
654*5295Srandyf #endif
655*5295Srandyf 
656*5295Srandyf 		PMD(PMD_SX, ("gdt=%p:%x, idt=%p:%x, ldt=%lx, tr=%lx, "
657*5295Srandyf 		    "kgsbase=%lx\n", (void *)wcpp->rm_gdt_base,
658*5295Srandyf 		    wcpp->rm_gdt_lim, (void *)wcpp->rm_idt_base,
659*5295Srandyf 		    wcpp->rm_idt_lim, (long)cpup->wc_ldt, (long)cpup->wc_tr,
660*5295Srandyf 		    (long)cpup->wc_kgsbase))
661*5295Srandyf 
662*5295Srandyf 		power_req.request_type = PMR_PPM_ENTER_SX;
663*5295Srandyf 		power_req.req.ppm_power_enter_sx_req.sx_state = S3;
664*5295Srandyf 		power_req.req.ppm_power_enter_sx_req.test_point =
665*5295Srandyf 		    cpr_test_point;
666*5295Srandyf 		power_req.req.ppm_power_enter_sx_req.wakephys = wakephys;
667*5295Srandyf 
668*5295Srandyf 		PMD(PMD_SX, ("%s: pm_ctlops PMR_PPM_ENTER_SX\n", str))
669*5295Srandyf 		PT(PT_PPMCTLOP);
670*5295Srandyf 		(void) pm_ctlops(ppm, ddi_root_node(), DDI_CTLOPS_POWER,
671*5295Srandyf 		    &power_req, &ret);
672*5295Srandyf 		PMD(PMD_SX, ("%s: returns %d\n", str, ret))
673*5295Srandyf 
674*5295Srandyf 		/*
675*5295Srandyf 		 * If it works, we get control back to the else branch below
676*5295Srandyf 		 * If we get control back here, it didn't work.
677*5295Srandyf 		 * XXX return EINVAL here?
678*5295Srandyf 		 */
679*5295Srandyf 
680*5295Srandyf 		unmap_wakeaddr_1to1(wakephys);
681*5295Srandyf 		intr_restore(saved_intr);
682*5295Srandyf 
683*5295Srandyf 		return (ret);
684*5295Srandyf 	} else {
685*5295Srandyf 		cpr_suspend_succeeded = 1;
686*5295Srandyf 
687*5295Srandyf 		power_req.request_type = PMR_PPM_EXIT_SX;
688*5295Srandyf 		power_req.req.ppm_power_enter_sx_req.sx_state = S3;
689*5295Srandyf 
690*5295Srandyf 		PMD(PMD_SX, ("%s: pm_ctlops PMR_PPM_EXIT_SX\n", str))
691*5295Srandyf 		PT(PT_PPMCTLOP);
692*5295Srandyf 		(void) pm_ctlops(ppm, ddi_root_node(), DDI_CTLOPS_POWER,
693*5295Srandyf 		    &power_req, &ret);
694*5295Srandyf 		PMD(PMD_SX, ("%s: returns %d\n", str, ret))
695*5295Srandyf 
696*5295Srandyf 		ret = i_cpr_restore_apic(&(wc_other_cpus->wc_apic_state));
697*5295Srandyf 		/*
698*5295Srandyf 		 * the restore should never fail, if the saved suceeded
699*5295Srandyf 		 */
700*5295Srandyf 		ASSERT(ret == 0);
701*5295Srandyf 
702*5295Srandyf 		i_cpr_platform_free(&(wc_other_cpus->wc_apic_state));
703*5295Srandyf 
704*5295Srandyf 		PT(PT_INTRRESTORE);
705*5295Srandyf 		intr_restore(saved_intr);
706*5295Srandyf 		PT(PT_CPU);
707*5295Srandyf 
708*5295Srandyf 		return (ret);
709*5295Srandyf 	}
710*5295Srandyf }
711*5295Srandyf 
712*5295Srandyf /*
713*5295Srandyf  * Stop all other cpu's before halting or rebooting. We pause the cpu's
714*5295Srandyf  * instead of sending a cross call.
715*5295Srandyf  * Stolen from sun4/os/mp_states.c
716*5295Srandyf  */
717*5295Srandyf 
718*5295Srandyf static int cpu_are_paused;	/* sic */
719*5295Srandyf 
720*5295Srandyf void
721*5295Srandyf i_cpr_stop_other_cpus(void)
722*5295Srandyf {
723*5295Srandyf 	mutex_enter(&cpu_lock);
724*5295Srandyf 	if (cpu_are_paused) {
725*5295Srandyf 		mutex_exit(&cpu_lock);
726*5295Srandyf 		return;
727*5295Srandyf 	}
728*5295Srandyf 	pause_cpus(NULL);
729*5295Srandyf 	cpu_are_paused = 1;
730*5295Srandyf 
731*5295Srandyf 	mutex_exit(&cpu_lock);
732*5295Srandyf }
733*5295Srandyf 
734*5295Srandyf int
735*5295Srandyf i_cpr_is_supported(int sleeptype)
736*5295Srandyf {
737*5295Srandyf 	extern int cpr_supported_override;
738*5295Srandyf 	extern int cpr_platform_enable;
739*5295Srandyf 	extern int pm_S3_enabled;
740*5295Srandyf 
741*5295Srandyf 	if (sleeptype != CPR_TORAM)
742*5295Srandyf 		return (0);
743*5295Srandyf 
744*5295Srandyf 	/*
745*5295Srandyf 	 * The next statement tests if a specific platform has turned off
746*5295Srandyf 	 * cpr support.
747*5295Srandyf 	 */
748*5295Srandyf 	if (cpr_supported_override)
749*5295Srandyf 		return (0);
750*5295Srandyf 
751*5295Srandyf 	/*
752*5295Srandyf 	 * If a platform has specifically turned on cpr support ...
753*5295Srandyf 	 */
754*5295Srandyf 	if (cpr_platform_enable)
755*5295Srandyf 		return (1);
756*5295Srandyf 
757*5295Srandyf 	return (pm_S3_enabled);
758*5295Srandyf }
759*5295Srandyf 
760*5295Srandyf void
761*5295Srandyf i_cpr_bitmap_cleanup(void)
762*5295Srandyf {
763*5295Srandyf }
764*5295Srandyf 
765*5295Srandyf void
766*5295Srandyf i_cpr_free_memory_resources(void)
767*5295Srandyf {
768*5295Srandyf }
769*5295Srandyf 
770*5295Srandyf /*
771*5295Srandyf  * Needed only for S3 so far
772*5295Srandyf  */
773*5295Srandyf static int
774*5295Srandyf i_cpr_platform_alloc(psm_state_request_t *req)
775*5295Srandyf {
776*5295Srandyf 	char	*str = "i_cpr_platform_alloc";
777*5295Srandyf 
778*5295Srandyf 	PMD(PMD_SX, ("cpu = %d, %s(%p) \n", CPU->cpu_id, str, (void *)req))
779*5295Srandyf 
780*5295Srandyf 	if (ncpus == 1) {
781*5295Srandyf 		PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
782*5295Srandyf 		return (0);
783*5295Srandyf 	}
784*5295Srandyf 
785*5295Srandyf 	req->psr_cmd = PSM_STATE_ALLOC;
786*5295Srandyf 	return ((*psm_state)(req));
787*5295Srandyf }
788*5295Srandyf 
789*5295Srandyf /*
790*5295Srandyf  * Needed only for S3 so far
791*5295Srandyf  */
792*5295Srandyf static void
793*5295Srandyf i_cpr_platform_free(psm_state_request_t *req)
794*5295Srandyf {
795*5295Srandyf 	char	*str = "i_cpr_platform_free";
796*5295Srandyf 
797*5295Srandyf 	PMD(PMD_SX, ("cpu = %d, %s(%p) \n", CPU->cpu_id, str, (void *)req))
798*5295Srandyf 
799*5295Srandyf 	if (ncpus == 1) {
800*5295Srandyf 		PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
801*5295Srandyf 	}
802*5295Srandyf 
803*5295Srandyf 	req->psr_cmd = PSM_STATE_FREE;
804*5295Srandyf 	(void) (*psm_state)(req);
805*5295Srandyf }
806*5295Srandyf 
807*5295Srandyf static int
808*5295Srandyf i_cpr_save_apic(psm_state_request_t *req)
809*5295Srandyf {
810*5295Srandyf 	char	*str = "i_cpr_save_apic";
811*5295Srandyf 
812*5295Srandyf 	if (ncpus == 1) {
813*5295Srandyf 		PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
814*5295Srandyf 		return (0);
815*5295Srandyf 	}
816*5295Srandyf 
817*5295Srandyf 	req->psr_cmd = PSM_STATE_SAVE;
818*5295Srandyf 	return ((*psm_state)(req));
819*5295Srandyf }
820*5295Srandyf 
821*5295Srandyf static int
822*5295Srandyf i_cpr_restore_apic(psm_state_request_t *req)
823*5295Srandyf {
824*5295Srandyf 	char	*str = "i_cpr_restore_apic";
825*5295Srandyf 
826*5295Srandyf 	if (ncpus == 1) {
827*5295Srandyf 		PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
828*5295Srandyf 		return (0);
829*5295Srandyf 	}
830*5295Srandyf 
831*5295Srandyf 	req->psr_cmd = PSM_STATE_RESTORE;
832*5295Srandyf 	return ((*psm_state)(req));
833*5295Srandyf }
834*5295Srandyf 
835*5295Srandyf 
836*5295Srandyf /* stop lint complaining about offset not being used in 32bit mode */
837*5295Srandyf #if !defined(__amd64)
838*5295Srandyf /*ARGSUSED*/
839*5295Srandyf #endif
840*5295Srandyf static void
841*5295Srandyf init_real_mode_platter(int cpun, uint32_t offset, uint_t cr4, wc_desctbr_t gdt)
842*5295Srandyf {
843*5295Srandyf 	/*LINTED*/
844*5295Srandyf 	rm_platter_t *real_mode_platter = (rm_platter_t *)rm_platter_va;
845*5295Srandyf 
846*5295Srandyf 	/*
847*5295Srandyf 	 * Fill up the real mode platter to make it easy for real mode code to
848*5295Srandyf 	 * kick it off. This area should really be one passed by boot to kernel
849*5295Srandyf 	 * and guaranteed to be below 1MB and aligned to 16 bytes. Should also
850*5295Srandyf 	 * have identical physical and virtual address in paged mode.
851*5295Srandyf 	 */
852*5295Srandyf 
853*5295Srandyf 	real_mode_platter->rm_pdbr = getcr3();
854*5295Srandyf 	real_mode_platter->rm_cpu = cpun;
855*5295Srandyf 	real_mode_platter->rm_cr4 = cr4;
856*5295Srandyf 
857*5295Srandyf 	real_mode_platter->rm_gdt_base = gdt.base;
858*5295Srandyf 	real_mode_platter->rm_gdt_lim = gdt.limit;
859*5295Srandyf 
860*5295Srandyf #if defined(__amd64)
861*5295Srandyf 	real_mode_platter->rm_x86feature = x86_feature;
862*5295Srandyf 
863*5295Srandyf 	if (getcr3() > 0xffffffffUL)
864*5295Srandyf 		panic("Cannot initialize CPUs; kernel's 64-bit page tables\n"
865*5295Srandyf 		    "located above 4G in physical memory (@ 0x%llx).",
866*5295Srandyf 		    (unsigned long long)getcr3());
867*5295Srandyf 
868*5295Srandyf 	/*
869*5295Srandyf 	 * Setup pseudo-descriptors for temporary GDT and IDT for use ONLY
870*5295Srandyf 	 * by code in real_mode_start():
871*5295Srandyf 	 *
872*5295Srandyf 	 * GDT[0]:  NULL selector
873*5295Srandyf 	 * GDT[1]:  64-bit CS: Long = 1, Present = 1, bits 12, 11 = 1
874*5295Srandyf 	 *
875*5295Srandyf 	 * Clear the IDT as interrupts will be off and a limit of 0 will cause
876*5295Srandyf 	 * the CPU to triple fault and reset on an NMI, seemingly as reasonable
877*5295Srandyf 	 * a course of action as any other, though it may cause the entire
878*5295Srandyf 	 * platform to reset in some cases...
879*5295Srandyf 	 */
880*5295Srandyf 	real_mode_platter->rm_temp_gdt[0] = 0ULL;
881*5295Srandyf 	real_mode_platter->rm_temp_gdt[TEMPGDT_KCODE64] = 0x20980000000000ULL;
882*5295Srandyf 
883*5295Srandyf 	real_mode_platter->rm_temp_gdt_lim = (ushort_t)
884*5295Srandyf 	    (sizeof (real_mode_platter->rm_temp_gdt) - 1);
885*5295Srandyf 	real_mode_platter->rm_temp_gdt_base = rm_platter_pa +
886*5295Srandyf 	    (uint32_t)(&((rm_platter_t *)0)->rm_temp_gdt);
887*5295Srandyf 
888*5295Srandyf 	real_mode_platter->rm_temp_idt_lim = 0;
889*5295Srandyf 	real_mode_platter->rm_temp_idt_base = 0;
890*5295Srandyf 
891*5295Srandyf 	/*
892*5295Srandyf 	 * Since the CPU needs to jump to protected mode using an identity
893*5295Srandyf 	 * mapped address, we need to calculate it here.
894*5295Srandyf 	 */
895*5295Srandyf 	real_mode_platter->rm_longmode64_addr = rm_platter_pa + offset;
896*5295Srandyf #endif	/* __amd64 */
897*5295Srandyf 
898*5295Srandyf 	/* return; */
899*5295Srandyf }
900*5295Srandyf 
901*5295Srandyf void
902*5295Srandyf i_cpr_start_cpu(void)
903*5295Srandyf {
904*5295Srandyf 
905*5295Srandyf 	struct cpu *cp = CPU;
906*5295Srandyf 
907*5295Srandyf 	char *str = "i_cpr_start_cpu";
908*5295Srandyf 	extern void init_cpu_syscall(struct cpu *cp);
909*5295Srandyf 
910*5295Srandyf #if defined(__amd64)
911*5295Srandyf 	wc_cpu_t	*cpup = wc_other_cpus + cp->cpu_id;
912*5295Srandyf #endif	/*	__amd64	*/
913*5295Srandyf 
914*5295Srandyf 	PMD(PMD_SX, ("%s() called\n", str))
915*5295Srandyf 
916*5295Srandyf 	PMD(PMD_SX, ("%s() #0 cp->cpu_base_spl %d\n", str,
917*5295Srandyf 	    cp->cpu_base_spl))
918*5295Srandyf 
919*5295Srandyf 	mutex_enter(&cpu_lock);
920*5295Srandyf 	if (cp == i_cpr_bootcpu()) {
921*5295Srandyf 		mutex_exit(&cpu_lock);
922*5295Srandyf 		PMD(PMD_SX,
923*5295Srandyf 		    ("%s() called on bootcpu nothing to do!\n", str))
924*5295Srandyf 		return;
925*5295Srandyf 	}
926*5295Srandyf 	mutex_exit(&cpu_lock);
927*5295Srandyf 
928*5295Srandyf 	/*
929*5295Srandyf 	 * We need to Sync PAT with cpu0's PAT. We have to do
930*5295Srandyf 	 * this with interrupts disabled.
931*5295Srandyf 	 */
932*5295Srandyf 	if (x86_feature & X86_PAT)
933*5295Srandyf 		pat_sync();
934*5295Srandyf 
935*5295Srandyf 	/*
936*5295Srandyf 	 * Initialize this CPU's syscall handlers
937*5295Srandyf 	 */
938*5295Srandyf 	init_cpu_syscall(cp);
939*5295Srandyf 
940*5295Srandyf 	PMD(PMD_SX, ("%s() #1 cp->cpu_base_spl %d\n", str, cp->cpu_base_spl))
941*5295Srandyf 
942*5295Srandyf 	/*
943*5295Srandyf 	 * Do not need to call cpuid_pass2(), cpuid_pass3(), cpuid_pass4() or
944*5295Srandyf 	 * init_cpu_info(), since the work that they do is only needed to
945*5295Srandyf 	 * be done once at boot time
946*5295Srandyf 	 */
947*5295Srandyf 
948*5295Srandyf 
949*5295Srandyf 	mutex_enter(&cpu_lock);
950*5295Srandyf 
951*5295Srandyf #if defined(__amd64)
952*5295Srandyf 	restore_stack(cpup);
953*5295Srandyf #endif	/*	__amd64	*/
954*5295Srandyf 
955*5295Srandyf 	CPUSET_ADD(procset, cp->cpu_id);
956*5295Srandyf 	mutex_exit(&cpu_lock);
957*5295Srandyf 
958*5295Srandyf 	PMD(PMD_SX, ("%s() #2 cp->cpu_base_spl %d\n", str,
959*5295Srandyf 	    cp->cpu_base_spl))
960*5295Srandyf 
961*5295Srandyf 	/* XXX remove before integration */
962*5295Srandyf 	PMD(PMD_SX, ("%s() procset 0x%lx\n", str, (ulong_t)procset))
963*5295Srandyf 
964*5295Srandyf 	if (tsc_gethrtime_enable) {
965*5295Srandyf 		PMD(PMD_SX, ("%s() calling tsc_sync_slave\n", str))
966*5295Srandyf 		tsc_sync_slave();
967*5295Srandyf 	}
968*5295Srandyf 
969*5295Srandyf 	PMD(PMD_SX, ("%s() cp->cpu_id %d, cp->cpu_intr_actv %d\n", str,
970*5295Srandyf 	    cp->cpu_id, cp->cpu_intr_actv))
971*5295Srandyf 	PMD(PMD_SX, ("%s() #3 cp->cpu_base_spl %d\n", str,
972*5295Srandyf 	    cp->cpu_base_spl))
973*5295Srandyf 
974*5295Srandyf 	(void) spl0();		/* enable interrupts */
975*5295Srandyf 
976*5295Srandyf 	PMD(PMD_SX, ("%s() #4 cp->cpu_base_spl %d\n", str,
977*5295Srandyf 	    cp->cpu_base_spl))
978*5295Srandyf 
979*5295Srandyf 	/*
980*5295Srandyf 	 * Set up the CPU module for this CPU.  This can't be done before
981*5295Srandyf 	 * this CPU is made CPU_READY, because we may (in heterogeneous systems)
982*5295Srandyf 	 * need to go load another CPU module.  The act of attempting to load
983*5295Srandyf 	 * a module may trigger a cross-call, which will ASSERT unless this
984*5295Srandyf 	 * cpu is CPU_READY.
985*5295Srandyf 	 */
986*5295Srandyf 
987*5295Srandyf 	/*
988*5295Srandyf 	 * cmi already been init'd (during boot), so do not need to do it again
989*5295Srandyf 	 */
990*5295Srandyf #ifdef PM_REINITMCAONRESUME
991*5295Srandyf 	if (x86_feature & X86_MCA)
992*5295Srandyf 		cmi_mca_init();
993*5295Srandyf #endif
994*5295Srandyf 
995*5295Srandyf 	PMD(PMD_SX, ("%s() returning\n", str))
996*5295Srandyf 
997*5295Srandyf 	/* return; */
998*5295Srandyf }
999*5295Srandyf 
1000*5295Srandyf #if defined(__amd64)
1001*5295Srandyf /*
1002*5295Srandyf  * we only need to do this for amd64!
1003*5295Srandyf  */
1004*5295Srandyf 
1005*5295Srandyf /*
1006*5295Srandyf  * save the stack
1007*5295Srandyf  */
1008*5295Srandyf void
1009*5295Srandyf save_stack(wc_cpu_t *cpup)
1010*5295Srandyf {
1011*5295Srandyf 	char *str = "save_stack";
1012*5295Srandyf 	caddr_t base = curthread->t_stk;
1013*5295Srandyf 	caddr_t sp = (caddr_t)cpup->wc_rsp;
1014*5295Srandyf 
1015*5295Srandyf 
1016*5295Srandyf 	PMD(PMD_SX, ("%s() CPU->cpu_id %d\n", str, CPU->cpu_id))
1017*5295Srandyf 	PMD(PMD_SX, ("save_stack() curthread->t_stk = %p, sp = %p\n",
1018*5295Srandyf 	    (void *)base, (void *)sp))
1019*5295Srandyf 
1020*5295Srandyf 	ASSERT(base > sp);
1021*5295Srandyf 	/*LINTED*/
1022*5295Srandyf 	bcopy(sp, cpup->wc_stack, base - sp);
1023*5295Srandyf 
1024*5295Srandyf }
1025*5295Srandyf 
1026*5295Srandyf /*
1027*5295Srandyf  * restore the stack
1028*5295Srandyf  */
1029*5295Srandyf static	void
1030*5295Srandyf restore_stack(wc_cpu_t *cpup)
1031*5295Srandyf {
1032*5295Srandyf 	/*
1033*5295Srandyf 	 * we only need to do this for amd64!
1034*5295Srandyf 	 */
1035*5295Srandyf 
1036*5295Srandyf 	char *str = "restore_stack";
1037*5295Srandyf 	caddr_t base = curthread->t_stk;
1038*5295Srandyf 	caddr_t sp = (caddr_t)cpup->wc_rsp;
1039*5295Srandyf 
1040*5295Srandyf 	PMD(PMD_SX, ("%s() CPU->cpu_id %d\n", str, CPU->cpu_id))
1041*5295Srandyf 	PMD(PMD_SX, ("%s() curthread->t_stk = %p, sp = %p\n", str,
1042*5295Srandyf 	    (void *)base, (void *)sp))
1043*5295Srandyf 
1044*5295Srandyf 	ASSERT(base > sp);
1045*5295Srandyf 	/*LINTED*/
1046*5295Srandyf 	bcopy(cpup->wc_stack, sp, base - sp);
1047*5295Srandyf 
1048*5295Srandyf }
1049*5295Srandyf 
1050*5295Srandyf #endif	/*	__amd64	*/
1051*5295Srandyf 
1052*5295Srandyf 
1053*5295Srandyf void
1054*5295Srandyf i_cpr_alloc_cpus(void)
1055*5295Srandyf {
1056*5295Srandyf 	char *str = "i_cpr_alloc_cpus";
1057*5295Srandyf 
1058*5295Srandyf 	PMD(PMD_SX, ("%s() CPU->cpu_id %d\n", str, CPU->cpu_id))
1059*5295Srandyf 	/*
1060*5295Srandyf 	 * we allocate this only when we actually need it to save on
1061*5295Srandyf 	 * kernel memory
1062*5295Srandyf 	 */
1063*5295Srandyf 
1064*5295Srandyf 	if (wc_other_cpus == NULL) {
1065*5295Srandyf 		wc_other_cpus = kmem_zalloc(ncpus * sizeof (wc_cpu_t),
1066*5295Srandyf 		    KM_SLEEP);
1067*5295Srandyf 	}
1068*5295Srandyf 
1069*5295Srandyf }
1070*5295Srandyf 
1071*5295Srandyf void
1072*5295Srandyf i_cpr_free_cpus(void)
1073*5295Srandyf {
1074*5295Srandyf 	if (wc_other_cpus != NULL) {
1075*5295Srandyf 		kmem_free((void *) wc_other_cpus, ncpus * sizeof (wc_cpu_t));
1076*5295Srandyf 		wc_other_cpus = NULL;
1077*5295Srandyf 	}
1078*5295Srandyf }
1079*5295Srandyf 
1080*5295Srandyf /*
1081*5295Srandyf  * wrapper for acpica_ddi_save_resources()
1082*5295Srandyf  */
1083*5295Srandyf void
1084*5295Srandyf i_cpr_save_configuration(dev_info_t *dip)
1085*5295Srandyf {
1086*5295Srandyf 	acpica_ddi_save_resources(dip);
1087*5295Srandyf }
1088*5295Srandyf 
1089*5295Srandyf /*
1090*5295Srandyf  * wrapper for acpica_ddi_restore_resources()
1091*5295Srandyf  */
1092*5295Srandyf void
1093*5295Srandyf i_cpr_restore_configuration(dev_info_t *dip)
1094*5295Srandyf {
1095*5295Srandyf 	acpica_ddi_restore_resources(dip);
1096*5295Srandyf }
1097