summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c35
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c170
-rw-r--r--sys/kern/kern_linker.c78
-rw-r--r--sys/sys/linker.h3
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/pmc.h10
-rw-r--r--sys/sys/pmckern.h18
-rw-r--r--sys/sys/pmclog.h39
-rw-r--r--sys/vm/vm_mmap.c41
9 files changed, 361 insertions, 35 deletions
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index f901cbe..efa0c52 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -137,10 +137,11 @@ static struct mtx pmc_kthread_mtx; /* sleep lock */
CTASSERT(sizeof(struct pmclog_closelog) == 3*4);
CTASSERT(sizeof(struct pmclog_dropnotify) == 3*4);
-CTASSERT(sizeof(struct pmclog_mappingchange) == PATH_MAX +
- 5*4 + 2*sizeof(uintfptr_t));
-CTASSERT(offsetof(struct pmclog_mappingchange,pl_pathname) ==
- 5*4 + 2*sizeof(uintfptr_t));
+CTASSERT(sizeof(struct pmclog_map_in) == PATH_MAX +
+ 4*4 + sizeof(uintfptr_t));
+CTASSERT(offsetof(struct pmclog_map_in,pl_pathname) ==
+ 4*4 + sizeof(uintfptr_t));
+CTASSERT(sizeof(struct pmclog_map_out) == 4*4 + 2*sizeof(uintfptr_t));
CTASSERT(sizeof(struct pmclog_pcsample) == 6*4 + sizeof(uintfptr_t));
CTASSERT(sizeof(struct pmclog_pmcallocate) == 6*4);
CTASSERT(sizeof(struct pmclog_pmcattach) == 5*4 + PATH_MAX);
@@ -728,24 +729,36 @@ pmclog_process_dropnotify(struct pmc_owner *po)
}
void
-pmclog_process_mappingchange(struct pmc_owner *po, pid_t pid, int type,
- uintfptr_t start, uintfptr_t end, char *path)
+pmclog_process_map_in(struct pmc_owner *po, pid_t pid, uintfptr_t start,
+ const char *path)
{
int pathlen, recordlen;
+ KASSERT(path != NULL, ("[pmclog,%d] map-in, null path", __LINE__));
+
pathlen = strlen(path) + 1; /* #bytes for path name */
- recordlen = offsetof(struct pmclog_mappingchange, pl_pathname) +
+ recordlen = offsetof(struct pmclog_map_in, pl_pathname) +
pathlen;
- PMCLOG_RESERVE(po,MAPPINGCHANGE,recordlen);
- PMCLOG_EMIT32(type);
- PMCLOG_EMITADDR(start);
- PMCLOG_EMITADDR(end);
+ PMCLOG_RESERVE(po, MAP_IN, recordlen);
PMCLOG_EMIT32(pid);
+ PMCLOG_EMITADDR(start);
PMCLOG_EMITSTRING(path,pathlen);
PMCLOG_DESPATCH(po);
}
+void
+pmclog_process_map_out(struct pmc_owner *po, pid_t pid, uintfptr_t start,
+ uintfptr_t end)
+{
+ KASSERT(start <= end, ("[pmclog,%d] start > end", __LINE__));
+
+ PMCLOG_RESERVE(po, MAP_OUT, sizeof(struct pmclog_map_out));
+ PMCLOG_EMIT32(pid);
+ PMCLOG_EMITADDR(start);
+ PMCLOG_EMITADDR(end);
+ PMCLOG_DESPATCH(po);
+}
void
pmclog_process_pcsample(struct pmc *pm, struct pmc_sample *ps)
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index 0b6f72d..12d742a 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2005 Joseph Koshy
+ * Copyright (c) 2003-2006 Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/vnode.h>
+#include <sys/linker.h> /* needs to be after <sys/malloc.h> */
+
#include <machine/atomic.h>
#include <machine/md_var.h>
@@ -1411,19 +1413,138 @@ pmc_process_csw_out(struct thread *td)
}
/*
+ * Log a KLD operation.
+ */
+
+static void
+pmc_process_kld_load(struct pmckern_map_in *pkm)
+{
+ struct pmc_owner *po;
+
+ sx_assert(&pmc_sx, SX_LOCKED);
+
+ /*
+ * Notify owners of system sampling PMCs about KLD operations.
+ */
+
+ LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ pmclog_process_map_in(po, (pid_t) -1, pkm->pm_address,
+ (char *) pkm->pm_file);
+
+ /*
+ * TODO: Notify owners of (all) process-sampling PMCs too.
+ */
+
+ return;
+}
+
+static void
+pmc_process_kld_unload(struct pmckern_map_out *pkm)
+{
+ struct pmc_owner *po;
+
+ sx_assert(&pmc_sx, SX_LOCKED);
+
+ LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ pmclog_process_map_out(po, (pid_t) -1,
+ pkm->pm_address, pkm->pm_address + pkm->pm_size);
+
+ /*
+ * TODO: Notify owners of process-sampling PMCs.
+ */
+}
+
+/*
+ * A mapping change for a process.
+ */
+
+static void
+pmc_process_mmap(struct thread *td, struct pmckern_map_in *pkm)
+{
+ int ri;
+ pid_t pid;
+ char *fullpath, *freepath;
+ const struct pmc *pm;
+ struct pmc_owner *po;
+ const struct pmc_process *pp;
+
+ freepath = fullpath = NULL;
+ pmc_getfilename((struct vnode *) pkm->pm_file, &fullpath, &freepath);
+
+ pid = td->td_proc->p_pid;
+
+ /* Inform owners of all system-wide sampling PMCs. */
+ LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ pmclog_process_map_in(po, pid, pkm->pm_address, fullpath);
+
+ if ((pp = pmc_find_process_descriptor(td->td_proc, 0)) == NULL)
+ goto done;
+
+ /*
+ * Inform sampling PMC owners tracking this process.
+ */
+ for (ri = 0; ri < md->pmd_npmc; ri++)
+ if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL &&
+ PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ pmclog_process_map_in(pm->pm_owner,
+ pid, pkm->pm_address, fullpath);
+
+ done:
+ if (freepath)
+ FREE(freepath, M_TEMP);
+}
+
+
+/*
+ * Log an munmap request.
+ */
+
+static void
+pmc_process_munmap(struct thread *td, struct pmckern_map_out *pkm)
+{
+ int ri;
+ pid_t pid;
+ struct pmc_owner *po;
+ const struct pmc *pm;
+ const struct pmc_process *pp;
+
+ pid = td->td_proc->p_pid;
+
+ LIST_FOREACH(po, &pmc_ss_owners, po_ssnext)
+ if (po->po_flags & PMC_PO_OWNS_LOGFILE)
+ pmclog_process_map_out(po, pid, pkm->pm_address,
+ pkm->pm_address + pkm->pm_size);
+
+ if ((pp = pmc_find_process_descriptor(td->td_proc, 0)) == NULL)
+ return;
+
+ for (ri = 0; ri < md->pmd_npmc; ri++)
+ if ((pm = pp->pp_pmcs[ri].pp_pmc) != NULL &&
+ PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
+ pmclog_process_map_out(po, pid, pkm->pm_address,
+ pkm->pm_address + pkm->pm_size);
+}
+
+/*
* The 'hook' invoked from the kernel proper
*/
#ifdef DEBUG
const char *pmc_hooknames[] = {
+ /* these strings correspond to PMC_FN_* in <sys/pmckern.h> */
"",
- "EXIT",
"EXEC",
- "FORK",
"CSW-IN",
"CSW-OUT",
- "SAMPLE"
+ "SAMPLE",
+ "KLDLOAD",
+ "KLDUNLOAD",
+ "MMAP",
+ "MUNMAP"
};
#endif
@@ -1585,6 +1706,27 @@ pmc_hook_handler(struct thread *td, int function, void *arg)
pmc_process_samples(PCPU_GET(cpuid));
break;
+
+ case PMC_FN_KLD_LOAD:
+ sx_assert(&pmc_sx, SX_LOCKED);
+ pmc_process_kld_load((struct pmckern_map_in *) arg);
+ break;
+
+ case PMC_FN_KLD_UNLOAD:
+ sx_assert(&pmc_sx, SX_LOCKED);
+ pmc_process_kld_unload((struct pmckern_map_out *) arg);
+ break;
+
+ case PMC_FN_MMAP:
+ sx_assert(&pmc_sx, SX_LOCKED);
+ pmc_process_mmap(td, (struct pmckern_map_in *) arg);
+ break;
+
+ case PMC_FN_MUNMAP:
+ sx_assert(&pmc_sx, SX_LOCKED);
+ pmc_process_munmap(td, (struct pmckern_map_out *) arg);
+ break;
+
default:
#ifdef DEBUG
KASSERT(0, ("[pmc,%d] unknown hook %d\n", __LINE__, function));
@@ -2237,6 +2379,8 @@ pmc_start(struct pmc *pm)
po->po_sscount++;
}
+ /* TODO: dump system wide process mappings to the log? */
+
/*
* Move to the CPU associated with this
* PMC, and start the hardware.
@@ -2408,10 +2552,11 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
case PMC_OP_CONFIGURELOG:
{
+ struct proc *p;
struct pmc *pm;
struct pmc_owner *po;
+ struct pmckern_map_in *km, *kmbase;
struct pmc_op_configurelog cl;
- struct proc *p;
sx_assert(&pmc_sx, SX_XLOCKED);
@@ -2446,6 +2591,21 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
} else
error = EINVAL;
+
+ if (error)
+ break;
+
+ /*
+ * Log the current set of kernel modules.
+ */
+ kmbase = linker_hwpmc_list_objects();
+ for (km = kmbase; km->pm_file != NULL; km++) {
+ PMCDBG(LOG,REG,1,"%s %p", (char *) km->pm_file,
+ (void *) km->pm_address);
+ pmclog_process_map_in(po, (pid_t) -1, km->pm_address,
+ km->pm_file);
+ }
+ FREE(kmbase, M_LINKER);
}
break;
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
index ca05cc0..a48cfd2 100644
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -28,6 +28,7 @@
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
+#include "opt_hwpmc_hooks.h"
#include "opt_mac.h"
#include <sys/param.h>
@@ -51,6 +52,10 @@ __FBSDID("$FreeBSD$");
#include "linker_if.h"
+#ifdef HWPMC_HOOKS
+#include <sys/pmckern.h>
+#endif
+
#ifdef KLD_DEBUG
int kld_debug = 0;
#endif
@@ -751,6 +756,9 @@ linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval)
int
kldload(struct thread *td, struct kldload_args *uap)
{
+#ifdef HWPMC_HOOKS
+ struct pmckern_map_in pkm;
+#endif
char *kldname, *modname;
char *pathname = NULL;
linker_file_t lf;
@@ -786,6 +794,11 @@ kldload(struct thread *td, struct kldload_args *uap)
if (error)
goto out;
+#ifdef HWPMC_HOOKS
+ pkm.pm_file = lf->filename;
+ pkm.pm_address = (uintptr_t) lf->address;
+ PMC_CALL_HOOK(td, PMC_FN_KLD_LOAD, (void *) &pkm);
+#endif
lf->userrefs++;
td->td_retval[0] = lf->id;
out:
@@ -801,6 +814,9 @@ out:
static int
kern_kldunload(struct thread *td, int fileid, int flags)
{
+#ifdef HWPMC_HOOKS
+ struct pmckern_map_out pkm;
+#endif
linker_file_t lf;
int error = 0;
@@ -825,11 +841,21 @@ kern_kldunload(struct thread *td, int fileid, int flags)
goto out;
}
lf->userrefs--;
+#ifdef HWPMC_HOOKS
+ /* Save data needed by hwpmc(4) before unloading the kld. */
+ pkm.pm_address = (uintptr_t) lf->address;
+ pkm.pm_size = lf->size;
+#endif
error = linker_file_unload(lf, flags);
if (error)
lf->userrefs++;
} else
error = ENOENT;
+
+#ifdef HWPMC_HOOKS
+ if (error == 0)
+ PMC_CALL_HOOK(td, PMC_FN_KLD_UNLOAD, (void *) &pkm);
+#endif
out:
mtx_unlock(&Giant);
return (error);
@@ -1659,6 +1685,58 @@ linker_basename(const char *path)
return (filename);
}
+#ifdef HWPMC_HOOKS
+
+/*
+ * Inform hwpmc about the set of kernel modules currently loaded.
+ */
+void *
+linker_hwpmc_list_objects(void)
+{
+ int nobjects, nmappings;
+ linker_file_t lf;
+ struct pmckern_map_in *ko, *kobase;
+
+ nmappings = 15; /* a reasonable default */
+
+ retry:
+ /* allocate nmappings+1 entries */
+ MALLOC(kobase, struct pmckern_map_in *,
+ (nmappings + 1) * sizeof(struct pmckern_map_in), M_LINKER,
+ M_WAITOK | M_ZERO);
+
+ nobjects = 0;
+ mtx_lock(&kld_mtx);
+ TAILQ_FOREACH(lf, &linker_files, link)
+ nobjects++;
+
+ KASSERT(nobjects > 0, ("linker_hpwmc_list_objects: no kernel "
+ "objects?"));
+
+ if (nobjects > nmappings) {
+ nmappings = nobjects;
+ FREE(kobase, M_LINKER);
+ mtx_unlock(&kld_mtx);
+ goto retry;
+ }
+
+ ko = kobase;
+ TAILQ_FOREACH(lf, &linker_files, link) {
+ ko->pm_file = lf->filename;
+ ko->pm_address = (uintptr_t) lf->address;
+ ko++;
+ }
+
+ /* The last entry of the malloced area comprises of all zeros. */
+ KASSERT(ko->pm_file == NULL,
+ ("linker_hwpmc_list_objects: last object not NULL"));
+
+ mtx_unlock(&kld_mtx);
+
+ return ((void *) kobase);
+}
+#endif
+
/*
* Find a file which contains given module and load it, if "parent" is not
* NULL, register a reference to it.
diff --git a/sys/sys/linker.h b/sys/sys/linker.h
index 90ed243..c112eb4 100644
--- a/sys/sys/linker.h
+++ b/sys/sys/linker.h
@@ -172,6 +172,9 @@ int linker_ddb_search_symbol(caddr_t _value, c_linker_sym_t *_sym,
int linker_ddb_symbol_values(c_linker_sym_t _sym, linker_symval_t *_symval);
+/* HWPMC helper */
+void *linker_hwpmc_list_objects(void);
+
#endif /* _KERNEL */
/*
diff --git a/sys/sys/param.h b/sys/sys/param.h
index 4c6a6ca..04ee8b8 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 700014 /* Master, propagated to newvers */
+#define __FreeBSD_version 700015 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/pmc.h b/sys/sys/pmc.h
index 3ce513d..a0bad56 100644
--- a/sys/sys/pmc.h
+++ b/sys/sys/pmc.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2005, Joseph Koshy
+ * Copyright (c) 2003-2006, Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -50,9 +50,9 @@
*
* The patch version is incremented for every bug fix.
*/
-#define PMC_VERSION_MAJOR 0x01
-#define PMC_VERSION_MINOR 0x02
-#define PMC_VERSION_PATCH 0x0003
+#define PMC_VERSION_MAJOR 0x02
+#define PMC_VERSION_MINOR 0x00
+#define PMC_VERSION_PATCH 0x0000
#define PMC_VERSION (PMC_VERSION_MAJOR << 24 | \
PMC_VERSION_MINOR << 16 | PMC_VERSION_PATCH)
@@ -538,7 +538,7 @@ struct pmc_op_getmsr {
#define PMC_MTXPOOL_SIZE 32
#define PMC_LOG_BUFFER_SIZE 4
#define PMC_NLOGBUFFERS 16
-#define PMC_NSAMPLES 16
+#define PMC_NSAMPLES 32
#define PMC_SYSCTL_NAME_PREFIX "kern." PMC_MODULE_NAME "."
diff --git a/sys/sys/pmckern.h b/sys/sys/pmckern.h
index d489fe6..5ae3101 100644
--- a/sys/sys/pmckern.h
+++ b/sys/sys/pmckern.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2003-2005, Joseph Koshy
+ * Copyright (c) 2003-2006, Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -43,10 +43,24 @@
#define PMC_FN_CSW_IN 2
#define PMC_FN_CSW_OUT 3
#define PMC_FN_DO_SAMPLES 4
+#define PMC_FN_KLD_LOAD 5
+#define PMC_FN_KLD_UNLOAD 6
+#define PMC_FN_MMAP 7
+#define PMC_FN_MUNMAP 8
struct pmckern_procexec {
int pm_credentialschanged;
- uintptr_t pm_entryaddr;
+ uintfptr_t pm_entryaddr;
+};
+
+struct pmckern_map_in {
+ void *pm_file; /* filename or vnode pointer */
+ uintfptr_t pm_address; /* address object is loaded at */
+};
+
+struct pmckern_map_out {
+ uintfptr_t pm_address; /* start address of region */
+ size_t pm_size; /* size of unmapped region */
};
/* hook */
diff --git a/sys/sys/pmclog.h b/sys/sys/pmclog.h
index 026c667..2d2edc0 100644
--- a/sys/sys/pmclog.h
+++ b/sys/sys/pmclog.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005 Joseph Koshy
+ * Copyright (c) 2005-2006, Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -32,10 +32,11 @@
#include <sys/pmc.h>
enum pmclog_type {
+ /* V1 ABI */
PMCLOG_TYPE_CLOSELOG,
PMCLOG_TYPE_DROPNOTIFY,
PMCLOG_TYPE_INITIALIZE,
- PMCLOG_TYPE_MAPPINGCHANGE,
+ PMCLOG_TYPE_MAPPINGCHANGE, /* unused in v1 */
PMCLOG_TYPE_PCSAMPLE,
PMCLOG_TYPE_PMCALLOCATE,
PMCLOG_TYPE_PMCATTACH,
@@ -45,11 +46,19 @@ enum pmclog_type {
PMCLOG_TYPE_PROCEXIT,
PMCLOG_TYPE_PROCFORK,
PMCLOG_TYPE_SYSEXIT,
- PMCLOG_TYPE_USERDATA
+ PMCLOG_TYPE_USERDATA,
+ /*
+ * V2 ABI
+ *
+ * The MAP_{IN,OUT} event types obsolete the MAPPING_CHANGE
+ * event type of the older (V1) ABI.
+ */
+ PMCLOG_TYPE_MAP_IN,
+ PMCLOG_TYPE_MAP_OUT
};
-#define PMCLOG_MAPPING_INSERT 0x01
-#define PMCLOG_MAPPING_DELETE 0x02
+#define PMCLOG_MAPPING_INSERT 0x01 /* obsolete */
+#define PMCLOG_MAPPING_DELETE 0x02 /* obsolete */
/*
* A log entry descriptor comprises of a 32 bit header and a 64 bit
@@ -98,15 +107,19 @@ struct pmclog_initialize {
uint32_t pl_cpu; /* enum pmc_cputype */
} __packed;
-struct pmclog_mappingchange {
+struct pmclog_map_in {
PMCLOG_ENTRY_HEADER
- uint32_t pl_type;
- uintfptr_t pl_start; /* 8 byte aligned */
- uintfptr_t pl_end;
uint32_t pl_pid;
+ uintfptr_t pl_start; /* 8 byte aligned */
char pl_pathname[PATH_MAX];
} __packed;
+struct pmclog_map_out {
+ PMCLOG_ENTRY_HEADER
+ uint32_t pl_pid;
+ uintfptr_t pl_start; /* 8 byte aligned */
+ uintfptr_t pl_end;
+} __packed;
struct pmclog_pcsample {
PMCLOG_ENTRY_HEADER
@@ -178,6 +191,8 @@ union pmclog_entry { /* only used to size scratch areas */
struct pmclog_closelog pl_cl;
struct pmclog_dropnotify pl_dn;
struct pmclog_initialize pl_i;
+ struct pmclog_map_in pl_mi;
+ struct pmclog_map_out pl_mo;
struct pmclog_pcsample pl_s;
struct pmclog_pmcallocate pl_a;
struct pmclog_pmcattach pl_t;
@@ -212,8 +227,10 @@ int pmclog_flush(struct pmc_owner *_po);
void pmclog_initialize(void);
void pmclog_process_closelog(struct pmc_owner *po);
void pmclog_process_dropnotify(struct pmc_owner *po);
-void pmclog_process_mappingchange(struct pmc_owner *po, pid_t pid, int type,
- uintfptr_t start, uintfptr_t end, char *path);
+void pmclog_process_map_in(struct pmc_owner *po, pid_t pid,
+ uintfptr_t start, const char *path);
+void pmclog_process_map_out(struct pmc_owner *po, pid_t pid,
+ uintfptr_t start, uintfptr_t end);
void pmclog_process_pcsample(struct pmc *_pm, struct pmc_sample *_ps);
void pmclog_process_pmcallocate(struct pmc *_pm);
void pmclog_process_pmcattach(struct pmc *_pm, pid_t _pid, char *_path);
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 9379c3b..33f387e 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -44,6 +44,7 @@
__FBSDID("$FreeBSD$");
#include "opt_compat.h"
+#include "opt_hwpmc_hooks.h"
#include "opt_mac.h"
#include <sys/param.h>
@@ -79,6 +80,10 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_page.h>
#include <vm/vm_kern.h>
+#ifdef HWPMC_HOOKS
+#include <sys/pmckern.h>
+#endif
+
#ifndef _SYS_SYSPROTO_H_
struct sbrk_args {
int incr;
@@ -201,6 +206,9 @@ mmap(td, uap)
struct thread *td;
struct mmap_args *uap;
{
+#ifdef HWPMC_HOOKS
+ struct pmckern_map_in pkm;
+#endif
struct file *fp;
struct vnode *vp;
vm_offset_t addr;
@@ -364,6 +372,15 @@ mmap(td, uap)
error = vm_mmap(&vms->vm_map, &addr, size, prot, maxprot,
flags, handle_type, handle, pos);
+#ifdef HWPMC_HOOKS
+ /* inform hwpmc(4) if an executable is being mapped */
+ if (error == 0 && handle_type == OBJT_VNODE &&
+ (prot & PROT_EXEC)) {
+ pkm.pm_file = handle;
+ pkm.pm_address = (uintptr_t) addr;
+ PMC_CALL_HOOK(td, PMC_FN_MMAP, (void *) &pkm);
+ }
+#endif
if (error == 0)
td->td_retval[0] = (register_t) (addr + pageoff);
done:
@@ -495,6 +512,10 @@ munmap(td, uap)
struct thread *td;
struct munmap_args *uap;
{
+#ifdef HWPMC_HOOKS
+ struct pmckern_map_out pkm;
+ vm_map_entry_t entry;
+#endif
vm_offset_t addr;
vm_size_t size, pageoff;
vm_map_t map;
@@ -525,6 +546,26 @@ munmap(td, uap)
vm_map_unlock(map);
return (EINVAL);
}
+#ifdef HWPMC_HOOKS
+ /*
+ * Inform hwpmc if the address range being unmapped contains
+ * an executable region.
+ */
+ 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;
+ PMC_CALL_HOOK(td, PMC_FN_MUNMAP,
+ (void *) &pkm);
+ break;
+ }
+ }
+ }
+#endif
/* returns nothing but KERN_SUCCESS anyway */
vm_map_delete(map, addr, addr + size);
vm_map_unlock(map);
OpenPOWER on IntegriCloud