svn commit: r210509 - in stable/8/sys: amd64/acpica amd64/amd64
amd64/include i386/acpica i386/i386 i386/include
John Baldwin
jhb at FreeBSD.org
Mon Jul 26 18:22:46 UTC 2010
Author: jhb
Date: Mon Jul 26 18:22:46 2010
New Revision: 210509
URL: http://svn.freebsd.org/changeset/base/210509
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/8/sys/amd64/acpica/acpi_wakeup.c
stable/8/sys/amd64/amd64/mca.c
stable/8/sys/amd64/amd64/mp_machdep.c
stable/8/sys/amd64/include/mca.h
stable/8/sys/i386/acpica/acpi_wakeup.c
stable/8/sys/i386/i386/mca.c
stable/8/sys/i386/include/mca.h
Directory Properties:
stable/8/sys/ (props changed)
stable/8/sys/amd64/include/xen/ (props changed)
stable/8/sys/cddl/contrib/opensolaris/ (props changed)
stable/8/sys/contrib/dev/acpica/ (props changed)
stable/8/sys/contrib/pf/ (props changed)
stable/8/sys/dev/xen/xenpci/ (props changed)
Modified: stable/8/sys/amd64/acpica/acpi_wakeup.c
==============================================================================
--- stable/8/sys/amd64/acpica/acpi_wakeup.c Mon Jul 26 18:07:43 2010 (r210508)
+++ stable/8/sys/amd64/acpica/acpi_wakeup.c Mon Jul 26 18:22:46 2010 (r210509)
@@ -43,6 +43,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>
@@ -306,6 +307,7 @@ out:
#endif
load_cr3(cr3);
+ mca_resume();
intr_resume();
intr_restore(rf);
Modified: stable/8/sys/amd64/amd64/mca.c
==============================================================================
--- stable/8/sys/amd64/amd64/mca.c Mon Jul 26 18:07:43 2010 (r210508)
+++ stable/8/sys/amd64/amd64/mca.c Mon Jul 26 18:22:46 2010 (r210509)
@@ -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/8/sys/amd64/amd64/mp_machdep.c
==============================================================================
--- stable/8/sys/amd64/amd64/mp_machdep.c Mon Jul 26 18:07:43 2010 (r210508)
+++ stable/8/sys/amd64/amd64/mp_machdep.c Mon Jul 26 18:22:46 2010 (r210509)
@@ -1273,6 +1273,7 @@ cpususpend_handler(void)
/* Restore CR3 and enable interrupts */
load_cr3(cr3);
+ mca_resume();
lapic_setup(0);
intr_restore(rf);
}
Modified: stable/8/sys/amd64/include/mca.h
==============================================================================
--- stable/8/sys/amd64/include/mca.h Mon Jul 26 18:07:43 2010 (r210508)
+++ stable/8/sys/amd64/include/mca.h Mon Jul 26 18:22:46 2010 (r210509)
@@ -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/8/sys/i386/acpica/acpi_wakeup.c
==============================================================================
--- stable/8/sys/i386/acpica/acpi_wakeup.c Mon Jul 26 18:07:43 2010 (r210508)
+++ stable/8/sys/i386/acpica/acpi_wakeup.c Mon Jul 26 18:22:46 2010 (r210509)
@@ -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: stable/8/sys/i386/i386/mca.c
==============================================================================
--- stable/8/sys/i386/i386/mca.c Mon Jul 26 18:07:43 2010 (r210508)
+++ stable/8/sys/i386/i386/mca.c Mon Jul 26 18:22:46 2010 (r210509)
@@ -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/8/sys/i386/include/mca.h
==============================================================================
--- stable/8/sys/i386/include/mca.h Mon Jul 26 18:07:43 2010 (r210508)
+++ stable/8/sys/i386/include/mca.h Mon Jul 26 18:22:46 2010 (r210509)
@@ -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-all
mailing list