Use the general page fault accounting by passing regs into handle_mm_fault(). It naturally solve the issue of multiple page fault accounting when page fault retry happened. Add the missing PERF_COUNT_SW_PAGE_FAULTS perf events too. Note, the other two perf events (PERF_COUNT_SW_PAGE_FAULTS_[MAJ|MIN]) were done in handle_mm_fault().
Unified · Split
| @@ -12,6 +12,7 @@ · 11 unmodified lines | |||
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/uaccess.h> | 14 | #include <linux/uaccess.h> |
| 15 | #include <linux/perf_event.h> | ||
| 15 | 16 | ||
| 16 | #include <asm/setup.h> | 17 | #include <asm/setup.h> |
| 17 | #include <asm/traps.h> | 18 | #include <asm/traps.h> |
| @@ -84,6 +85,8 @@ int do_page_fault(struct pt_regs *regs, unsigned long address, · 66 unmodified lines | |||
| 84 | 85 | ||
| 85 | if (user_mode(regs)) | 86 | if (user_mode(regs)) |
| 86 | flags |= FAULT_FLAG_USER; | 87 | flags |= FAULT_FLAG_USER; |
| 88 | |||
| 89 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | ||
| 87 | retry: | 90 | retry: |
| 88 | mmap_read_lock(mm); | 91 | mmap_read_lock(mm); |
| 89 | 92 | ||
| @@ -134,7 +137,7 @@ good_area: · 44 unmodified lines | |||
| 134 | * the fault. | 137 | * the fault. |
| 135 | */ | 138 | */ |
| 136 | 139 | ||
| 137 | fault = handle_mm_fault(vma, address, flags, NULL); | 140 | fault = handle_mm_fault(vma, address, flags, regs); |
| 138 | pr_debug("handle_mm_fault returns %x\n", fault); | 141 | pr_debug("handle_mm_fault returns %x\n", fault); |
| 139 | 142 | ||
| 140 | if (fault_signal_pending(fault, regs)) | 143 | if (fault_signal_pending(fault, regs)) |
| @@ -150,16 +153,7 @@ good_area: · 9 unmodified lines | |||
| 150 | BUG(); | 153 | BUG(); |
| 151 | } | 154 | } |
| 152 | 155 | ||
| 153 | /* | ||
| 154 | * Major/minor page fault accounting is only done on the | ||
| 155 | * initial attempt. If we go through a retry, it is extremely | ||
| 156 | * likely that the page will be found in page cache at that point. | ||
| 157 | */ | ||
| 158 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | 156 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
| 159 | if (fault & VM_FAULT_MAJOR) | ||
| 160 | current->maj_flt++; | ||
| 161 | else | ||
| 162 | current->min_flt++; | ||
| 163 | if (fault & VM_FAULT_RETRY) { | 157 | if (fault & VM_FAULT_RETRY) { |
| 164 | flags |= FAULT_FLAG_TRIED; | 158 | flags |= FAULT_FLAG_TRIED; |
| 165 | 159 | ||