perf_counter: provide major/minor page fault software events
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Fri, 13 Mar 2009 11:21:34 +0000 (12:21 +0100)
committerIngo Molnar <mingo@elte.hu>
Mon, 6 Apr 2009 07:29:40 +0000 (09:29 +0200)
Provide separate sw counters for major and minor page faults.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/powerpc/mm/fault.c
arch/x86/mm/fault.c
include/linux/perf_counter.h
kernel/perf_counter.c

index eda5b0ca4af26f5090111215c9a8f11f81d1c801..17bbf6f91fbe6e560a8c637a2b15de2aa41fec86 100644 (file)
@@ -312,6 +312,7 @@ good_area:
        }
        if (ret & VM_FAULT_MAJOR) {
                current->maj_flt++;
+               perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MAJ, 1, 0, regs);
 #ifdef CONFIG_PPC_SMLPAR
                if (firmware_has_feature(FW_FEATURE_CMO)) {
                        preempt_disable();
@@ -319,8 +320,10 @@ good_area:
                        preempt_enable();
                }
 #endif
-       } else
+       } else {
                current->min_flt++;
+               perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MIN, 1, 0, regs);
+       }
        up_read(&mm->mmap_sem);
        return 0;
 
index c8725752b6cdb6df9bb33b3ecfa95e7150d2f23c..f2d3324d9215208b7788a23e071fedde2122ab4f 100644 (file)
@@ -1140,10 +1140,13 @@ good_area:
                return;
        }
 
-       if (fault & VM_FAULT_MAJOR)
+       if (fault & VM_FAULT_MAJOR) {
                tsk->maj_flt++;
-       else
+               perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MAJ, 1, 0, regs);
+       } else {
                tsk->min_flt++;
+               perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MIN, 1, 0, regs);
+       }
 
        check_v8086_mode(regs, address, tsk);
 
index 3fefc3b8150dff9263157b5d888ae5e9a4b5f4b1..4b14a8e9dbf5d384b9bab58dbdee2d19ac775cbd 100644 (file)
@@ -49,8 +49,10 @@ enum hw_event_types {
        PERF_COUNT_PAGE_FAULTS          = -3,
        PERF_COUNT_CONTEXT_SWITCHES     = -4,
        PERF_COUNT_CPU_MIGRATIONS       = -5,
+       PERF_COUNT_PAGE_FAULTS_MIN      = -6,
+       PERF_COUNT_PAGE_FAULTS_MAJ      = -7,
 
-       PERF_SW_EVENTS_MIN              = -6,
+       PERF_SW_EVENTS_MIN              = -8,
 };
 
 /*
index 1773c5d7427dc9e9d57eded65ee3f8b4cf9a4134..68950a3a52bfbad3bd076d3ddaa4aa9324bf2d95 100644 (file)
@@ -1503,6 +1503,12 @@ static void perf_swcounter_disable(struct perf_counter *counter)
        perf_swcounter_update(counter);
 }
 
+static const struct hw_perf_counter_ops perf_ops_generic = {
+       .enable         = perf_swcounter_enable,
+       .disable        = perf_swcounter_disable,
+       .read           = perf_swcounter_read,
+};
+
 /*
  * Software counter: cpu wall time clock
  */
@@ -1603,16 +1609,6 @@ static const struct hw_perf_counter_ops perf_ops_task_clock = {
        .read           = task_clock_perf_counter_read,
 };
 
-/*
- * Software counter: page faults
- */
-
-static const struct hw_perf_counter_ops perf_ops_page_faults = {
-       .enable         = perf_swcounter_enable,
-       .disable        = perf_swcounter_disable,
-       .read           = perf_swcounter_read,
-};
-
 /*
  * Software counter: context switches
  */
@@ -1753,9 +1749,9 @@ sw_perf_counter_init(struct perf_counter *counter)
                        hw_ops = &perf_ops_cpu_clock;
                break;
        case PERF_COUNT_PAGE_FAULTS:
-               if (!(counter->hw_event.exclude_user ||
-                     counter->hw_event.exclude_kernel))
-                       hw_ops = &perf_ops_page_faults;
+       case PERF_COUNT_PAGE_FAULTS_MIN:
+       case PERF_COUNT_PAGE_FAULTS_MAJ:
+               hw_ops = &perf_ops_generic;
                break;
        case PERF_COUNT_CONTEXT_SWITCHES:
                if (!counter->hw_event.exclude_kernel)