cpr_impl.c revision 643e2e74e1c00e6b3d1896a6a67dbdb7308135c3
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * CDDL HEADER START
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * The contents of this file are subject to the terms of the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Common Development and Distribution License (the "License").
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * You may not use this file except in compliance with the License.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * or http://www.opensolaris.org/os/licensing.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * See the License for the specific language governing permissions
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * and limitations under the License.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * When distributing Covered Code, include this CDDL HEADER in each
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * If applicable, add the following below this CDDL HEADER, with the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * fields enclosed by brackets "[]" replaced with your own identifying
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * information: Portions Copyright [yyyy] [name of copyright owner]
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * CDDL HEADER END
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Use is subject to license terms.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#pragma ident "%Z%%M% %I% %E% SMI"
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Platform specific implementation code
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Currently only suspend to RAM is supported (ACPI S3)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define SUNDDI_IMPL
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/types.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/promif.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/prom_isa.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/prom_plat.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/cpuvar.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/pte.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <vm/hat.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <vm/page.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <vm/as.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/cpr.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/kmem.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/clock.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/kmem.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/panic.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <vm/seg_kmem.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/cpu_module.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/callb.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/machsystm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/vmsystm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/systm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/archsystm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/stack.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/fs/ufs_fs.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/memlist.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/bootconf.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/thread.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/x_call.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/smp_impldefs.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <vm/vm_dep.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/psm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/epm.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/cpr_wakecode.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/x86_archext.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/reboot.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/acpi/acpi.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#include <sys/acpica.h>
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#define AFMT "%lx"
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern int flushes_require_xcalls;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern cpuset_t cpu_ready_set;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern void *wc_long_mode_64(void);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif /* __amd64 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern int tsc_gethrtime_enable;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfextern void i_cpr_start_cpu(void);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfushort_t cpr_mach_type = CPR_MACHTYPE_X86;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid (*cpr_start_cpu_func)(void) = i_cpr_start_cpu;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic wc_cpu_t *wc_other_cpus = NULL;
a563a037ee1e9e7c39304f3775eb7327ab86b914bhollerstatic cpuset_t procset;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfinit_real_mode_platter(int cpun, uint32_t offset, uint_t cr4, wc_desctbr_t gdt);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int i_cpr_platform_alloc(psm_state_request_t *req);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void i_cpr_platform_free(psm_state_request_t *req);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int i_cpr_save_apic(psm_state_request_t *req);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int i_cpr_restore_apic(psm_state_request_t *req);
4716fd887b81cd876928e6c03a0c6d0dcf362c90janstatic int wait_for_set(cpuset_t *set, int who);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void restore_stack(wc_cpu_t *cpup);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void save_stack(wc_cpu_t *cpup);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid (*save_stack_func)(wc_cpu_t *) = save_stack;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif /* __amd64 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * restart paused slave cpus
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_machdep_setup(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ncpus > 1) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf CPR_DEBUG(CPR_DEBUG1, ("MP restarted...\n"));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf start_cpus();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Stop all interrupt activities in the system
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_stop_intr(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) spl7();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Set machine up to take interrupts
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_enable_intr(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) spl0();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Save miscellaneous information which needs to be written to the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * state file. This information is required to re-initialize
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * kernel/prom handshaking.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_save_machdep_info(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int notcalled = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(notcalled);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_set_tbr(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfprocessorid_t
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_bootcpuid(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * cpu0 should contain bootcpu info
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfcpu_t *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_bootcpu(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(MUTEX_HELD(&cpu_lock));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (cpu_get(i_cpr_bootcpuid()));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Save context for the specified CPU
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_save_context(void *arg)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf long index = (long)arg;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf psm_state_request_t *papic_state;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int resuming;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int ret;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("i_cpr_save_context() index = %ld\n", index))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(index < NCPU);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf papic_state = &(wc_other_cpus + index)->wc_apic_state;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ret = i_cpr_platform_alloc(papic_state);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(ret == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ret = i_cpr_save_apic(papic_state);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(ret == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * wc_save_context returns twice, once when susending and
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * once when resuming, wc_save_context() returns 0 when
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * suspending and non-zero upon resume
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf resuming = (wc_save_context(wc_other_cpus + index) == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("i_cpr_save_context: wc_save_context returns %d\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf resuming))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * do NOT call any functions after this point, because doing so
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * will modify the stack that we are running on
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (resuming) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ret = i_cpr_restore_apic(papic_state);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(ret == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf i_cpr_platform_free(papic_state);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler /*
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler * Enable interrupts on this cpu.
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler * Do not bind interrupts to this CPU's local APIC until
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler * the CPU is ready to recieve interrupts.
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler */
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler ASSERT(CPU->cpu_id != i_cpr_bootcpuid());
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler mutex_enter(&cpu_lock);
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler cpu_enable_intr(CPU);
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler mutex_exit(&cpu_lock);
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Setting the bit in cpu_ready_set must be the last operation
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * in processor initialization; the boot CPU will continue to
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * boot once it sees this bit set for all active CPUs.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf CPUSET_ATOMIC_ADD(cpu_ready_set, CPU->cpu_id);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX,
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler ("i_cpr_save_context() resuming cpu %d in cpu_ready_set\n",
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler CPU->cpu_id))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (NULL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic ushort_t *warm_reset_vector = NULL;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic ushort_t *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfmap_warm_reset_vector()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!(warm_reset_vector = (ushort_t *)psm_map_phys(WARM_RESET_VECTOR,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf sizeof (ushort_t *), PROT_READ|PROT_WRITE)))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (NULL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * setup secondary cpu bios boot up vector
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *warm_reset_vector = (ushort_t)((caddr_t)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ((struct rm_platter *)rm_platter_va)->rm_code - rm_platter_va
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf + ((ulong_t)rm_platter_va & 0xf));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf warm_reset_vector++;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *warm_reset_vector = (ushort_t)(rm_platter_pa >> 4);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf --warm_reset_vector;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (warm_reset_vector);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_pre_resume_cpus()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * this is a cut down version of start_other_cpus()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * just do the initialization to wake the other cpus
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf unsigned who;
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan int boot_cpuid = i_cpr_bootcpuid();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uint32_t code_length = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf caddr_t wakevirt = rm_platter_va;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wakecode_t *wp = (wakecode_t *)wakevirt;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_pre_resume_cpus";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern int get_tsc_ready();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int err;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rm_platter_t *real_mode_platter = (rm_platter_t *)rm_platter_va;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Copy the real mode code at "real_mode_start" to the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * page at rm_platter_va.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf warm_reset_vector = map_warm_reset_vector();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (warm_reset_vector == NULL) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("i_cpr_pre_resume_cpus() returning #2\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf flushes_require_xcalls = 1;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * We lock our affinity to the master CPU to ensure that all slave CPUs
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * do their TSC syncs with the same CPU.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf affinity_set(CPU_CURRENT);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan /*
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler * Mark the boot cpu as being ready and in the procset, since we are
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler * running on that cpu.
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan */
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan CPUSET_ONLY(cpu_ready_set, boot_cpuid);
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler CPUSET_ONLY(procset, boot_cpuid);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (who = 0; who < ncpus; who++) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_cpu_t *cpup = wc_other_cpus + who;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_desctbr_t gdt;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan if (who == boot_cpuid)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf continue;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (!CPU_IN_SET(mp_cpus, who))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf continue;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() waking up %d cpu\n", str, who))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf bcopy(cpup, &(wp->wc_cpu), sizeof (wc_cpu_t));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf gdt.base = cpup->wc_gdt_base;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf gdt.limit = cpup->wc_gdt_limit;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf code_length = (uint32_t)wc_long_mode_64 - (uint32_t)wc_rm_start;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#else
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf code_length = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf init_real_mode_platter(who, code_length, cpup->wc_cr4, gdt);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if ((err = mach_cpuid_start(who, rm_platter_va)) != 0) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cmn_err(CE_WARN, "cpu%d: failed to start during "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "suspend/resume error %d", who, err);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf continue;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler PMD(PMD_SX, ("%s() #1 waiting for %d in procset\n", str, who))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan if (!wait_for_set(&procset, who))
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan continue;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() %d cpu started\n", str, who))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan PMD(PMD_SX, ("%s() tsc_ready = %d\n", str, get_tsc_ready()))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (tsc_gethrtime_enable) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() calling tsc_sync_master\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf tsc_sync_master(who);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler PMD(PMD_SX, ("%s() waiting for %d in cpu_ready_set\n", str,
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler who))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Wait for cpu to declare that it is ready, we want the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * cpus to start serially instead of in parallel, so that
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * they do not contend with each other in wc_rm_start()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan if (!wait_for_set(&cpu_ready_set, who))
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan continue;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * do not need to re-initialize dtrace using dtrace_cpu_init
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * function
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() cpu %d now ready\n", str, who))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf affinity_clear();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() all cpus now ready\n", str))
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfunmap_warm_reset_vector(ushort_t *warm_reset_vector)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf psm_unmap_phys((caddr_t)warm_reset_vector, sizeof (ushort_t *));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * We need to setup a 1:1 (virtual to physical) mapping for the
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * page containing the wakeup code.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic struct as *save_as; /* when switching to kas */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfunmap_wakeaddr_1to1(uint64_t wakephys)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uintptr_t wp = (uintptr_t)wakephys;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf hat_setup(save_as->a_hat, 0); /* switch back from kernel hat */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf hat_unload(kas.a_hat, (caddr_t)wp, PAGESIZE, HAT_UNLOAD);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_post_resume_cpus()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uint64_t wakephys = rm_platter_pa;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (warm_reset_vector != NULL)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf unmap_warm_reset_vector(warm_reset_vector);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf hat_unload(kas.a_hat, (caddr_t)(uintptr_t)rm_platter_pa, MMU_PAGESIZE,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf HAT_UNLOAD);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * cmi_post_mpstartup() is only required upon boot not upon
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * resume from RAM
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_UNDO1to1);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* Tear down 1:1 mapping for wakeup code */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf unmap_wakeaddr_1to1(wakephys);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/* ARGSUSED */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_handle_xc(int flag)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_reusable_supported(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfmap_wakeaddr_1to1(uint64_t wakephys)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uintptr_t wp = (uintptr_t)wakephys;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf hat_devload(kas.a_hat, (caddr_t)wp, PAGESIZE, btop(wakephys),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (PROT_READ|PROT_WRITE|PROT_EXEC|HAT_STORECACHING_OK|HAT_NOSYNC),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf HAT_LOAD);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf save_as = curthread->t_procp->p_as;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf hat_setup(kas.a_hat, 0); /* switch to kernel-only hat */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfprt_other_cpus()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int who;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ncpus == 1) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("prt_other_cpus() other cpu table empty for "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "uniprocessor machine\n"))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf for (who = 0; who < ncpus; who++) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_cpu_t *cpup = wc_other_cpus + who;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("prt_other_cpus() who = %d, gdt=%p:%x, "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "idt=%p:%x, ldt=%lx, tr=%lx, kgsbase="
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf AFMT ", sp=%lx\n", who,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void *)cpup->wc_gdt_base, cpup->wc_gdt_limit,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void *)cpup->wc_idt_base, cpup->wc_idt_limit,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_ldt, (long)cpup->wc_tr,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_kgsbase, (long)cpup->wc_rsp))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Power down the system.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_power_down(int sleeptype)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf caddr_t wakevirt = rm_platter_va;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uint64_t wakephys = rm_platter_pa;
a563a037ee1e9e7c39304f3775eb7327ab86b914bholler ulong_t saved_intr;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf uint32_t code_length = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_desctbr_t gdt;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wakecode_t *wp = (wakecode_t *)wakevirt;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rm_platter_t *wcpp = (rm_platter_t *)wakevirt;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_cpu_t *cpup = &(wp->wc_cpu);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf dev_info_t *ppm;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf int ret = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf power_req_t power_req;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_power_down";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rm_platter_t *real_mode_platter = (rm_platter_t *)rm_platter_va;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern int cpr_suspend_succeeded;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern void kernel_wc_code();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(sleeptype == CPR_TORAM);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(CPU->cpu_id == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if ((ppm = PPM(ddi_root_node())) == NULL) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s: root node not claimed\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ENOTTY);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("Entering %s()\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_IC);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf saved_intr = intr_clear();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_1to1);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* Setup 1:1 mapping for wakeup code */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf map_wakeaddr_1to1(wakephys);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("ncpus=%d\n", ncpus))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("wc_rm_end - wc_rm_start=%lx WC_CODESIZE=%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ((size_t)((uint_t)wc_rm_end - (uint_t)wc_rm_start)), WC_CODESIZE))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("wakevirt=%p, wakephys=%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void *)wakevirt, (uint_t)wakephys))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(((size_t)((uint_t)wc_rm_end - (uint_t)wc_rm_start)) <
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf WC_CODESIZE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf bzero(wakevirt, PAGESIZE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* Copy code to rm_platter */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf bcopy((caddr_t)wc_rm_start, wakevirt,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (size_t)((uint_t)wc_rm_end - (uint_t)wc_rm_start));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf prt_other_cpus();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_cr4=%lx, getcr4()=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)real_mode_platter->rm_cr4, (ulong_t)getcr4()))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_pdbr=%lx, getcr3()=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)real_mode_platter->rm_pdbr, getcr3()))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_cr4 = getcr4();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_pdbr = getcr3();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rmp_gdt_init(real_mode_platter);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Since the CPU needs to jump to protected mode using an identity
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * mapped address, we need to calculate it here.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_longmode64_addr = rm_platter_pa +
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ((uint32_t)wc_long_mode_64 - (uint32_t)wc_rm_start);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_cr4=%lx, getcr4()=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)real_mode_platter->rm_cr4, getcr4()))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_pdbr=%lx, getcr3()=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)real_mode_platter->rm_pdbr, getcr3()))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_longmode64_addr=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)real_mode_platter->rm_longmode64_addr))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_SC);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (wc_save_context(cpup)) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ret = i_cpr_platform_alloc(&(wc_other_cpus->wc_apic_state));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ret != 0)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ret);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ret = i_cpr_save_apic(&(wc_other_cpus->wc_apic_state));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s: i_cpr_save_apic() returned %d\n", str, ret))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ret != 0)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ret);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("wakephys=%x, kernel_wc_code=%p\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (uint_t)wakephys, (void *)&kernel_wc_code))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("virtaddr=%lx, retaddr=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_virtaddr, (long)cpup->wc_retaddr))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("ebx=%x, edi=%x, esi=%x, ebp=%x, esp=%x\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpup->wc_ebx, cpup->wc_edi, cpup->wc_esi, cpup->wc_ebp,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpup->wc_esp))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("cr0=%lx, cr3=%lx, cr4=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_cr0, (long)cpup->wc_cr3,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_cr4))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("cs=%x, ds=%x, es=%x, ss=%x, fs=%lx, gs=%lx, "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "flgs=%lx\n", cpup->wc_cs, cpup->wc_ds, cpup->wc_es,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpup->wc_ss, (long)cpup->wc_fs, (long)cpup->wc_gs,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_eflags))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("gdt=%p:%x, idt=%p:%x, ldt=%lx, tr=%lx, "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "kgbase=%lx\n", (void *)cpup->wc_gdt_base,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpup->wc_gdt_limit, (void *)cpup->wc_idt_base,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpup->wc_idt_limit, (long)cpup->wc_ldt,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_tr, (long)cpup->wc_kgsbase))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf gdt.base = cpup->wc_gdt_base;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf gdt.limit = cpup->wc_gdt_limit;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf code_length = (uint32_t)wc_long_mode_64 -
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (uint32_t)wc_rm_start;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#else
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf code_length = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf init_real_mode_platter(0, code_length, cpup->wc_cr4, gdt);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_cr4=%lx, getcr4()=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)wcpp->rm_cr4, getcr4()))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_pdbr=%lx, getcr3()=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)wcpp->rm_pdbr, getcr3()))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("real_mode_platter->rm_longmode64_addr=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)wcpp->rm_longmode64_addr))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ("real_mode_platter->rm_temp_gdt[TEMPGDT_KCODE64]=%lx\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (ulong_t)wcpp->rm_temp_gdt[TEMPGDT_KCODE64]))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("gdt=%p:%x, idt=%p:%x, ldt=%lx, tr=%lx, "
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "kgsbase=%lx\n", (void *)wcpp->rm_gdt_base,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wcpp->rm_gdt_lim, (void *)wcpp->rm_idt_base,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wcpp->rm_idt_lim, (long)cpup->wc_ldt, (long)cpup->wc_tr,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (long)cpup->wc_kgsbase))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf power_req.request_type = PMR_PPM_ENTER_SX;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf power_req.req.ppm_power_enter_sx_req.sx_state = S3;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf power_req.req.ppm_power_enter_sx_req.test_point =
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpr_test_point;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf power_req.req.ppm_power_enter_sx_req.wakephys = wakephys;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s: pm_ctlops PMR_PPM_ENTER_SX\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_PPMCTLOP);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) pm_ctlops(ppm, ddi_root_node(), DDI_CTLOPS_POWER,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &power_req, &ret);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s: returns %d\n", str, ret))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * If it works, we get control back to the else branch below
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * If we get control back here, it didn't work.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * XXX return EINVAL here?
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf unmap_wakeaddr_1to1(wakephys);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf intr_restore(saved_intr);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ret);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf } else {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpr_suspend_succeeded = 1;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf power_req.request_type = PMR_PPM_EXIT_SX;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf power_req.req.ppm_power_enter_sx_req.sx_state = S3;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s: pm_ctlops PMR_PPM_EXIT_SX\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_PPMCTLOP);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) pm_ctlops(ppm, ddi_root_node(), DDI_CTLOPS_POWER,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf &power_req, &ret);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s: returns %d\n", str, ret))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ret = i_cpr_restore_apic(&(wc_other_cpus->wc_apic_state));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * the restore should never fail, if the saved suceeded
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(ret == 0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf i_cpr_platform_free(&(wc_other_cpus->wc_apic_state));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler /*
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler * Enable interrupts on boot cpu.
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler */
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler ASSERT(CPU->cpu_id == i_cpr_bootcpuid());
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler mutex_enter(&cpu_lock);
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler cpu_enable_intr(CPU);
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler mutex_exit(&cpu_lock);
643e2e74e1c00e6b3d1896a6a67dbdb7308135c3bholler
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_INTRRESTORE);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf intr_restore(saved_intr);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PT(PT_CPU);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (ret);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Stop all other cpu's before halting or rebooting. We pause the cpu's
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * instead of sending a cross call.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Stolen from sun4/os/mp_states.c
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int cpu_are_paused; /* sic */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_stop_other_cpus(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (cpu_are_paused) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf pause_cpus(NULL);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cpu_are_paused = 1;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfint
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_is_supported(int sleeptype)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern int cpr_supported_override;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern int cpr_platform_enable;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern int pm_S3_enabled;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (sleeptype != CPR_TORAM)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * The next statement tests if a specific platform has turned off
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * cpr support.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (cpr_supported_override)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * If a platform has specifically turned on cpr support ...
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (cpr_platform_enable)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (1);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (pm_S3_enabled);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_bitmap_cleanup(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_free_memory_resources(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Needed only for S3 so far
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_platform_alloc(psm_state_request_t *req)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_platform_alloc";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("cpu = %d, %s(%p) \n", CPU->cpu_id, str, (void *)req))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ncpus == 1) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf req->psr_cmd = PSM_STATE_ALLOC;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return ((*psm_state)(req));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Needed only for S3 so far
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_platform_free(psm_state_request_t *req)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_platform_free";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("cpu = %d, %s(%p) \n", CPU->cpu_id, str, (void *)req))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ncpus == 1) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf req->psr_cmd = PSM_STATE_FREE;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) (*psm_state)(req);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_save_apic(psm_state_request_t *req)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_save_apic";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ncpus == 1) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf req->psr_cmd = PSM_STATE_SAVE;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return ((*psm_state)(req));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic int
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_restore_apic(psm_state_request_t *req)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_restore_apic";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (ncpus == 1) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() : ncpus == 1\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return (0);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf req->psr_cmd = PSM_STATE_RESTORE;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return ((*psm_state)(req));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/* stop lint complaining about offset not being used in 32bit mode */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if !defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*ARGSUSED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfinit_real_mode_platter(int cpun, uint32_t offset, uint_t cr4, wc_desctbr_t gdt)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf rm_platter_t *real_mode_platter = (rm_platter_t *)rm_platter_va;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Fill up the real mode platter to make it easy for real mode code to
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * kick it off. This area should really be one passed by boot to kernel
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * and guaranteed to be below 1MB and aligned to 16 bytes. Should also
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * have identical physical and virtual address in paged mode.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_pdbr = getcr3();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_cpu = cpun;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_cr4 = cr4;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_gdt_base = gdt.base;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_gdt_lim = gdt.limit;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_x86feature = x86_feature;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (getcr3() > 0xffffffffUL)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf panic("Cannot initialize CPUs; kernel's 64-bit page tables\n"
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf "located above 4G in physical memory (@ 0x%llx).",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (unsigned long long)getcr3());
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Setup pseudo-descriptors for temporary GDT and IDT for use ONLY
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * by code in real_mode_start():
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * GDT[0]: NULL selector
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * GDT[1]: 64-bit CS: Long = 1, Present = 1, bits 12, 11 = 1
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf *
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Clear the IDT as interrupts will be off and a limit of 0 will cause
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * the CPU to triple fault and reset on an NMI, seemingly as reasonable
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * a course of action as any other, though it may cause the entire
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * platform to reset in some cases...
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_temp_gdt[0] = 0ULL;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_temp_gdt[TEMPGDT_KCODE64] = 0x20980000000000ULL;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_temp_gdt_lim = (ushort_t)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (sizeof (real_mode_platter->rm_temp_gdt) - 1);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_temp_gdt_base = rm_platter_pa +
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (uint32_t)(&((rm_platter_t *)0)->rm_temp_gdt);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_temp_idt_lim = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_temp_idt_base = 0;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Since the CPU needs to jump to protected mode using an identity
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * mapped address, we need to calculate it here.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf real_mode_platter->rm_longmode64_addr = rm_platter_pa + offset;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif /* __amd64 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* return; */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_start_cpu(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf struct cpu *cp = CPU;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_start_cpu";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf extern void init_cpu_syscall(struct cpu *cp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_cpu_t *cpup = wc_other_cpus + cp->cpu_id;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif /* __amd64 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() called\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() #0 cp->cpu_base_spl %d\n", str,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cp->cpu_base_spl))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (cp == i_cpr_bootcpu()) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ("%s() called on bootcpu nothing to do!\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf return;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * We need to Sync PAT with cpu0's PAT. We have to do
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * this with interrupts disabled.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (x86_feature & X86_PAT)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf pat_sync();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Initialize this CPU's syscall handlers
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf init_cpu_syscall(cp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() #1 cp->cpu_base_spl %d\n", str, cp->cpu_base_spl))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Do not need to call cpuid_pass2(), cpuid_pass3(), cpuid_pass4() or
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * init_cpu_info(), since the work that they do is only needed to
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * be done once at boot time
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_enter(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf restore_stack(cpup);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif /* __amd64 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf CPUSET_ADD(procset, cp->cpu_id);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf mutex_exit(&cpu_lock);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() #2 cp->cpu_base_spl %d\n", str,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cp->cpu_base_spl))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (tsc_gethrtime_enable) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() calling tsc_sync_slave\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf tsc_sync_slave();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() cp->cpu_id %d, cp->cpu_intr_actv %d\n", str,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cp->cpu_id, cp->cpu_intr_actv))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() #3 cp->cpu_base_spl %d\n", str,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cp->cpu_base_spl))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void) spl0(); /* enable interrupts */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() #4 cp->cpu_base_spl %d\n", str,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cp->cpu_base_spl))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * Set up the CPU module for this CPU. This can't be done before
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * this CPU is made CPU_READY, because we may (in heterogeneous systems)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * need to go load another CPU module. The act of attempting to load
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * a module may trigger a cross-call, which will ASSERT unless this
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * cpu is CPU_READY.
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * cmi already been init'd (during boot), so do not need to do it again
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#ifdef PM_REINITMCAONRESUME
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (x86_feature & X86_MCA)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf cmi_mca_init();
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() returning\n", str))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /* return; */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#if defined(__amd64)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * we only need to do this for amd64!
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * save the stack
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfsave_stack(wc_cpu_t *cpup)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "save_stack";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf caddr_t base = curthread->t_stk;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf caddr_t sp = (caddr_t)cpup->wc_rsp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() CPU->cpu_id %d\n", str, CPU->cpu_id))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("save_stack() curthread->t_stk = %p, sp = %p\n",
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void *)base, (void *)sp))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(base > sp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf bcopy(sp, cpup->wc_stack, base - sp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * restore the stack
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfstatic void
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfrestore_stack(wc_cpu_t *cpup)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * we only need to do this for amd64!
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "restore_stack";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf caddr_t base = curthread->t_stk;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf caddr_t sp = (caddr_t)cpup->wc_rsp;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() CPU->cpu_id %d\n", str, CPU->cpu_id))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() curthread->t_stk = %p, sp = %p\n", str,
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf (void *)base, (void *)sp))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf ASSERT(base > sp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*LINTED*/
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf bcopy(cpup->wc_stack, sp, base - sp);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf#endif /* __amd64 */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_alloc_cpus(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf char *str = "i_cpr_alloc_cpus";
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf PMD(PMD_SX, ("%s() CPU->cpu_id %d\n", str, CPU->cpu_id))
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf /*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * we allocate this only when we actually need it to save on
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * kernel memory
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (wc_other_cpus == NULL) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_other_cpus = kmem_zalloc(ncpus * sizeof (wc_cpu_t),
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf KM_SLEEP);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_free_cpus(void)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf if (wc_other_cpus != NULL) {
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf kmem_free((void *) wc_other_cpus, ncpus * sizeof (wc_cpu_t));
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf wc_other_cpus = NULL;
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf }
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * wrapper for acpica_ddi_save_resources()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_save_configuration(dev_info_t *dip)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf acpica_ddi_save_resources(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf/*
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf * wrapper for acpica_ddi_restore_resources()
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf */
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfvoid
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyfi_cpr_restore_configuration(dev_info_t *dip)
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf{
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf acpica_ddi_restore_resources(dip);
2df1fe9ca32bb227b9158c67f5c00b54c20b10fdrandyf}
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan
4716fd887b81cd876928e6c03a0c6d0dcf362c90janstatic int
4716fd887b81cd876928e6c03a0c6d0dcf362c90janwait_for_set(cpuset_t *set, int who)
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan{
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan int delays;
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan char *str = "wait_for_set";
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan for (delays = 0; !CPU_IN_SET(*set, who); delays++) {
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan if (delays == 500) {
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan /*
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan * After five seconds, things are probably
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan * looking a bit bleak - explain the hang.
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan */
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan cmn_err(CE_NOTE, "cpu%d: started, "
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan "but not running in the kernel yet", who);
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan PMD(PMD_SX, ("%s() %d cpu started "
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan "but not running in the kernel yet\n",
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan str, who))
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan } else if (delays > 2000) {
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan /*
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan * We waited at least 20 seconds, bail ..
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan */
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan cmn_err(CE_WARN, "cpu%d: timed out", who);
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan PMD(PMD_SX, ("%s() %d cpu timed out\n",
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan str, who))
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan return (0);
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan }
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan /*
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan * wait at least 10ms, then check again..
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan */
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan drv_usecwait(10000);
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan }
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan return (1);
4716fd887b81cd876928e6c03a0c6d0dcf362c90jan}