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>