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:
  * process stack
                                 * pointer (index -1 to end) in the IRQ stack:
                                 */
                                stack = (unsigned long *) (irq_stack_end[-1]);
-                               bp = fixup_bp_irq_link(bp, stack, irq_stack,
-                                                      irq_stack_end);
                                irq_stack_end = NULL;
                                ops->stack(data, "EOI");
                                continue;
 
        movq_cfi r10, R10-RBP
        movq_cfi r11, R11-RBP
 
-       movq_cfi rbp, 0         /* push %rbp */
-       movq %rsp, %rbp
+       /* Save rbp so that we can unwind from get_irq_regs() */
+       movq_cfi rbp, 0
+
+       /* Save previous stack value */
+       movq %rsp, %rsi
 
        leaq -RBP(%rsp),%rdi    /* arg1 for handler */
        testl $3, CS(%rdi)
        jne 2f
        mov PER_CPU_VAR(irq_stack_ptr),%rsp
        EMPTY_FRAME 0
-       /*
-        * We entered an interrupt context - irqs are off:
-        */
-2:     TRACE_IRQS_OFF
+
+2:     /* Store previous stack value */
+       pushq %rsi
+       /* We entered an interrupt context - irqs are off: */
+       TRACE_IRQS_OFF
        .endm
 
 ENTRY(save_rest)
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
        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_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:
        GET_THREAD_INFO(%rcx)
        testl $3,CS-ARGOFFSET(%rsp)