diff options
author | alc <alc@FreeBSD.org> | 2007-03-05 21:40:10 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2007-03-05 21:40:10 +0000 |
commit | e5d284af0e116746a686e9cbb85fcf3daaa3ee76 (patch) | |
tree | cb57b528f77fc194b8c0c89bb65222dfcaebe191 /sys/i386 | |
parent | e346acc30df9e6e8a4d6f4d0a6db074437f3df28 (diff) | |
download | FreeBSD-src-e5d284af0e116746a686e9cbb85fcf3daaa3ee76.zip FreeBSD-src-e5d284af0e116746a686e9cbb85fcf3daaa3ee76.tar.gz |
Acquiring smp_ipi_mtx on every call to pmap_invalidate_*() is wasteful.
For example, during a buildworld more than half of the calls do not
generate an IPI because the only TLB entry invalidated is on the calling
processor. This revision pushes down the acquisition and release of
smp_ipi_mtx into smp_tlb_shootdown() and smp_targeted_tlb_shootdown() and
instead uses sched_pin() and sched_unpin() in pmap_invalidate_*() so that
thread migration doesn't lead to a missed TLB invalidation.
Reviewed by: jhb
MFC after: 3 weeks
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/i386/mp_machdep.c | 11 | ||||
-rw-r--r-- | sys/i386/i386/pmap.c | 72 | ||||
-rw-r--r-- | sys/i386/i386/vm_machdep.c | 2 |
3 files changed, 17 insertions, 68 deletions
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c index 2dde6c0..3ca9bcf 100644 --- a/sys/i386/i386/mp_machdep.c +++ b/sys/i386/i386/mp_machdep.c @@ -74,6 +74,7 @@ __FBSDID("$FreeBSD$"); #include <machine/md_var.h> #include <machine/mp_watchdog.h> #include <machine/pcb.h> +#include <machine/psl.h> #include <machine/smp.h> #include <machine/specialreg.h> #include <machine/privatespace.h> @@ -1007,13 +1008,16 @@ smp_tlb_shootdown(u_int vector, vm_offset_t addr1, vm_offset_t addr2) ncpu = mp_ncpus - 1; /* does not shootdown self */ if (ncpu < 1) return; /* no other cpus */ - mtx_assert(&smp_ipi_mtx, MA_OWNED); + if (!(read_eflags() & PSL_I)) + panic("%s: interrupts disabled", __func__); + mtx_lock_spin(&smp_ipi_mtx); smp_tlb_addr1 = addr1; smp_tlb_addr2 = addr2; atomic_store_rel_int(&smp_tlb_wait, 0); ipi_all_but_self(vector); while (smp_tlb_wait < ncpu) ia32_pause(); + mtx_unlock_spin(&smp_ipi_mtx); } static void @@ -1041,7 +1045,9 @@ smp_targeted_tlb_shootdown(u_int mask, u_int vector, vm_offset_t addr1, vm_offse if (ncpu < 1) return; } - mtx_assert(&smp_ipi_mtx, MA_OWNED); + if (!(read_eflags() & PSL_I)) + panic("%s: interrupts disabled", __func__); + mtx_lock_spin(&smp_ipi_mtx); smp_tlb_addr1 = addr1; smp_tlb_addr2 = addr2; atomic_store_rel_int(&smp_tlb_wait, 0); @@ -1051,6 +1057,7 @@ smp_targeted_tlb_shootdown(u_int mask, u_int vector, vm_offset_t addr1, vm_offse ipi_selected(mask, vector); while (smp_tlb_wait < ncpu) ia32_pause(); + mtx_unlock_spin(&smp_ipi_mtx); } void diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 963c57d..b2ab67d 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -717,18 +717,7 @@ pmap_invalidate_page(pmap_t pmap, vm_offset_t va) u_int cpumask; u_int other_cpus; - if (smp_started) { - if (!(read_eflags() & PSL_I)) - panic("%s: interrupts disabled", __func__); - mtx_lock_spin(&smp_ipi_mtx); - } else - critical_enter(); - /* - * We need to disable interrupt preemption but MUST NOT have - * interrupts disabled here. - * XXX we may need to hold schedlock to get a coherent pm_active - * XXX critical sections disable interrupts again - */ + sched_pin(); if (pmap == kernel_pmap || pmap->pm_active == all_cpus) { invlpg(va); smp_invlpg(va); @@ -740,10 +729,7 @@ pmap_invalidate_page(pmap_t pmap, vm_offset_t va) if (pmap->pm_active & other_cpus) smp_masked_invlpg(pmap->pm_active & other_cpus, va); } - if (smp_started) - mtx_unlock_spin(&smp_ipi_mtx); - else - critical_exit(); + sched_unpin(); } void @@ -753,18 +739,7 @@ pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) u_int other_cpus; vm_offset_t addr; - if (smp_started) { - if (!(read_eflags() & PSL_I)) - panic("%s: interrupts disabled", __func__); - mtx_lock_spin(&smp_ipi_mtx); - } else - critical_enter(); - /* - * We need to disable interrupt preemption but MUST NOT have - * interrupts disabled here. - * XXX we may need to hold schedlock to get a coherent pm_active - * XXX critical sections disable interrupts again - */ + sched_pin(); if (pmap == kernel_pmap || pmap->pm_active == all_cpus) { for (addr = sva; addr < eva; addr += PAGE_SIZE) invlpg(addr); @@ -779,10 +754,7 @@ pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva) smp_masked_invlpg_range(pmap->pm_active & other_cpus, sva, eva); } - if (smp_started) - mtx_unlock_spin(&smp_ipi_mtx); - else - critical_exit(); + sched_unpin(); } void @@ -791,18 +763,7 @@ pmap_invalidate_all(pmap_t pmap) u_int cpumask; u_int other_cpus; - if (smp_started) { - if (!(read_eflags() & PSL_I)) - panic("%s: interrupts disabled", __func__); - mtx_lock_spin(&smp_ipi_mtx); - } else - critical_enter(); - /* - * We need to disable interrupt preemption but MUST NOT have - * interrupts disabled here. - * XXX we may need to hold schedlock to get a coherent pm_active - * XXX critical sections disable interrupts again - */ + sched_pin(); if (pmap == kernel_pmap || pmap->pm_active == all_cpus) { invltlb(); smp_invltlb(); @@ -814,34 +775,17 @@ pmap_invalidate_all(pmap_t pmap) if (pmap->pm_active & other_cpus) smp_masked_invltlb(pmap->pm_active & other_cpus); } - if (smp_started) - mtx_unlock_spin(&smp_ipi_mtx); - else - critical_exit(); + sched_unpin(); } void pmap_invalidate_cache(void) { - if (smp_started) { - if (!(read_eflags() & PSL_I)) - panic("%s: interrupts disabled", __func__); - mtx_lock_spin(&smp_ipi_mtx); - } else - critical_enter(); - /* - * We need to disable interrupt preemption but MUST NOT have - * interrupts disabled here. - * XXX we may need to hold schedlock to get a coherent pm_active - * XXX critical sections disable interrupts again - */ + sched_pin(); wbinvd(); smp_cache_flush(); - if (smp_started) - mtx_unlock_spin(&smp_ipi_mtx); - else - critical_exit(); + sched_unpin(); } #else /* !SMP */ /* diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index 075bfdd..9d23013 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -767,9 +767,7 @@ shootdown: other_cpus = PCPU_GET(other_cpus) & ~sf->cpumask; if (other_cpus != 0) { sf->cpumask |= other_cpus; - mtx_lock_spin(&smp_ipi_mtx); smp_masked_invlpg(other_cpus, sf->kva); - mtx_unlock_spin(&smp_ipi_mtx); } } sched_unpin(); |