瀏覽代碼

perf_counter: provide major/minor page fault software events

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>
Peter Zijlstra 16 年之前
父節點
當前提交
ac17dc8e58
共有 4 個文件被更改,包括 21 次插入17 次删除
  1. 4 1
      arch/powerpc/mm/fault.c
  2. 5 2
      arch/x86/mm/fault.c
  3. 3 1
      include/linux/perf_counter.h
  4. 9 13
      kernel/perf_counter.c

+ 4 - 1
arch/powerpc/mm/fault.c

@@ -312,6 +312,7 @@ good_area:
 	}
 	}
 	if (ret & VM_FAULT_MAJOR) {
 	if (ret & VM_FAULT_MAJOR) {
 		current->maj_flt++;
 		current->maj_flt++;
+		perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MAJ, 1, 0, regs);
 #ifdef CONFIG_PPC_SMLPAR
 #ifdef CONFIG_PPC_SMLPAR
 		if (firmware_has_feature(FW_FEATURE_CMO)) {
 		if (firmware_has_feature(FW_FEATURE_CMO)) {
 			preempt_disable();
 			preempt_disable();
@@ -319,8 +320,10 @@ good_area:
 			preempt_enable();
 			preempt_enable();
 		}
 		}
 #endif
 #endif
-	} else
+	} else {
 		current->min_flt++;
 		current->min_flt++;
+		perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MIN, 1, 0, regs);
+	}
 	up_read(&mm->mmap_sem);
 	up_read(&mm->mmap_sem);
 	return 0;
 	return 0;
 
 

+ 5 - 2
arch/x86/mm/fault.c

@@ -1140,10 +1140,13 @@ good_area:
 		return;
 		return;
 	}
 	}
 
 
-	if (fault & VM_FAULT_MAJOR)
+	if (fault & VM_FAULT_MAJOR) {
 		tsk->maj_flt++;
 		tsk->maj_flt++;
-	else
+		perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MAJ, 1, 0, regs);
+	} else {
 		tsk->min_flt++;
 		tsk->min_flt++;
+		perf_swcounter_event(PERF_COUNT_PAGE_FAULTS_MIN, 1, 0, regs);
+	}
 
 
 	check_v8086_mode(regs, address, tsk);
 	check_v8086_mode(regs, address, tsk);
 
 

+ 3 - 1
include/linux/perf_counter.h

@@ -49,8 +49,10 @@ enum hw_event_types {
 	PERF_COUNT_PAGE_FAULTS		= -3,
 	PERF_COUNT_PAGE_FAULTS		= -3,
 	PERF_COUNT_CONTEXT_SWITCHES	= -4,
 	PERF_COUNT_CONTEXT_SWITCHES	= -4,
 	PERF_COUNT_CPU_MIGRATIONS	= -5,
 	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,
 };
 };
 
 
 /*
 /*

+ 9 - 13
kernel/perf_counter.c

@@ -1503,6 +1503,12 @@ static void perf_swcounter_disable(struct perf_counter *counter)
 	perf_swcounter_update(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
  * 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,
 	.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
  * Software counter: context switches
  */
  */
@@ -1753,9 +1749,9 @@ sw_perf_counter_init(struct perf_counter *counter)
 			hw_ops = &perf_ops_cpu_clock;
 			hw_ops = &perf_ops_cpu_clock;
 		break;
 		break;
 	case PERF_COUNT_PAGE_FAULTS:
 	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;
 		break;
 	case PERF_COUNT_CONTEXT_SWITCHES:
 	case PERF_COUNT_CONTEXT_SWITCHES:
 		if (!counter->hw_event.exclude_kernel)
 		if (!counter->hw_event.exclude_kernel)