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