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

x86-32/asm/power: Create stack frames in hibernate_asm_32.S

swsusp_arch_suspend() is callable non-leaf function which doesn't
honor CONFIG_FRAME_POINTER, which can result in bad stack traces.
Also it's not annotated as ELF callable function which can confuse tooling.

Create a stack frame for it when CONFIG_FRAME_POINTER is enabled and
give it proper ELF function annotation.

Also in this patch introduces the restore_registers() symbol and
gives it ELF function annotation, thus to prepare for later register
restore.

Analogous changes were made for 64bit before in commit ef0f3ed5a4ac
(x86/asm/power: Create stack frames in hibernate_asm_64.S) and
commit 4ce827b4cc58 (x86/power/64: Fix hibernation return address
corruption).

Signed-off-by: Zhimin Gu <kookoo.gu@intel.com>
Signed-off-by: Chen Yu <yu.c.chen@intel.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Zhimin Gu and committed by
Rafael J. Wysocki
8e5b2a3c 749fa170

+13
+4
arch/x86/include/asm/suspend_32.h
··· 32 32 unsigned long return_address; 33 33 } __attribute__((packed)); 34 34 35 + /* routines for saving/restoring kernel state */ 36 + extern char core_restore_code[]; 37 + extern char restore_registers[]; 38 + 35 39 #endif /* _ASM_X86_SUSPEND_32_H */
+9
arch/x86/power/hibernate_asm_32.S
··· 12 12 #include <asm/page_types.h> 13 13 #include <asm/asm-offsets.h> 14 14 #include <asm/processor-flags.h> 15 + #include <asm/frame.h> 15 16 16 17 .text 17 18 ··· 25 24 pushfl 26 25 popl saved_context_eflags 27 26 27 + FRAME_BEGIN 28 28 call swsusp_save 29 + FRAME_END 29 30 ret 31 + ENDPROC(swsusp_arch_suspend) 30 32 31 33 ENTRY(restore_image) 32 34 movl mmu_cr4_features, %ecx ··· 62 58 .p2align 4,,7 63 59 64 60 done: 61 + 62 + /* code below belongs to the image kernel */ 63 + .align PAGE_SIZE 64 + ENTRY(restore_registers) 65 65 /* go back to the original page tables */ 66 66 movl $swapper_pg_dir, %eax 67 67 subl $__PAGE_OFFSET, %eax ··· 91 83 xorl %eax, %eax 92 84 93 85 ret 86 + ENDPROC(restore_registers)