Commit 729aa21a authored by Ingo Molnar's avatar Ingo Molnar

Merge branch 'perf/stacktrace' of...

Merge branch 'perf/stacktrace' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing into perf/core
parents 29dfc4fd a2bbe750
...@@ -152,6 +152,11 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs); ...@@ -152,6 +152,11 @@ extern unsigned long perf_misc_flags(struct pt_regs *regs);
(regs)->bp = caller_frame_pointer(); \ (regs)->bp = caller_frame_pointer(); \
(regs)->cs = __KERNEL_CS; \ (regs)->cs = __KERNEL_CS; \
regs->flags = 0; \ regs->flags = 0; \
asm volatile( \
_ASM_MOV "%%"_ASM_SP ", %0\n" \
: "=m" ((regs)->sp) \
:: "memory" \
); \
} }
#else #else
......
...@@ -104,34 +104,6 @@ in_irq_stack(unsigned long *stack, unsigned long *irq_stack, ...@@ -104,34 +104,6 @@ in_irq_stack(unsigned long *stack, unsigned long *irq_stack,
return (stack >= irq_stack && stack < irq_stack_end); return (stack >= irq_stack && stack < irq_stack_end);
} }
/*
* We are returning from the irq stack and go to the previous one.
* If the previous stack is also in the irq stack, then bp in the first
* frame of the irq stack points to the previous, interrupted one.
* Otherwise we have another level of indirection: We first save
* the bp of the previous stack, then we switch the stack to the irq one
* and save a new bp that links to the previous one.
* (See save_args())
*/
static inline unsigned long
fixup_bp_irq_link(unsigned long bp, unsigned long *stack,
unsigned long *irq_stack, unsigned long *irq_stack_end)
{
#ifdef CONFIG_FRAME_POINTER
struct stack_frame *frame = (struct stack_frame *)bp;
unsigned long next;
if (!in_irq_stack(stack, irq_stack, irq_stack_end)) {
if (!probe_kernel_address(&frame->next_frame, next))
return next;
else
WARN_ONCE(1, "Perf: bad frame pointer = %p in "
"callchain\n", &frame->next_frame);
}
#endif
return bp;
}
/* /*
* x86-64 can have up to three kernel stacks: * x86-64 can have up to three kernel stacks:
* process stack * process stack
...@@ -155,9 +127,12 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, ...@@ -155,9 +127,12 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
task = current; task = current;
if (!stack) { if (!stack) {
stack = &dummy; if (regs)
if (task && task != current) stack = (unsigned long *)regs->sp;
else if (task && task != current)
stack = (unsigned long *)task->thread.sp; stack = (unsigned long *)task->thread.sp;
else
stack = &dummy;
} }
if (!bp) if (!bp)
...@@ -205,8 +180,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, ...@@ -205,8 +180,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
* pointer (index -1 to end) in the IRQ stack: * pointer (index -1 to end) in the IRQ stack:
*/ */
stack = (unsigned long *) (irq_stack_end[-1]); stack = (unsigned long *) (irq_stack_end[-1]);
bp = fixup_bp_irq_link(bp, stack, irq_stack,
irq_stack_end);
irq_stack_end = NULL; irq_stack_end = NULL;
ops->stack(data, "EOI"); ops->stack(data, "EOI");
continue; continue;
......
...@@ -297,27 +297,26 @@ ENDPROC(native_usergs_sysret64) ...@@ -297,27 +297,26 @@ ENDPROC(native_usergs_sysret64)
.endm .endm
/* save partial stack frame */ /* save partial stack frame */
.pushsection .kprobes.text, "ax" .macro SAVE_ARGS_IRQ
ENTRY(save_args)
XCPT_FRAME
cld cld
/* /* start from rbp in pt_regs and jump over */
* start from rbp in pt_regs and jump over movq_cfi rdi, RDI-RBP
* return address. movq_cfi rsi, RSI-RBP
*/ movq_cfi rdx, RDX-RBP
movq_cfi rdi, RDI+8-RBP movq_cfi rcx, RCX-RBP
movq_cfi rsi, RSI+8-RBP movq_cfi rax, RAX-RBP
movq_cfi rdx, RDX+8-RBP movq_cfi r8, R8-RBP
movq_cfi rcx, RCX+8-RBP movq_cfi r9, R9-RBP
movq_cfi rax, RAX+8-RBP movq_cfi r10, R10-RBP
movq_cfi r8, R8+8-RBP movq_cfi r11, R11-RBP
movq_cfi r9, R9+8-RBP
movq_cfi r10, R10+8-RBP /* Save rbp so that we can unwind from get_irq_regs() */
movq_cfi r11, R11+8-RBP movq_cfi rbp, 0
leaq -RBP+8(%rsp),%rdi /* arg1 for handler */ /* Save previous stack value */
movq_cfi rbp, 8 /* push %rbp */ movq %rsp, %rsi
leaq 8(%rsp), %rbp /* mov %rsp, %ebp */
leaq -RBP(%rsp),%rdi /* arg1 for handler */
testl $3, CS(%rdi) testl $3, CS(%rdi)
je 1f je 1f
SWAPGS SWAPGS
...@@ -329,19 +328,14 @@ ENTRY(save_args) ...@@ -329,19 +328,14 @@ ENTRY(save_args)
*/ */
1: incl PER_CPU_VAR(irq_count) 1: incl PER_CPU_VAR(irq_count)
jne 2f jne 2f
popq_cfi %rax /* move return address... */
mov PER_CPU_VAR(irq_stack_ptr),%rsp mov PER_CPU_VAR(irq_stack_ptr),%rsp
EMPTY_FRAME 0 EMPTY_FRAME 0
pushq_cfi %rbp /* backlink for unwinder */
pushq_cfi %rax /* ... to the new stack */ 2: /* Store previous stack value */
/* pushq %rsi
* We entered an interrupt context - irqs are off: /* We entered an interrupt context - irqs are off: */
*/ TRACE_IRQS_OFF
2: TRACE_IRQS_OFF .endm
ret
CFI_ENDPROC
END(save_args)
.popsection
ENTRY(save_rest) ENTRY(save_rest)
PARTIAL_FRAME 1 REST_SKIP+8 PARTIAL_FRAME 1 REST_SKIP+8
...@@ -791,7 +785,7 @@ END(interrupt) ...@@ -791,7 +785,7 @@ END(interrupt)
/* reserve pt_regs for scratch regs and rbp */ /* reserve pt_regs for scratch regs and rbp */
subq $ORIG_RAX-RBP, %rsp subq $ORIG_RAX-RBP, %rsp
CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
call save_args SAVE_ARGS_IRQ
PARTIAL_FRAME 0 PARTIAL_FRAME 0
call \func call \func
.endm .endm
...@@ -814,15 +808,14 @@ ret_from_intr: ...@@ -814,15 +808,14 @@ ret_from_intr:
DISABLE_INTERRUPTS(CLBR_NONE) DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count) decl PER_CPU_VAR(irq_count)
leaveq
CFI_RESTORE rbp /* Restore saved previous stack */
popq %rsi
leaq 16(%rsi), %rsp
CFI_DEF_CFA_REGISTER rsp CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET -8 CFI_ADJUST_CFA_OFFSET -16
/* we did not save rbx, restore only from ARGOFFSET */
addq $8, %rsp
CFI_ADJUST_CFA_OFFSET -8
exit_intr: exit_intr:
GET_THREAD_INFO(%rcx) GET_THREAD_INFO(%rcx)
testl $3,CS-ARGOFFSET(%rsp) testl $3,CS-ARGOFFSET(%rsp)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment