svn commit: r210510 - in stable/7/sys: amd64/amd64 amd64/include i386/acpica i386/i386 i386/include

John Baldwin jhb at FreeBSD.org
Mon Jul 26 18:23:06 UTC 2010


Author: jhb
Date: Mon Jul 26 18:23:05 2010
New Revision: 210510
URL: http://svn.freebsd.org/changeset/base/210510

Log:
  MFC 209212:
  Restore the machine check register banks on resume.  For banks being
  monitored via CMCI, reset the interrupt threshold to 1 on resume.

Modified:
  stable/7/sys/amd64/amd64/mca.c
  stable/7/sys/amd64/include/mca.h
  stable/7/sys/i386/acpica/acpi_wakeup.c
  stable/7/sys/i386/i386/mca.c
  stable/7/sys/i386/include/mca.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/amd64/amd64/mca.c
==============================================================================
--- stable/7/sys/amd64/amd64/mca.c	Mon Jul 26 18:22:46 2010	(r210509)
+++ stable/7/sys/amd64/amd64/mca.c	Mon Jul 26 18:23:05 2010	(r210510)
@@ -642,6 +642,15 @@ static void
 mca_setup(uint64_t mcg_cap)
 {
 
+	/*
+	 * On AMD Family 10h processors, unless logging of level one TLB
+	 * parity (L1TP) errors is disabled, enable the recommended workaround
+	 * for Erratum 383.
+	 */
+	if (cpu_vendor_id == CPU_VENDOR_AMD &&
+	    CPUID_TO_FAMILY(cpu_id) == 0x10 && amd10h_L1TP)
+		workaround_erratum383 = 1;
+
 	mtx_init(&mca_lock, "mca", NULL, MTX_SPIN);
 	STAILQ_INIT(&mca_records);
 	TASK_INIT(&mca_task, 0x8000, mca_scan_cpus, NULL);
@@ -708,36 +717,54 @@ cmci_monitor(int i)
 	PCPU_SET(cmci_mask, PCPU_GET(cmci_mask) | 1 << i);
 }
 
-/* Must be executed on each CPU. */
-void
-mca_init(void)
+/*
+ * For resume, reset the threshold for any banks we monitor back to
+ * one and throw away the timestamp of the last interrupt.
+ */
+static void
+cmci_resume(int i)
+{
+	struct cmc_state *cc;
+	uint64_t ctl;
+
+	KASSERT(i < cmc_banks, ("CPU %d has more MC banks", PCPU_GET(cpuid)));
+
+	/* Ignore banks not monitored by this CPU. */
+	if (!(PCPU_GET(cmci_mask) & 1 << i))
+		return;
+
+	cc = &cmc_state[PCPU_GET(cpuid)][i];
+	cc->last_intr = -ticks;
+	ctl = rdmsr(MSR_MC_CTL2(i));
+	ctl &= ~MC_CTL2_THRESHOLD;
+	ctl |= MC_CTL2_CMCI_EN | 1;
+	wrmsr(MSR_MC_CTL2(i), ctl);
+}
+
+/*
+ * Initializes per-CPU machine check registers and enables corrected
+ * machine check interrupts.
+ */
+static void
+_mca_init(int boot)
 {
 	uint64_t mcg_cap;
 	uint64_t ctl, mask;
-	int skip;
-	int i;
+	int i, skip;
 
 	/* MCE is required. */
 	if (!mca_enabled || !(cpu_feature & CPUID_MCE))
 		return;
 
-	/*
-	 * On AMD Family 10h processors, unless logging of level one TLB
-	 * parity (L1TP) errors is disabled, enable the recommended workaround
-	 * for Erratum 383.
-	 */
-	if (cpu_vendor_id == CPU_VENDOR_AMD &&
-	    CPUID_TO_FAMILY(cpu_id) == 0x10 && amd10h_L1TP)
-		workaround_erratum383 = 1;
-
 	if (cpu_feature & CPUID_MCA) {
-		PCPU_SET(cmci_mask, 0);
+		if (boot)
+			PCPU_SET(cmci_mask, 0);
 
 		mcg_cap = rdmsr(MSR_MCG_CAP);
 		if (mcg_cap & MCG_CAP_CTL_P)
 			/* Enable MCA features. */
 			wrmsr(MSR_MCG_CTL, MCG_CTL_ENABLE);
-		if (PCPU_GET(cpuid) == 0)
+		if (PCPU_GET(cpuid) == 0 && boot)
 			mca_setup(mcg_cap);
 
 		/*
@@ -775,20 +802,40 @@ mca_init(void)
 			if (!skip)
 				wrmsr(MSR_MC_CTL(i), ctl);
 
-			if (mcg_cap & MCG_CAP_CMCI_P)
-				cmci_monitor(i);
+			if (mcg_cap & MCG_CAP_CMCI_P) {
+				if (boot)
+					cmci_monitor(i);
+				else
+					cmci_resume(i);
+			}
 
 			/* Clear all errors. */
 			wrmsr(MSR_MC_STATUS(i), 0);
 		}
 
-		if (PCPU_GET(cmci_mask) != 0)
+		if (PCPU_GET(cmci_mask) != 0 && boot)
 			lapic_enable_cmc();
 	}
 
 	load_cr4(rcr4() | CR4_MCE);
 }
 
