Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86-64: Fix CFI data for interrupt frames

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>

authored by

Jan Beulich and committed by
Ingo Molnar
eab9e613 e05139f2

+11 -5
+2
arch/x86/include/asm/dwarf2.h
··· 27 27 #define CFI_REMEMBER_STATE .cfi_remember_state 28 28 #define CFI_RESTORE_STATE .cfi_restore_state 29 29 #define CFI_UNDEFINED .cfi_undefined 30 + #define CFI_ESCAPE .cfi_escape 30 31 31 32 #ifdef CONFIG_AS_CFI_SIGNAL_FRAME 32 33 #define CFI_SIGNAL_FRAME .cfi_signal_frame ··· 69 68 #define CFI_REMEMBER_STATE cfi_ignore 70 69 #define CFI_RESTORE_STATE cfi_ignore 71 70 #define CFI_UNDEFINED cfi_ignore 71 + #define CFI_ESCAPE cfi_ignore 72 72 #define CFI_SIGNAL_FRAME cfi_ignore 73 73 74 74 #endif
+9 -5
arch/x86/kernel/entry_64.S
··· 331 331 1: incl PER_CPU_VAR(irq_count) 332 332 jne 2f 333 333 mov PER_CPU_VAR(irq_stack_ptr),%rsp 334 - EMPTY_FRAME 0 334 + CFI_DEF_CFA_REGISTER rsi 335 335 336 336 2: /* Store previous stack value */ 337 337 pushq %rsi 338 + CFI_ESCAPE 0x0f /* DW_CFA_def_cfa_expression */, 6, \ 339 + 0x77 /* DW_OP_breg7 */, 0, \ 340 + 0x06 /* DW_OP_deref */, \ 341 + 0x08 /* DW_OP_const1u */, SS+8-RBP, \ 342 + 0x22 /* DW_OP_plus */ 338 343 /* We entered an interrupt context - irqs are off: */ 339 344 TRACE_IRQS_OFF 340 345 .endm ··· 793 788 subq $ORIG_RAX-RBP, %rsp 794 789 CFI_ADJUST_CFA_OFFSET ORIG_RAX-RBP 795 790 SAVE_ARGS_IRQ 796 - PARTIAL_FRAME 0 797 791 call \func 798 792 .endm 799 793 ··· 817 813 818 814 /* Restore saved previous stack */ 819 815 popq %rsi 820 - leaq 16(%rsi), %rsp 821 - 816 + CFI_DEF_CFA_REGISTER rsi 817 + leaq ARGOFFSET-RBP(%rsi), %rsp 822 818 CFI_DEF_CFA_REGISTER rsp 823 - CFI_ADJUST_CFA_OFFSET -16 819 + CFI_ADJUST_CFA_OFFSET RBP-ARGOFFSET 824 820 825 821 exit_intr: 826 822 GET_THREAD_INFO(%rcx)