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
| @@ -24,6 +24,7 @@ · 23 unmodified lines | |||
| 24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
| 25 | #include <linux/extable.h> | 25 | #include <linux/extable.h> |
| 26 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
| 27 | #include <linux/perf_event.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/mmu_context.h> | 29 | #include <asm/mmu_context.h> |
| 29 | #include <asm/traps.h> | 30 | #include <asm/traps.h> |
| @@ -83,6 +84,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long cause, · 53 unmodified lines | |||
| 83 | if (user_mode(regs)) | 84 | if (user_mode(regs)) |
| 84 | flags |= FAULT_FLAG_USER; | 85 | flags |= FAULT_FLAG_USER; |
| 85 | 86 | ||
| 87 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address); | ||
| 88 | |||
| 86 | if (!mmap_read_trylock(mm)) { | 89 | if (!mmap_read_trylock(mm)) { |
| 87 | if (!user_mode(regs) && !search_exception_tables(regs->ea)) | 90 | if (!user_mode(regs) && !search_exception_tables(regs->ea)) |
| 88 | goto bad_area_nosemaphore; | 91 | goto bad_area_nosemaphore; |
| @@ -131,7 +134,7 @@ good_area: · 42 unmodified lines | |||
| 131 | * make sure we exit gracefully rather than endlessly redo | 134 | * make sure we exit gracefully rather than endlessly redo |
| 132 | * the fault. | 135 | * the fault. |
| 133 | */ | 136 | */ |
| 134 | fault = handle_mm_fault(vma, address, flags, NULL); | 137 | fault = handle_mm_fault(vma, address, flags, regs); |
| 135 | 138 | ||
| 136 | if (fault_signal_pending(fault, regs)) | 139 | if (fault_signal_pending(fault, regs)) |
| 137 | return; | 140 | return; |
| @@ -146,16 +149,7 @@ good_area: · 8 unmodified lines | |||
| 146 | BUG(); | 149 | BUG(); |
| 147 | } | 150 | } |
| 148 | 151 | ||
| 149 | /* | ||
| 150 | * Major/minor page fault accounting is only done on the | ||
| 151 | * initial attempt. If we go through a retry, it is extremely | ||
| 152 | * likely that the page will be found in page cache at that point. | ||
| 153 | */ | ||
| 154 | if (flags & FAULT_FLAG_ALLOW_RETRY) { | 152 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
| 155 | if (fault & VM_FAULT_MAJOR) | ||
| 156 | current->maj_flt++; | ||
| 157 | else | ||
| 158 | current->min_flt++; | ||
| 159 | if (fault & VM_FAULT_RETRY) { | 153 | if (fault & VM_FAULT_RETRY) { |
| 160 | flags |= FAULT_FLAG_TRIED; | 154 | flags |= FAULT_FLAG_TRIED; |
| 161 | 155 | ||