diff options
-rw-r--r-- | arch/x86/kernel/dumpstack_64.c | 30 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 27 |
2 files changed, 15 insertions, 42 deletions
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index 788295cbe4a7..19853ad8afc5 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -105,34 +105,6 @@ in_irq_stack(unsigned long *stack, unsigned long *irq_stack, | |||
105 | } | 105 | } |
106 | 106 | ||
107 | /* | 107 | /* |
108 | * We are returning from the irq stack and go to the previous one. | ||
109 | * If the previous stack is also in the irq stack, then bp in the first | ||
110 | * frame of the irq stack points to the previous, interrupted one. | ||
111 | * Otherwise we have another level of indirection: We first save | ||
112 | * the bp of the previous stack, then we switch the stack to the irq one | ||
113 | * and save a new bp that links to the previous one. | ||
114 | * (See save_args()) | ||
115 | */ | ||
116 | static inline unsigned long | ||
117 | fixup_bp_irq_link(unsigned long bp, unsigned long *stack, | ||
118 | unsigned long *irq_stack, unsigned long *irq_stack_end) | ||
119 | { | ||
120 | #ifdef CONFIG_FRAME_POINTER | ||
121 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
122 | unsigned long next; | ||
123 | |||
124 | if (!in_irq_stack(stack, irq_stack, irq_stack_end)) { | ||
125 | if (!probe_kernel_address(&frame->next_frame, next)) | ||
126 | return next; | ||
127 | else | ||
128 | WARN_ONCE(1, "Perf: bad frame pointer = %p in " | ||
129 | "callchain\n", &frame->next_frame); | ||
130 | } | ||
131 | #endif | ||
132 | return bp; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * x86-64 can have up to three kernel stacks: | 108 | * x86-64 can have up to three kernel stacks: |
137 | * process stack | 109 | * process stack |
138 | * interrupt stack | 110 | * interrupt stack |
@@ -208,8 +180,6 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
208 | * pointer (index -1 to end) in the IRQ stack: | 180 | * pointer (index -1 to end) in the IRQ stack: |
209 | */ | 181 | */ |
210 | stack = (unsigned long *) (irq_stack_end[-1]); | 182 | stack = (unsigned long *) (irq_stack_end[-1]); |
211 | bp = fixup_bp_irq_link(bp, stack, irq_stack, | ||
212 | irq_stack_end); | ||
213 | irq_stack_end = NULL; | 183 | irq_stack_end = NULL; |
214 | ops->stack(data, "EOI"); | 184 | ops->stack(data, "EOI"); |
215 | continue; | 185 | continue; |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 6131432c5afa..d656f68371a4 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -310,8 +310,11 @@ ENDPROC(native_usergs_sysret64) | |||
310 | movq_cfi r10, R10-RBP | 310 | movq_cfi r10, R10-RBP |
311 | movq_cfi r11, R11-RBP | 311 | movq_cfi r11, R11-RBP |
312 | 312 | ||
313 | movq_cfi rbp, 0 /* push %rbp */ | 313 | /* Save rbp so that we can unwind from get_irq_regs() */ |
314 | movq %rsp, %rbp | 314 | movq_cfi rbp, 0 |
315 | |||
316 | /* Save previous stack value */ | ||
317 | movq %rsp, %rsi | ||
315 | 318 | ||
316 | leaq -RBP(%rsp),%rdi /* arg1 for handler */ | 319 | leaq -RBP(%rsp),%rdi /* arg1 for handler */ |
317 | testl $3, CS(%rdi) | 320 | testl $3, CS(%rdi) |
@@ -327,10 +330,11 @@ ENDPROC(native_usergs_sysret64) | |||
327 | jne 2f | 330 | jne 2f |
328 | mov PER_CPU_VAR(irq_stack_ptr),%rsp | 331 | mov PER_CPU_VAR(irq_stack_ptr),%rsp |
329 | EMPTY_FRAME 0 | 332 | EMPTY_FRAME 0 |
330 | /* | 333 | |
331 | * We entered an interrupt context - irqs are off: | 334 | 2: /* Store previous stack value */ |
332 | */ | 335 | pushq %rsi |
333 | 2: TRACE_IRQS_OFF | 336 | /* We entered an interrupt context - irqs are off: */ |
337 | TRACE_IRQS_OFF | ||
334 | .endm | 338 | .endm |
335 | 339 | ||
336 | ENTRY(save_rest) | 340 | ENTRY(save_rest) |
@@ -804,15 +808,14 @@ ret_from_intr: | |||
804 | DISABLE_INTERRUPTS(CLBR_NONE) | 808 | DISABLE_INTERRUPTS(CLBR_NONE) |
805 | TRACE_IRQS_OFF | 809 | TRACE_IRQS_OFF |
806 | decl PER_CPU_VAR(irq_count) | 810 | decl PER_CPU_VAR(irq_count) |
807 | leaveq | ||
808 | 811 | ||
809 | CFI_RESTORE rbp | 812 | /* Restore saved previous stack */ |
813 | popq %rsi | ||
814 | leaq 16(%rsi), %rsp | ||
815 | |||
810 | CFI_DEF_CFA_REGISTER rsp | 816 | CFI_DEF_CFA_REGISTER rsp |
811 | CFI_ADJUST_CFA_OFFSET -8 | 817 | CFI_ADJUST_CFA_OFFSET -16 |
812 | 818 | ||
813 | /* we did not save rbx, restore only from ARGOFFSET */ | ||
814 | addq $8, %rsp | ||
815 | CFI_ADJUST_CFA_OFFSET -8 | ||
816 | exit_intr: | 819 | exit_intr: |
817 | GET_THREAD_INFO(%rcx) | 820 | GET_THREAD_INFO(%rcx) |
818 | testl $3,CS-ARGOFFSET(%rsp) | 821 | testl $3,CS-ARGOFFSET(%rsp) |