summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorfabient <fabient@FreeBSD.org>2012-03-28 20:58:30 +0000
committerfabient <fabient@FreeBSD.org>2012-03-28 20:58:30 +0000
commit5edfb77dd3a164bb9d2d40c6604faa6c9f3dce15 (patch)
treefadff08d26576c3d5c1cef9d47abd784602b237a /sys/amd64
parent9a7982e5a0267c0421856f3a43a1ae75880058f3 (diff)
downloadFreeBSD-src-5edfb77dd3a164bb9d2d40c6604faa6c9f3dce15.zip
FreeBSD-src-5edfb77dd3a164bb9d2d40c6604faa6c9f3dce15.tar.gz
Add software PMC support.
New kernel events can be added at various location for sampling or counting. This will for example allow easy system profiling whatever the processor is with known tools like pmcstat(8). Simultaneous usage of software PMC and hardware PMC is possible, for example looking at the lock acquire failure, page fault while sampling on instructions. Sponsored by: NETASQ MFC after: 1 month
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/trap.c17
-rw-r--r--sys/amd64/include/pmc_mdep.h23
2 files changed, 32 insertions, 8 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index a685f19..a760181 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -71,6 +71,9 @@ __FBSDID("$FreeBSD$");
#include <sys/vmmeter.h>
#ifdef HWPMC_HOOKS
#include <sys/pmckern.h>
+PMC_SOFT_DEFINE( , , page_fault, all);
+PMC_SOFT_DEFINE( , , page_fault, read);
+PMC_SOFT_DEFINE( , , page_fault, write);
#endif
#include <vm/vm.h>
@@ -743,8 +746,20 @@ trap_pfault(frame, usermode)
*/
rv = vm_fault(map, va, ftype, VM_FAULT_NORMAL);
}
- if (rv == KERN_SUCCESS)
+ if (rv == KERN_SUCCESS) {
+#ifdef HWPMC_HOOKS
+ if (ftype == VM_PROT_READ || ftype == VM_PROT_WRITE) {
+ PMC_SOFT_CALL_TF( , , page_fault, all, frame);
+ if (ftype == VM_PROT_READ)
+ PMC_SOFT_CALL_TF( , , page_fault, read,
+ frame);
+ else
+ PMC_SOFT_CALL_TF( , , page_fault, write,
+ frame);
+ }
+#endif
return (0);
+ }
nogo:
if (!usermode) {
if (td->td_intr_nesting_level == 0 &&
diff --git a/sys/amd64/include/pmc_mdep.h b/sys/amd64/include/pmc_mdep.h
index 4f16485..73c93fe 100644
--- a/sys/amd64/include/pmc_mdep.h
+++ b/sys/amd64/include/pmc_mdep.h
@@ -50,13 +50,13 @@ struct pmc_mdep;
* measurement architecture have PMCs of the following classes: TSC,
* IAF, IAP, UCF and UCP.
*/
-#define PMC_MDEP_CLASS_INDEX_TSC 0
-#define PMC_MDEP_CLASS_INDEX_K8 1
-#define PMC_MDEP_CLASS_INDEX_P4 1
-#define PMC_MDEP_CLASS_INDEX_IAP 1
-#define PMC_MDEP_CLASS_INDEX_IAF 2
-#define PMC_MDEP_CLASS_INDEX_UCP 3
-#define PMC_MDEP_CLASS_INDEX_UCF 4
+#define PMC_MDEP_CLASS_INDEX_TSC 1
+#define PMC_MDEP_CLASS_INDEX_K8 2
+#define PMC_MDEP_CLASS_INDEX_P4 2
+#define PMC_MDEP_CLASS_INDEX_IAP 2
+#define PMC_MDEP_CLASS_INDEX_IAF 3
+#define PMC_MDEP_CLASS_INDEX_UCP 4
+#define PMC_MDEP_CLASS_INDEX_UCF 5
/*
* On the amd64 platform we support the following PMCs.
@@ -119,6 +119,15 @@ union pmc_md_pmc {
#define PMC_IN_USERSPACE(va) ((va) <= VM_MAXUSER_ADDRESS)
+/* Build a fake kernel trapframe from current instruction pointer. */
+#define PMC_FAKE_TRAPFRAME(TF) \
+ do { \
+ (TF)->tf_cs = 0; (TF)->tf_rflags = 0; \
+ __asm __volatile("movq %%rbp,%0" : "=r" ((TF)->tf_rbp)); \
+ __asm __volatile("movq %%rsp,%0" : "=r" ((TF)->tf_rsp)); \
+ __asm __volatile("call 1f \n\t1: pop %0" : "=r"((TF)->tf_rip)); \
+ } while (0)
+
/*
* Prototypes
*/
OpenPOWER on IntegriCloud