svn commit: r245577 - in head/sys: amd64/amd64 i386/i386 x86/x86

John Baldwin jhb at FreeBSD.org
Thu Jan 17 21:32:26 UTC 2013


Author: jhb
Date: Thu Jan 17 21:32:25 2013
New Revision: 245577
URL: http://svnweb.freebsd.org/changeset/base/245577

Log:
  Don't attempt to use clflush on the local APIC register window.  Various
  CPUs exhibit bad behavior if this is done (Intel Errata AAJ3, hangs on
  Pentium-M, and trashing of the local APIC registers on a VIA C7).  The
  local APIC is implicitly mapped UC already via MTRRs, so the clflush isn't
  necessary anyway.
  
  MFC after:	2 weeks

Modified:
  head/sys/amd64/amd64/pmap.c
  head/sys/i386/i386/pmap.c
  head/sys/x86/x86/local_apic.c

Modified: head/sys/amd64/amd64/pmap.c
==============================================================================
--- head/sys/amd64/amd64/pmap.c	Thu Jan 17 21:32:03 2013	(r245576)
+++ head/sys/amd64/amd64/pmap.c	Thu Jan 17 21:32:25 2013	(r245577)
@@ -1150,6 +1150,15 @@ pmap_invalidate_cache_range(vm_offset_t 
 	    eva - sva < PMAP_CLFLUSH_THRESHOLD) {
 
 		/*
+		 * XXX: Some CPUs fault, hang, or trash the local APIC
+		 * registers if we use CLFLUSH on the local APIC
+		 * range.  The local APIC is always uncached, so we
+		 * don't need to flush for that range anyway.
+		 */
+		if (pmap_kextract(sva) == lapic_paddr)
+			return;
+
+		/*
 		 * Otherwise, do per-cache line flush.  Use the mfence
 		 * instruction to insure that previous stores are
 		 * included in the write-back.  The processor

Modified: head/sys/i386/i386/pmap.c
==============================================================================
--- head/sys/i386/i386/pmap.c	Thu Jan 17 21:32:03 2013	(r245576)
+++ head/sys/i386/i386/pmap.c	Thu Jan 17 21:32:25 2013	(r245577)
@@ -96,6 +96,7 @@ __FBSDID("$FreeBSD$");
  *	and to when physical maps must be made correct.
  */
 
+#include "opt_apic.h"
 #include "opt_cpu.h"
 #include "opt_pmap.h"
 #include "opt_smp.h"
@@ -1175,6 +1176,16 @@ pmap_invalidate_cache_range(vm_offset_t 
 	else if ((cpu_feature & CPUID_CLFSH) != 0 &&
 	    eva - sva < PMAP_CLFLUSH_THRESHOLD) {
 
+#ifdef DEV_APIC
+		/*
+		 * XXX: Some CPUs fault, hang, or trash the local APIC
+		 * registers if we use CLFLUSH on the local APIC
+		 * range.  The local APIC is always uncached, so we
+		 * don't need to flush for that range anyway.
+		 */
+		if (pmap_kextract(sva) == lapic_paddr)
+			return;
+#endif
 		/*
 		 * Otherwise, do per-cache line flush.  Use the mfence
 		 * instruction to insure that previous stores are

Modified: head/sys/x86/x86/local_apic.c
==============================================================================
--- head/sys/x86/x86/local_apic.c	Thu Jan 17 21:32:03 2013	(r245576)
+++ head/sys/x86/x86/local_apic.c	Thu Jan 17 21:32:25 2013	(r245577)
@@ -227,8 +227,8 @@ lapic_init(vm_paddr_t addr)
 	/* Map the local APIC and setup the spurious interrupt handler. */
 	KASSERT(trunc_page(addr) == addr,
 	    ("local APIC not aligned on a page boundary"));
-	lapic = pmap_mapdev(addr, sizeof(lapic_t));
 	lapic_paddr = addr;
+	lapic = pmap_mapdev(addr, sizeof(lapic_t));
 	setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_APIC, SEL_KPL,
 	    GSEL_APIC);
 


More information about the svn-src-all mailing list