summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
authorjan <none@none>2008-01-11 15:02:18 -0800
committerjan <none@none>2008-01-11 15:02:18 -0800
commit4716fd887b81cd876928e6c03a0c6d0dcf362c90 (patch)
tree61c7c26ec45deb9bc5e413f98e8030ed21c740fc /usr/src/uts
parent997ec7102007efcf2514c6f8c2c3d50946239970 (diff)
downloadillumos-gate-4716fd887b81cd876928e6c03a0c6d0dcf362c90.tar.gz
6395227 Need to support s3 on MP machines
6621792 nv_sata doesn't resume on MP ultra 40 system 6631154 cpr_wakecode.s has unguarded amd specific MSRs 6631159 cpr_wakecode.s will call APIC initialization, even if no APIC, or APIC disabled
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/common/cpr/cpr_main.c31
-rw-r--r--usr/src/uts/common/cpr/cpr_mod.c11
-rw-r--r--usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c32
-rw-r--r--usr/src/uts/i86pc/ml/cpr_wakecode.s33
-rw-r--r--usr/src/uts/i86pc/os/cpr_impl.c104
5 files changed, 118 insertions, 93 deletions
diff --git a/usr/src/uts/common/cpr/cpr_main.c b/usr/src/uts/common/cpr/cpr_main.c
index 96b1d29534..22e1b702f7 100644
--- a/usr/src/uts/common/cpr/cpr_main.c
+++ b/usr/src/uts/common/cpr/cpr_main.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -380,21 +380,15 @@ cpr_lock_mgr(void (*service)(void))
int
cpr_suspend_cpus(void)
{
- cpu_t *bootcpu;
int ret = 0;
extern void *i_cpr_save_context(void *arg);
mutex_enter(&cpu_lock);
/*
- * if bootcpu is offline bring it back online
- */
- bootcpu = i_cpr_bootcpu();
-
- /*
* the machine could not have booted without a bootcpu
*/
- ASSERT(bootcpu != NULL);
+ ASSERT(i_cpr_bootcpu() != NULL);
/*
* bring all the offline cpus online
@@ -789,11 +783,6 @@ cpr_resume_cpus(void)
start_cpus();
mutex_exit(&cpu_lock);
- /*
- * clear the affinity set in cpr_suspend_cpus()
- */
- affinity_clear();
-
i_cpr_post_resume_cpus();
mutex_enter(&cpu_lock);
@@ -804,14 +793,14 @@ cpr_resume_cpus(void)
cpu_pause_func = NULL;
/*
- * offline all the cpus that were brought online during suspend
+ * clear the affinity set in cpr_suspend_cpus()
*/
- cpr_restore_offline();
+ affinity_clear();
/*
- * clear the affinity set in cpr_suspend_cpus()
+ * offline all the cpus that were brought online during suspend
*/
- affinity_clear();
+ cpr_restore_offline();
mutex_exit(&cpu_lock);
}
@@ -839,14 +828,14 @@ cpr_unpause_cpus(void)
start_cpus();
/*
- * offline all the cpus that were brought online during suspend
+ * clear the affinity set in cpr_suspend_cpus()
*/
- cpr_restore_offline();
+ affinity_clear();
/*
- * clear the affinity set in cpr_suspend_cpus()
+ * offline all the cpus that were brought online during suspend
*/
- affinity_clear();
+ cpr_restore_offline();
mutex_exit(&cpu_lock);
}
diff --git a/usr/src/uts/common/cpr/cpr_mod.c b/usr/src/uts/common/cpr/cpr_mod.c
index 0799bca9f1..008cf5d73c 100644
--- a/usr/src/uts/common/cpr/cpr_mod.c
+++ b/usr/src/uts/common/cpr/cpr_mod.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -190,14 +190,7 @@ cpr(int fcn, void *mdep)
case AD_LOOPBACK_SUSPEND_TO_RAM_FAIL:
case AD_FORCE_SUSPEND_TO_RAM:
case AD_DEVICE_SUSPEND_TO_RAM:
- /*
- * if MP then do not support suspend to RAM, however override
- * the MP restriction if cpr_mp_enable has been set
- */
- if (ncpus > 1 && cpr_mp_enable == 0)
- return (ENOTSUP);
- else
- cpr_sleeptype = CPR_TORAM;
+ cpr_sleeptype = CPR_TORAM;
break;
#endif
}
diff --git a/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c b/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c
index f6d5870c5c..65c7af2fb5 100644
--- a/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c
+++ b/usr/src/uts/common/io/sata/adapters/nv_sata/nv_sata.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -406,6 +406,7 @@ nv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
ddi_acc_handle_t pci_conf_handle;
nv_ctl_t *nvc;
uint8_t subclass;
+ uint32_t reg32;
switch (cmd) {
@@ -600,12 +601,41 @@ nv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
NVLOG((NVDBG_INIT, nvc, NULL,
"nv_attach(): DDI_RESUME inst %d", inst));
+ if (pci_config_setup(dip, &pci_conf_handle) != DDI_SUCCESS) {
+ return (DDI_FAILURE);
+ }
+
+ /*
+ * If a device is attached after a suspend/resume, sometimes
+ * the command register is zero, as it might not be set by
+ * BIOS or a parent. Set it again here.
+ */
+ command = pci_config_get16(pci_conf_handle, PCI_CONF_COMM);
+
+ if (command == 0) {
+ pci_config_put16(pci_conf_handle, PCI_CONF_COMM,
+ PCI_COMM_IO|PCI_COMM_MAE|PCI_COMM_ME);
+ }
+
+ /*
+ * Need to set bit 2 to 1 at config offset 0x50
+ * to enable access to the bar5 registers.
+ */
+ reg32 = pci_config_get32(pci_conf_handle, NV_SATA_CFG_20);
+
+ if ((reg32 & NV_BAR5_SPACE_EN) != NV_BAR5_SPACE_EN) {
+ pci_config_put32(pci_conf_handle, NV_SATA_CFG_20,
+ reg32 | NV_BAR5_SPACE_EN);
+ }
+
nvc->nvc_state &= ~NV_CTRL_SUSPEND;
for (i = 0; i < NV_MAX_PORTS(nvc); i++) {
nv_resume(&(nvc->nvc_port[i]));
}
+ pci_config_teardown(&pci_conf_handle);
+
return (DDI_SUCCESS);
default:
diff --git a/usr/src/uts/i86pc/ml/cpr_wakecode.s b/usr/src/uts/i86pc/ml/cpr_wakecode.s
index 93dffd9c51..32baeaeb39 100644
--- a/usr/src/uts/i86pc/ml/cpr_wakecode.s
+++ b/usr/src/uts/i86pc/ml/cpr_wakecode.s
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -282,8 +282,8 @@ wc_rm_end(void)
/ using the following value blows up machines! - DO NOT USE
/ D16 movl 0xffc, %esp
-#define LED 1
-#define SERIAL 1
+#define LED 0
+#define SERIAL 0
#if LED
D16 movl $0x80, %edx
@@ -717,7 +717,13 @@ kernel_wc_code:
pushq $0 /* null frame pointer terminates stack trace */
movq %rsp, %rbp /* stack aligned on 16-byte boundary */
- call *ap_mlsetup
+ /*
+ * skip iff function pointer is NULL
+ */
+ cmpq $0, ap_mlsetup
+ je 2f
+ call *ap_mlsetup
+2:
call *cpr_start_cpu_func
@@ -976,10 +982,18 @@ kernel_wc_code:
movb $0xdc, %al
outb $0x80
- movl $MSR_AMD_EFER, %ecx / re-enable NX bit
+ /*
+ * Before proceeding, enable usage of the page table NX bit if
+ * that's how the page tables are set up.
+ */
+ movl x86_feature, %ecx
+ andl $X86_NX, %ecx
+ jz 1f
+ movl $MSR_AMD_EFER, %ecx
rdmsr
- orl $AMD_EFER_NXE, %eax
+ orl $AMD_EFER_NXE, %eax
wrmsr
+1:
movl WC_CR4(%ebx), %eax / restore full cr4 (with Global Enable)
movl %eax, %cr4
@@ -1003,9 +1017,12 @@ kernel_wc_code:
movw WC_GS(%ebx), %gs
/*
- * APIC initialization
+ * APIC initialization, skip iff function pointer is NULL
*/
- call *ap_mlsetup
+ cmpl $0, ap_mlsetup
+ je 2f
+ call *ap_mlsetup
+2:
call *cpr_start_cpu_func
diff --git a/usr/src/uts/i86pc/os/cpr_impl.c b/usr/src/uts/i86pc/os/cpr_impl.c
index 939df37716..a32b18511f 100644
--- a/usr/src/uts/i86pc/os/cpr_impl.c
+++ b/usr/src/uts/i86pc/os/cpr_impl.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -93,6 +93,7 @@ static int i_cpr_platform_alloc(psm_state_request_t *req);
static void i_cpr_platform_free(psm_state_request_t *req);
static int i_cpr_save_apic(psm_state_request_t *req);
static int i_cpr_restore_apic(psm_state_request_t *req);
+static int wait_for_set(cpuset_t *set, int who);
#if defined(__amd64)
static void restore_stack(wc_cpu_t *cpup);
@@ -260,8 +261,7 @@ i_cpr_pre_resume_cpus()
* just do the initialization to wake the other cpus
*/
unsigned who;
- int cpuid = i_cpr_bootcpuid();
- int started_cpu;
+ int boot_cpuid = i_cpr_bootcpuid();
uint32_t code_length = 0;
caddr_t wakevirt = rm_platter_va;
/*LINTED*/
@@ -292,14 +292,17 @@ i_cpr_pre_resume_cpus()
affinity_set(CPU_CURRENT);
- cpu_ready_set = 0;
+ /*
+ * mark the boot cpu as being ready, since we are running on that cpu
+ */
+ CPUSET_ONLY(cpu_ready_set, boot_cpuid);
for (who = 0; who < ncpus; who++) {
wc_cpu_t *cpup = wc_other_cpus + who;
wc_desctbr_t gdt;
- if (who == cpuid)
+ if (who == boot_cpuid)
continue;
if (!CPU_IN_SET(mp_cpus, who))
@@ -320,8 +323,6 @@ i_cpr_pre_resume_cpus()
init_real_mode_platter(who, code_length, cpup->wc_cr4, gdt);
- started_cpu = 1;
-
if ((err = mach_cpuid_start(who, rm_platter_va)) != 0) {
cmn_err(CE_WARN, "cpu%d: failed to start during "
"suspend/resume error %d", who, err);
@@ -331,57 +332,18 @@ i_cpr_pre_resume_cpus()
PMD(PMD_SX, ("%s() #1 waiting for procset 0x%lx\n", str,
(ulong_t)procset))
-/*
- * This conditional compile only affects the MP case.
- */
-#ifdef MP_PM
- for (delays = 0; !CPU_IN_SET(procset, who); delays++) {
- if (delays == 500) {
- /*
- * After five seconds, things are probably
- * looking a bit bleak - explain the hang.
- */
- cmn_err(CE_NOTE, "cpu%d: started, "
- "but not running in the kernel yet", who);
- PMD(PMD_SX, ("%s() %d cpu started "
- "but not running in the kernel yet\n",
- str, who))
- } else if (delays > 2000) {
- /*
- * We waited at least 20 seconds, bail ..
- */
- cmn_err(CE_WARN, "cpu%d: timed out", who);
- PMD(PMD_SX, ("%s() %d cpu timed out\n",
- str, who))
- started_cpu = 0;
- }
-
- /*
- * wait at least 10ms, then check again..
- */
- delay(USEC_TO_TICK_ROUNDUP(10000));
- }
-#else
- while (!CPU_IN_SET(procset, who)) {
- ;
- }
-
-#endif /* MP_PM */
+ if (!wait_for_set(&procset, who))
+ continue;
PMD(PMD_SX, ("%s() %d cpu started\n", str, who))
- if (!started_cpu)
- continue;
-
- PMD(PMD_SX, ("%s() tsc_ready = %d\n", str,
- get_tsc_ready()))
+ PMD(PMD_SX, ("%s() tsc_ready = %d\n", str, get_tsc_ready()))
if (tsc_gethrtime_enable) {
PMD(PMD_SX, ("%s() calling tsc_sync_master\n", str))
tsc_sync_master(who);
}
-
PMD(PMD_SX, ("%s() waiting for cpu_ready_set %ld\n", str,
cpu_ready_set))
/*
@@ -389,11 +351,8 @@ i_cpr_pre_resume_cpus()
* cpus to start serially instead of in parallel, so that
* they do not contend with each other in wc_rm_start()
*/
- while (!CPU_IN_SET(cpu_ready_set, who)) {
- PMD(PMD_SX, ("%s() waiting for "
- "cpu_ready_set %ld\n", str, cpu_ready_set))
- ;
- }
+ if (!wait_for_set(&cpu_ready_set, who))
+ continue;
/*
* do not need to re-initialize dtrace using dtrace_cpu_init
@@ -405,6 +364,7 @@ i_cpr_pre_resume_cpus()
affinity_clear();
PMD(PMD_SX, ("%s() all cpus now ready\n", str))
+
}
static void
@@ -1094,3 +1054,39 @@ i_cpr_restore_configuration(dev_info_t *dip)
{
acpica_ddi_restore_resources(dip);
}
+
+static int
+wait_for_set(cpuset_t *set, int who)
+{
+ int delays;
+ char *str = "wait_for_set";
+
+ for (delays = 0; !CPU_IN_SET(*set, who); delays++) {
+ if (delays == 500) {
+ /*
+ * After five seconds, things are probably
+ * looking a bit bleak - explain the hang.
+ */
+ cmn_err(CE_NOTE, "cpu%d: started, "
+ "but not running in the kernel yet", who);
+ PMD(PMD_SX, ("%s() %d cpu started "
+ "but not running in the kernel yet\n",
+ str, who))
+ } else if (delays > 2000) {
+ /*
+ * We waited at least 20 seconds, bail ..
+ */
+ cmn_err(CE_WARN, "cpu%d: timed out", who);
+ PMD(PMD_SX, ("%s() %d cpu timed out\n",
+ str, who))
+ return (0);
+ }
+
+ /*
+ * wait at least 10ms, then check again..
+ */
+ drv_usecwait(10000);
+ }
+
+ return (1);
+}