+/* Must be executed on each CPU during boot. */
+void
+mca_init(void)
+{
+
+	_mca_init(1);
+}
+
+/* Must be executed on each CPU during resume. */
+void
+mca_resume(void)
+{
+
+	_mca_init(0);
+}
+
 /*
  * The machine check registers for the BSP cannot be initialized until
  * the local APIC is initialized.  This happens at SI_SUB_CPU,

Modified: stable/7/sys/amd64/include/mca.h
==============================================================================
--- stable/7/sys/amd64/include/mca.h	Mon Jul 26 18:22:46 2010	(r210509)
+++ stable/7/sys/amd64/include/mca.h	Mon Jul 26 18:23:05 2010	(r210510)
@@ -49,6 +49,7 @@ struct mca_record {
 void	cmc_intr(void);
 void	mca_init(void);
 int	mca_intr(void);
+void	mca_resume(void);
 
 #endif
 

Modified: stable/7/sys/i386/acpica/acpi_wakeup.c
==============================================================================
--- stable/7/sys/i386/acpica/acpi_wakeup.c	Mon Jul 26 18:22:46 2010	(r210509)
+++ stable/7/sys/i386/acpica/acpi_wakeup.c	Mon Jul 26 18:23:05 2010	(r210510)
@@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include <machine/bus.h>
 #include <machine/cpufunc.h>
 #include <machine/intr_machdep.h>
+#include <machine/mca.h>
 #include <machine/segments.h>
 
 #include <contrib/dev/acpica/acpi.h>
@@ -270,6 +271,7 @@ acpi_sleep_machdep(struct acpi_softc *sc
 		for (;;) ;
 	} else {
 		/* Execute Wakeup */
