Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Jun 2010 18:51:42 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r209212 - in head/sys: amd64/acpica amd64/amd64 amd64/include i386/acpica i386/include x86/x86
Message-ID:  <201006151851.o5FIpg3I064045@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Tue Jun 15 18:51:41 2010
New Revision: 209212
URL: http://svn.freebsd.org/changeset/base/209212

Log:
  Restore the machine check register banks on resume.  For banks being
  monitored via CMCI, reset the interrupt threshold to 1 on resume.
  
  Reviewed by:	jkim
  MFC after:	2 weeks

Modified:
  head/sys/amd64/acpica/acpi_wakeup.c
  head/sys/amd64/amd64/mp_machdep.c
  head/sys/amd64/include/mca.h
  head/sys/i386/acpica/acpi_wakeup.c
  head/sys/i386/include/mca.h
  head/sys/x86/x86/mca.c

Modified: head/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/amd64/acpica/acpi_wakeup.c	Tue Jun 15 18:37:31 2010	(r209211)
+++ head/sys/amd64/acpica/acpi_wakeup.c	Tue Jun 15 18:51:41 2010	(r209212)
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <vm/pmap.h>
 
 #include <machine/intr_machdep.h>
+#include <machine/mca.h>
 #include <machine/pcb.h>
 #include <machine/pmap.h>
 #include <machine/specialreg.h>
@@ -300,6 +301,7 @@ out:
 #endif
 
 	load_cr3(cr3);
+	mca_resume();
 	intr_resume();
 	intr_restore(rf);
 

Modified: head/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- head/sys/amd64/amd64/mp_machdep.c	Tue Jun 15 18:37:31 2010	(r209211)
+++ head/sys/amd64/amd64/mp_machdep.c	Tue Jun 15 18:51:41 2010	(r209212)
@@ -1264,6 +1264,7 @@ cpususpend_handler(void)
 
 	/* Restore CR3 and enable interrupts */
 	load_cr3(cr3);
+	mca_resume();
 	lapic_setup(0);
 	intr_restore(rf);
 }

Modified: head/sys/amd64/include/mca.h
==============================================================================
--- head/sys/amd64/include/mca.h	Tue Jun 15 18:37:31 2010	(r209211)
+++ head/sys/amd64/include/mca.h	Tue Jun 15 18:51:41 2010	(r209212)
@@ -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: head/sys/i386/acpica/acpi_wakeup.c
==============================================================================
--- head/sys/i386/acpica/acpi_wakeup.c	Tue Jun 15 18:37:31 2010	(r209211)
+++ head/sys/i386/acpica/acpi_wakeup.c	Tue Jun 15 18:51:41 2010	(r209212)
@@ -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/include/acpi.h>
@@ -272,6 +273,7 @@ acpi_sleep_machdep(struct acpi_softc *sc
 		for (;;) ;
 	} else {
 		/* Execute Wakeup */
+		mca_resume();
 		intr_resume();
 
 		if (bootverbose) {

Modified: head/sys/i386/include/mca.h
==============================================================================
--- head/sys/i386/include/mca.h	Tue Jun 15 18:37:31 2010	(r209211)
+++ head/sys/i386/include/mca.h	Tue Jun 15 18:51:41 2010	(r209212)
@@ -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: head/sys/x86/x86/mca.c
==============================================================================
--- head/sys/x86/x86/mca.c	Tue Jun 15 18:37:31 2010	(r209211)
+++ head/sys/x86/x86/mca.c	Tue Jun 15 18:51:41 2010	(r209212)
@@ -659,6 +659,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);
@@ -727,38 +736,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);
 
 		/*
@@ -797,8 +824,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. */
@@ -806,7 +837,7 @@ mca_init(void)
 		}
 
 #ifdef DEV_APIC
-		if (PCPU_GET(cmci_mask) != 0)
+		if (PCPU_GET(cmci_mask) != 0 && boot)
 			lapic_enable_cmc();
 #endif
 	}
@@ -814,6 +845,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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201006151851.o5FIpg3I064045>