aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/pmap.c9
-rw-r--r--sys/i386/i386/pmap.c11
-rw-r--r--sys/x86/x86/local_apic.c2
3 files changed, 21 insertions, 1 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 8e06ff91a2bd3..352cb340a49f5 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -1150,6 +1150,15 @@ pmap_invalidate_cache_range(vm_offset_t sva, vm_offset_t eva)
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
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index f14f2151a2c38..24c8b2485e7b6 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -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 sva, vm_offset_t eva)
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
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index e9941729463ae..fc85abf3b7d9c 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -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);