x86-64: Fix CFI data for interrupt frames
authorJan Beulich <JBeulich@suse.com>
Wed, 28 Sep 2011 15:57:52 +0000 (16:57 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 28 Sep 2011 17:04:52 +0000 (19:04 +0200)
The patch titled "x86: Don't use frame pointer to save old stack
on irq entry" did not properly adjust CFI directives, so this
patch is a follow-up to that one.

With the old stack pointer no longer stored in a callee-saved
register (plus some offset), we now have to use a CFA expression
to describe the memory location where it is being found. This
requires the use of .cfi_escape (allowing arbitrary byte streams
to be emitted into .eh_frame), as there is no
.cfi_def_cfa_expression (which also cannot reasonably be
expected, as it would require a full expression parser).

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Link: http://lkml.kernel.org/r/4E8360200200007800058467@nat28.tlf.novell.com
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/include/asm/dwarf2.h
arch/x86/kernel/entry_64.S

index 3260991..f6f1598 100644 (file)
@@ -27,6 +27,7 @@
 #define CFI_REMEMBER_STATE     .cfi_remember_state
 #define CFI_RESTORE_STATE      .cfi_restore_state
 #define CFI_UNDEFINED          .cfi_undefined
+#define CFI_ESCAPE             .cfi_escape
 
 #ifdef CONFIG_AS_CFI_SIGNAL_FRAME
 #define CFI_SIGNAL_FRAME       .cfi_signal_frame
@@ -68,6 +69,7 @@
 #define CFI_REMEMBER_STATE     cfi_ignore
 #define CFI_RESTORE_STATE      cfi_ignore
 #define CFI_UNDEFINED          cfi_ignore
+#define CFI_ESCAPE             cfi_ignore
 #define CFI_SIGNAL_FRAME       cfi_ignore
 
 #endif
index 6419bb0..faf8d5e 100644 (file)
@@ -331,10 +331,15 @@ ENDPROC(native_usergs_sysret64)
 1:     incl PER_CPU_VAR(irq_count)
        jne 2f
        mov PER_CPU_VAR(irq_stack_ptr),%rsp
-       EMPTY_FRAME 0
+       CFI_DEF_CFA_REGISTER    rsi
 
 2:     /* Store previous stack value */
        pushq %rsi
+       CFI_ESCAPE      0x0f /* DW_CFA_def_cfa_expression */, 6, \
+                       0x77 /* DW_OP_breg7 */, 0, \
+                       0x06 /* DW_OP_deref */, \
+                       0x08 /* DW_OP_const1u */, SS+8-RBP, \
+                       0x22 /* DW_OP_plus */
        /* We entered an interrupt context - irqs are off: */
        TRACE_IRQS_OFF
        .endm
@@ -788,7 +793,6 @@ END(interrupt)
        subq $ORIG_RAX-RBP, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP
        SAVE_ARGS_IRQ
-       PARTIAL_FRAME 0
        call \func
        .endm
 
@@ -813,10 +817,10 @@ ret_from_intr:
 
        /* Restore saved previous stack */
        popq %rsi
-       leaq 16(%rsi), %rsp
-
+       CFI_DEF_CFA_REGISTER    rsi
+       leaq ARGOFFSET-RBP(%rsi), %rsp
        CFI_DEF_CFA_REGISTER    rsp
-       CFI_ADJUST_CFA_OFFSET   -16
+       CFI_ADJUST_CFA_OFFSET   RBP-ARGOFFSET
 
 exit_intr:
        GET_THREAD_INFO(%rcx)