+		mca_resume();
 		intr_resume();
 
 		if (bootverbose) {

Modified: stable/7/sys/i386/i386/mca.c
==============================================================================
--- stable/7/sys/i386/i386/mca.c	Mon Jul 26 18:22:46 2010	(r210509)
+++ stable/7/sys/i386/i386/mca.c	Mon Jul 26 18:23:05 2010	(r210510)
@@ -657,6 +657,15 @@ static void
 mca_setup(uint64_t mcg_cap)
 {
 
+	/*
+	 * On AMD Family 10h processors, unless logging of level one TLB
+	 * parity (L1TP) errors is disabled, enable the recommended workaround
+	 * for Erratum 383.
+	 */
+	if (cpu_vendor_id == CPU_VENDOR_AMD &&
+	    CPUID_TO_FAMILY(cpu_id) == 0x10 && amd10h_L1TP)
+		workaround_erratum383 = 1;
+
 	mtx_init(&mca_lock, "mca", NULL, MTX_SPIN);
 	STAILQ_INIT(&mca_records);
 	TASK_INIT(&mca_task, 0x8000, mca_scan_cpus, NULL);
@@ -725,38 +734,56 @@ cmci_monitor(int i)
 	/* Mark this bank as monitored. */
 	PCPU_SET(cmci_mask, PCPU_GET(cmci_mask) | 1 << i);
 }
+
+/*
+ * For resume, reset the threshold for any banks we monitor back to
+ * one and throw away the timestamp of the last interrupt.
+ */
+static void
+cmci_resume(int i)
+{
+	struct cmc_state *cc;
+	uint64_t ctl;
+
+	KASSERT(i < cmc_banks, ("CPU %d has more MC banks", PCPU_GET(cpuid)));
+
+	/* Ignore banks not monitored by this CPU. */
+	if (!(PCPU_GET(cmci_mask) & 1 << i))
+		return;
+
+	cc = &cmc_state[PCPU_GET(cpuid)][i];
+	cc->last_intr = -ticks;
+	ctl = rdmsr(MSR_MC_CTL2(i));
+	ctl &= ~MC_CTL2_THRESHOLD;
+	ctl |= MC_CTL2_CMCI_EN | 1;
+	wrmsr(MSR_MC_CTL2(i), ctl);
+}
 #endif
 
-/* Must be executed on each CPU. */
-void
-mca_init(void)
+/*
+ * Initializes per-CPU machine check registers and enables corrected
+ * machine check interrupts.
+ */
+static void
+_mca_init(int boot)
 {
 	uint64_t mcg_cap;
 	uint64_t ctl, mask;
-	int skip;
-	int i;
+	int i, skip;
 
 	/* MCE is required. */
 	if (!mca_enabled || !(cpu_feature & CPUID_MCE))
 		return;
 
-	/*
-	 * On AMD Family 10h processors, unless logging of level one TLB
-	 * parity (L1TP) errors is disabled, enable the recommended workaround
-	 * for Erratum 383.
-	 */
-	if (cpu_vendor_id == CPU_VENDOR_AMD &&
-	    CPUID_TO_FAMILY(cpu_id) == 0x10 && amd10h_L1TP)
-		workaround_erratum383 = 1;
-
 	if (cpu_feature & CPUID_MCA) {
-		PCPU_SET(cmci_mask, 0);
+		if (boot)
+			PCPU_SET(cmci_mask, 0);
 
 		mcg_cap = rdmsr(MSR_MCG_CAP);
 		if (mcg_cap & MCG_CAP_CTL_P)
 			/* Enable MCA features. */
 			wrmsr(MSR_MCG_CTL, MCG_CTL_ENABLE);
-		if (PCPU_GET(cpuid) == 0)
+		if (PCPU_GET(cpuid) == 0 && boot)
 			mca_setup(mcg_cap);
 
 		/*
@@ -795,8 +822,12 @@ mca_init(void)
 				wrmsr(MSR_MC_CTL(i), ctl);
 
 #ifdef DEV_APIC
-			if (mcg_cap & MCG_CAP_CMCI_P)
-				cmci_monitor(i);
+			if (mcg_cap & MCG_CAP_CMCI_P) {
+				if (boot)
+					cmci_monitor(i);
+				else
+					cmci_resume(i);
+			}
 #endif
 
 			/* Clear all errors. */
@@ -804,7 +835,7 @@ mca_init(void)
 		}
 
 #ifdef DEV_APIC
-		if (PCPU_GET(cmci_mask) != 0)
+		if (PCPU_GET(cmci_mask) != 0 && boot)
 			lapic_enable_cmc();
 #endif
 	}
@@ -812,6 +843,22 @@ mca_init(void)
 	load_cr4(rcr4() | CR4_MCE);
 }
 
+/* Must be executed on each CPU during boot. */
+void
+mca_init(void)
+{
+
+	_mca_init(1);
+}
+
+/* Must be executed on each CPU during resume. */
+void
+mca_resume(void)
+{
+
+	_mca_init(0);
+}
+
 /*
  * The machine check registers for the BSP cannot be initialized until
  * the local APIC is initialized.  This happens at SI_SUB_CPU,

Modified: stable/7/sys/i386/include/mca.h
==============================================================================
--- stable/7/sys/i386/include/mca.h	Mon Jul 26 18:22:46 2010	(r210509)
+++ stable/7/sys/i386/include/mca.h	Mon Jul 26 18:23:05 2010	(r210510)
@@ -49,6 +49,7 @@ struct mca_record {
 void	cmc_intr(void);
 void	mca_init(void);
 int	mca_intr(void);
+void	mca_resume(void);
 
 #endif
 


More information about the svn-src-stable-7 mailing list