summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authormjg <mjg@FreeBSD.org>2017-03-14 20:43:04 +0000
committermjg <mjg@FreeBSD.org>2017-03-14 20:43:04 +0000
commit3edf8a9d08485cf11c17af11e7852d41f8edea23 (patch)
tree3a52f54c3221a41c2827b86fcf9b8cfa4136dae9 /sys/vm
parent57f28a25af7dd32fc8adea80c5ebb2b237cc86a6 (diff)
downloadFreeBSD-src-3edf8a9d08485cf11c17af11e7852d41f8edea23.zip
FreeBSD-src-3edf8a9d08485cf11c17af11e7852d41f8edea23.tar.gz
MFC r312724,r312901,r312902:
hwpmc: partially depessimize munmap handling if the module is not loaded HWPMC_HOOKS is enabled in GENERIC and triggers some work avoidable in the common (module not loaded) case. In particular this avoids permission checks + lock downgrade singlethreaded and in cases were an executable mapping is found the pmc sx lock is no longer bounced. Note this is a band aid. == hwpmc: partially depessimize mmap handling if the module is not loaded In particular this means the pmc sx lock is no longer taken when an executable mapping succeeds. == hwpmc: annotate pmc_hook and pmc_intr as __read_mostly
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_mmap.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index ada71f0..db0a3bd 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -500,6 +500,7 @@ kern_munmap(struct thread *td, uintptr_t addr0, size_t size)
#ifdef HWPMC_HOOKS
struct pmckern_map_out pkm;
vm_map_entry_t entry;
+ bool pmc_handled;
#endif
vm_offset_t addr;
vm_size_t pageoff;
@@ -524,20 +525,24 @@ kern_munmap(struct thread *td, uintptr_t addr0, size_t size)
return (EINVAL);
vm_map_lock(map);
#ifdef HWPMC_HOOKS
- /*
- * Inform hwpmc if the address range being unmapped contains
- * an executable region.
- */
- pkm.pm_address = (uintptr_t) NULL;
- if (vm_map_lookup_entry(map, addr, &entry)) {
- for (;
- entry != &map->header && entry->start < addr + size;
- entry = entry->next) {
- if (vm_map_check_protection(map, entry->start,
- entry->end, VM_PROT_EXECUTE) == TRUE) {
- pkm.pm_address = (uintptr_t) addr;
- pkm.pm_size = (size_t) size;
- break;
+ pmc_handled = false;
+ if (PMC_HOOK_INSTALLED(PMC_FN_MUNMAP)) {
+ pmc_handled = true;
+ /*
+ * Inform hwpmc if the address range being unmapped contains
+ * an executable region.
+ */
+ pkm.pm_address = (uintptr_t) NULL;
+ if (vm_map_lookup_entry(map, addr, &entry)) {
+ for (;
+ entry != &map->header && entry->start < addr + size;
+ entry = entry->next) {
+ if (vm_map_check_protection(map, entry->start,
+ entry->end, VM_PROT_EXECUTE) == TRUE) {
+ pkm.pm_address = (uintptr_t) addr;
+ pkm.pm_size = (size_t) size;
+ break;
+ }
}
}
}
@@ -545,14 +550,16 @@ kern_munmap(struct thread *td, uintptr_t addr0, size_t size)
vm_map_delete(map, addr, addr + size);
#ifdef HWPMC_HOOKS
- /* downgrade the lock to prevent a LOR with the pmc-sx lock */
- vm_map_lock_downgrade(map);
- if (pkm.pm_address != (uintptr_t) NULL)
- PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm);
- vm_map_unlock_read(map);
-#else
- vm_map_unlock(map);
+ if (__predict_false(pmc_handled)) {
+ /* downgrade the lock to prevent a LOR with the pmc-sx lock */
+ vm_map_lock_downgrade(map);
+ if (pkm.pm_address != (uintptr_t) NULL)
+ PMC_CALL_HOOK(td, PMC_FN_MUNMAP, (void *) &pkm);
+ vm_map_unlock_read(map);
+ } else
#endif
+ vm_map_unlock(map);
+
/* vm_map_delete returns nothing but KERN_SUCCESS anyway */
return (0);
}
OpenPOWER on IntegriCloud