aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r--arch/x86/kernel/cpu/perf_event.c25
-rw-r--r--arch/x86/kernel/dumpstack.h15
-rw-r--r--arch/x86/kernel/dumpstack_64.c4
3 files changed, 33 insertions, 11 deletions
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 5586a02067d..978d297170a 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -798,7 +798,6 @@ void hw_perf_enable(void)
798 * step2: reprogram moved events into new counters 798 * step2: reprogram moved events into new counters
799 */ 799 */
800 for (i = 0; i < n_running; i++) { 800 for (i = 0; i < n_running; i++) {
801
802 event = cpuc->event_list[i]; 801 event = cpuc->event_list[i];
803 hwc = &event->hw; 802 hwc = &event->hw;
804 803
@@ -813,21 +812,16 @@ void hw_perf_enable(void)
813 continue; 812 continue;
814 813
815 x86_pmu_stop(event); 814 x86_pmu_stop(event);
816
817 hwc->idx = -1;
818 } 815 }
819 816
820 for (i = 0; i < cpuc->n_events; i++) { 817 for (i = 0; i < cpuc->n_events; i++) {
821
822 event = cpuc->event_list[i]; 818 event = cpuc->event_list[i];
823 hwc = &event->hw; 819 hwc = &event->hw;
824 820
825 if (i < n_running && 821 if (!match_prev_assignment(hwc, cpuc, i))
826 match_prev_assignment(hwc, cpuc, i))
827 continue;
828
829 if (hwc->idx == -1)
830 x86_assign_hw_event(event, cpuc, i); 822 x86_assign_hw_event(event, cpuc, i);
823 else if (i < n_running)
824 continue;
831 825
832 x86_pmu_start(event); 826 x86_pmu_start(event);
833 } 827 }
@@ -1700,3 +1694,16 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs)
1700 1694
1701 return entry; 1695 return entry;
1702} 1696}
1697
1698void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip)
1699{
1700 regs->ip = ip;
1701 /*
1702 * perf_arch_fetch_caller_regs adds another call, we need to increment
1703 * the skip level
1704 */
1705 regs->bp = rewind_frame_pointer(skip + 1);
1706 regs->cs = __KERNEL_CS;
1707 local_save_flags(regs->flags);
1708}
1709EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs);
diff --git a/arch/x86/kernel/dumpstack.h b/arch/x86/kernel/dumpstack.h
index 4fd1420faff..29e5f7c845b 100644
--- a/arch/x86/kernel/dumpstack.h
+++ b/arch/x86/kernel/dumpstack.h
@@ -29,4 +29,19 @@ struct stack_frame {
29 struct stack_frame *next_frame; 29 struct stack_frame *next_frame;
30 unsigned long return_address; 30 unsigned long return_address;
31}; 31};
32
33static inline unsigned long rewind_frame_pointer(int n)
34{
35 struct stack_frame *frame;
36
37 get_bp(frame);
38
39#ifdef CONFIG_FRAME_POINTER
40 while (n--)
41 frame = frame->next_frame;
32#endif 42#endif
43
44 return (unsigned long)frame;
45}
46
47#endif /* DUMPSTACK_H */
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index d5e2a2ebb62..272c9f1f05f 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -208,7 +208,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
208 if (in_irq_stack(stack, irq_stack, irq_stack_end)) { 208 if (in_irq_stack(stack, irq_stack, irq_stack_end)) {
209 if (ops->stack(data, "IRQ") < 0) 209 if (ops->stack(data, "IRQ") < 0)
210 break; 210 break;
211 bp = print_context_stack(tinfo, stack, bp, 211 bp = ops->walk_stack(tinfo, stack, bp,
212 ops, data, irq_stack_end, &graph); 212 ops, data, irq_stack_end, &graph);
213 /* 213 /*
214 * We link to the next stack (which would be 214 * We link to the next stack (which would be
@@ -229,7 +229,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
229 /* 229 /*
230 * This handles the process stack: 230 * This handles the process stack:
231 */ 231 */
232 bp = print_context_stack(tinfo, stack, bp, ops, data, NULL, &graph); 232 bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph);
233 put_cpu(); 233 put_cpu();
234} 234}
235EXPORT_SYMBOL(dump_trace); 235EXPORT_SYMBOL(dump_trace);