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.

MFC after:	1 week
This commit is contained in:
Mateusz Guzik 2017-01-24 22:00:16 +00:00
parent 543b2f425d
commit 736ff8c396
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=312724
2 changed files with 31 additions and 21 deletions

View File

@ -174,6 +174,9 @@ extern const int pmc_kernel_version;
/* PMC soft per cpu trapframe */
extern struct trapframe pmc_tf[MAXCPU];
/* Quick check if preparatory work is necessary */
#define PMC_HOOK_INSTALLED(cmd) __predict_false(pmc_hook != NULL)
/* Hook invocation; for use within the kernel */
#define PMC_CALL_HOOK(t, cmd, arg) \
do { \

View File

@ -526,6 +526,7 @@ sys_munmap(td, uap)
#ifdef HWPMC_HOOKS
struct pmckern_map_out pkm;
vm_map_entry_t entry;
bool pmc_handled;
#endif
vm_offset_t addr;
vm_size_t size, pageoff;
@ -551,20 +552,24 @@ sys_munmap(td, uap)
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;
}
}
}
}
@ -572,14 +577,16 @@ sys_munmap(td, uap)
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);
}