diff options
| -rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 2 | ||||
| -rw-r--r-- | arch/x86/kernel/kgdb.c | 2 | ||||
| -rw-r--r-- | include/linux/perf_event.h | 21 | ||||
| -rw-r--r-- | kernel/perf_event.c | 4 | ||||
| -rw-r--r-- | kernel/trace/trace_event_perf.c | 11 |
5 files changed, 25 insertions, 15 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 60398a0d947c..5fb490c6ee5c 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
| @@ -1702,7 +1702,6 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
| 1702 | return entry; | 1702 | return entry; |
| 1703 | } | 1703 | } |
| 1704 | 1704 | ||
| 1705 | #ifdef CONFIG_EVENT_TRACING | ||
| 1706 | void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) | 1705 | void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) |
| 1707 | { | 1706 | { |
| 1708 | regs->ip = ip; | 1707 | regs->ip = ip; |
| @@ -1714,4 +1713,3 @@ void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int ski | |||
| 1714 | regs->cs = __KERNEL_CS; | 1713 | regs->cs = __KERNEL_CS; |
| 1715 | local_save_flags(regs->flags); | 1714 | local_save_flags(regs->flags); |
| 1716 | } | 1715 | } |
| 1717 | #endif | ||
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index bfba6019d762..b2258ca91003 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c | |||
| @@ -618,8 +618,8 @@ int kgdb_arch_init(void) | |||
| 618 | * portion of kgdb because this operation requires mutexs to | 618 | * portion of kgdb because this operation requires mutexs to |
| 619 | * complete. | 619 | * complete. |
| 620 | */ | 620 | */ |
| 621 | hw_breakpoint_init(&attr); | ||
| 621 | attr.bp_addr = (unsigned long)kgdb_arch_init; | 622 | attr.bp_addr = (unsigned long)kgdb_arch_init; |
| 622 | attr.type = PERF_TYPE_BREAKPOINT; | ||
| 623 | attr.bp_len = HW_BREAKPOINT_LEN_1; | 623 | attr.bp_len = HW_BREAKPOINT_LEN_1; |
| 624 | attr.bp_type = HW_BREAKPOINT_W; | 624 | attr.bp_type = HW_BREAKPOINT_W; |
| 625 | attr.disabled = 1; | 625 | attr.disabled = 1; |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 95477038a72a..c8e375440403 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
| @@ -842,13 +842,6 @@ extern atomic_t perf_swevent_enabled[PERF_COUNT_SW_MAX]; | |||
| 842 | 842 | ||
| 843 | extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64); | 843 | extern void __perf_sw_event(u32, u64, int, struct pt_regs *, u64); |
| 844 | 844 | ||
| 845 | static inline void | ||
| 846 | perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) | ||
| 847 | { | ||
| 848 | if (atomic_read(&perf_swevent_enabled[event_id])) | ||
| 849 | __perf_sw_event(event_id, nr, nmi, regs, addr); | ||
| 850 | } | ||
| 851 | |||
| 852 | extern void | 845 | extern void |
| 853 | perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip); | 846 | perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip); |
| 854 | 847 | ||
| @@ -887,6 +880,20 @@ static inline void perf_fetch_caller_regs(struct pt_regs *regs, int skip) | |||
| 887 | return perf_arch_fetch_caller_regs(regs, ip, skip); | 880 | return perf_arch_fetch_caller_regs(regs, ip, skip); |
| 888 | } | 881 | } |
| 889 | 882 | ||
| 883 | static inline void | ||
| 884 | perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) | ||
| 885 | { | ||
| 886 | if (atomic_read(&perf_swevent_enabled[event_id])) { | ||
| 887 | struct pt_regs hot_regs; | ||
| 888 | |||
| 889 | if (!regs) { | ||
| 890 | perf_fetch_caller_regs(&hot_regs, 1); | ||
| 891 | regs = &hot_regs; | ||
| 892 | } | ||
| 893 | __perf_sw_event(event_id, nr, nmi, regs, addr); | ||
| 894 | } | ||
| 895 | } | ||
| 896 | |||
| 890 | extern void __perf_event_mmap(struct vm_area_struct *vma); | 897 | extern void __perf_event_mmap(struct vm_area_struct *vma); |
| 891 | 898 | ||
| 892 | static inline void perf_event_mmap(struct vm_area_struct *vma) | 899 | static inline void perf_event_mmap(struct vm_area_struct *vma) |
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 574ee58a3046..b0feb4795af3 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
| @@ -1164,11 +1164,9 @@ void perf_event_task_sched_out(struct task_struct *task, | |||
| 1164 | struct perf_event_context *ctx = task->perf_event_ctxp; | 1164 | struct perf_event_context *ctx = task->perf_event_ctxp; |
| 1165 | struct perf_event_context *next_ctx; | 1165 | struct perf_event_context *next_ctx; |
| 1166 | struct perf_event_context *parent; | 1166 | struct perf_event_context *parent; |
| 1167 | struct pt_regs *regs; | ||
| 1168 | int do_switch = 1; | 1167 | int do_switch = 1; |
| 1169 | 1168 | ||
| 1170 | regs = task_pt_regs(task); | 1169 | perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, NULL, 0); |
| 1171 | perf_sw_event(PERF_COUNT_SW_CONTEXT_SWITCHES, 1, 1, regs, 0); | ||
| 1172 | 1170 | ||
| 1173 | if (likely(!ctx || !cpuctx->task_ctx)) | 1171 | if (likely(!ctx || !cpuctx->task_ctx)) |
| 1174 | return; | 1172 | return; |
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 81f691eb3a30..0565bb42566f 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c | |||
| @@ -17,7 +17,12 @@ EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); | |||
| 17 | static char *perf_trace_buf; | 17 | static char *perf_trace_buf; |
| 18 | static char *perf_trace_buf_nmi; | 18 | static char *perf_trace_buf_nmi; |
| 19 | 19 | ||
| 20 | typedef typeof(char [PERF_MAX_TRACE_SIZE]) perf_trace_t ; | 20 | /* |
| 21 | * Force it to be aligned to unsigned long to avoid misaligned accesses | ||
| 22 | * suprises | ||
| 23 | */ | ||
| 24 | typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)]) | ||
| 25 | perf_trace_t; | ||
| 21 | 26 | ||
| 22 | /* Count the events in use (per event id, not per instance) */ | 27 | /* Count the events in use (per event id, not per instance) */ |
| 23 | static int total_ref_count; | 28 | static int total_ref_count; |
| @@ -130,6 +135,8 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type, | |||
| 130 | char *trace_buf, *raw_data; | 135 | char *trace_buf, *raw_data; |
| 131 | int pc, cpu; | 136 | int pc, cpu; |
| 132 | 137 | ||
| 138 | BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(unsigned long)); | ||
| 139 | |||
| 133 | pc = preempt_count(); | 140 | pc = preempt_count(); |
| 134 | 141 | ||
| 135 | /* Protect the per cpu buffer, begin the rcu read side */ | 142 | /* Protect the per cpu buffer, begin the rcu read side */ |
| @@ -152,7 +159,7 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type, | |||
| 152 | raw_data = per_cpu_ptr(trace_buf, cpu); | 159 | raw_data = per_cpu_ptr(trace_buf, cpu); |
| 153 | 160 | ||
| 154 | /* zero the dead bytes from align to not leak stack to user */ | 161 | /* zero the dead bytes from align to not leak stack to user */ |
| 155 | *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; | 162 | memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64)); |
| 156 | 163 | ||
| 157 | entry = (struct trace_entry *)raw_data; | 164 | entry = (struct trace_entry *)raw_data; |
| 158 | tracing_generic_entry_update(entry, *irq_flags, pc); | 165 | tracing_generic_entry_update(entry, *irq_flags, pc); |
