xref: /openbmc/linux/arch/x86/power/hibernate_asm_32.S (revision 03ab8e6297acd1bc0eedaa050e2a1635c576fd11)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
2c5759124SRafael J. Wysocki/*
3c5759124SRafael J. Wysocki * This may not use any stack, nor any variable that is not "NoSave":
4c5759124SRafael J. Wysocki *
5c5759124SRafael J. Wysocki * Its rewriting one kernel image with another. What is stack in "old"
6c5759124SRafael J. Wysocki * image could very well be data page in "new" image, and overwriting
7c5759124SRafael J. Wysocki * your own stack under you is bad idea.
8c5759124SRafael J. Wysocki */
9c5759124SRafael J. Wysocki
10c5759124SRafael J. Wysocki#include <linux/linkage.h>
11c5759124SRafael J. Wysocki#include <asm/segment.h>
120341c14dSJeremy Fitzhardinge#include <asm/page_types.h>
13c5759124SRafael J. Wysocki#include <asm/asm-offsets.h>
14c171f465SUros Bizjak#include <asm/processor-flags.h>
158e5b2a3cSZhimin Gu#include <asm/frame.h>
16c5759124SRafael J. Wysocki
17c5759124SRafael J. Wysocki.text
18c5759124SRafael J. Wysocki
196d685e53SJiri SlabySYM_FUNC_START(swsusp_arch_suspend)
20c5759124SRafael J. Wysocki	movl %esp, saved_context_esp
21c5759124SRafael J. Wysocki	movl %ebx, saved_context_ebx
22c5759124SRafael J. Wysocki	movl %ebp, saved_context_ebp
23c5759124SRafael J. Wysocki	movl %esi, saved_context_esi
24c5759124SRafael J. Wysocki	movl %edi, saved_context_edi
25c171f465SUros Bizjak	pushfl
26c171f465SUros Bizjak	popl saved_context_eflags
27c5759124SRafael J. Wysocki
2832aa2764SZhimin Gu	/* save cr3 */
2932aa2764SZhimin Gu	movl	%cr3, %eax
3032aa2764SZhimin Gu	movl	%eax, restore_cr3
3132aa2764SZhimin Gu
328e5b2a3cSZhimin Gu	FRAME_BEGIN
33c5759124SRafael J. Wysocki	call swsusp_save
348e5b2a3cSZhimin Gu	FRAME_END
35*f94909ceSPeter Zijlstra	RET
366d685e53SJiri SlabySYM_FUNC_END(swsusp_arch_suspend)
37c5759124SRafael J. Wysocki
3878762b0eSJiri SlabySYM_CODE_START(restore_image)
395331d2c7SZhimin Gu	/* prepare to jump to the image kernel */
405331d2c7SZhimin Gu	movl	restore_jump_address, %ebx
4132aa2764SZhimin Gu	movl	restore_cr3, %ebp
4232aa2764SZhimin Gu
438ae06d22SShaohua Li	movl	mmu_cr4_features, %ecx
446bae499aSZhimin Gu
456bae499aSZhimin Gu	/* jump to relocated restore code */
466bae499aSZhimin Gu	movl	relocated_restore_code, %eax
476bae499aSZhimin Gu	jmpl	*%eax
4878762b0eSJiri SlabySYM_CODE_END(restore_image)
496bae499aSZhimin Gu
506bae499aSZhimin Gu/* code below has been relocated to a safe page */
5178762b0eSJiri SlabySYM_CODE_START(core_restore_code)
527c0a9827SZhimin Gu	movl	temp_pgt, %eax
53e532c06fSDavid Fries	movl	%eax, %cr3
54c5759124SRafael J. Wysocki
558ae06d22SShaohua Li	jecxz	1f	# cr4 Pentium and higher, skip if zero
568ae06d22SShaohua Li	andl	$~(X86_CR4_PGE), %ecx
578ae06d22SShaohua Li	movl	%ecx, %cr4;  # turn off PGE
588ae06d22SShaohua Li	movl	%cr3, %eax;  # flush TLB
598ae06d22SShaohua Li	movl	%eax, %cr3
608ae06d22SShaohua Li1:
61c5759124SRafael J. Wysocki	movl	restore_pblist, %edx
62c5759124SRafael J. Wysocki	.p2align 4,,7
63c5759124SRafael J. Wysocki
64c5759124SRafael J. Wysockicopy_loop:
65c5759124SRafael J. Wysocki	testl	%edx, %edx
66c5759124SRafael J. Wysocki	jz	done
67c5759124SRafael J. Wysocki
68c5759124SRafael J. Wysocki	movl	pbe_address(%edx), %esi
69c5759124SRafael J. Wysocki	movl	pbe_orig_address(%edx), %edi
70c5759124SRafael J. Wysocki
710b0a6b1fSZhimin Gu	movl	$(PAGE_SIZE >> 2), %ecx
72c5759124SRafael J. Wysocki	rep
73c5759124SRafael J. Wysocki	movsl
74c5759124SRafael J. Wysocki
75c5759124SRafael J. Wysocki	movl	pbe_next(%edx), %edx
76c5759124SRafael J. Wysocki	jmp	copy_loop
77c5759124SRafael J. Wysocki	.p2align 4,,7
78c5759124SRafael J. Wysocki
79c5759124SRafael J. Wysockidone:
805331d2c7SZhimin Gu	jmpl	*%ebx
8178762b0eSJiri SlabySYM_CODE_END(core_restore_code)
828e5b2a3cSZhimin Gu
838e5b2a3cSZhimin Gu	/* code below belongs to the image kernel */
848e5b2a3cSZhimin Gu	.align PAGE_SIZE
856d685e53SJiri SlabySYM_FUNC_START(restore_registers)
86c5759124SRafael J. Wysocki	/* go back to the original page tables */
8732aa2764SZhimin Gu	movl	%ebp, %cr3
88e532c06fSDavid Fries	movl	mmu_cr4_features, %ecx
89e532c06fSDavid Fries	jecxz	1f	# cr4 Pentium and higher, skip if zero
90e532c06fSDavid Fries	movl	%ecx, %cr4;  # turn PGE back on
91e532c06fSDavid Fries1:
92c5759124SRafael J. Wysocki
93c5759124SRafael J. Wysocki	movl saved_context_esp, %esp
94c5759124SRafael J. Wysocki	movl saved_context_ebp, %ebp
95c5759124SRafael J. Wysocki	movl saved_context_ebx, %ebx
96c5759124SRafael J. Wysocki	movl saved_context_esi, %esi
97c5759124SRafael J. Wysocki	movl saved_context_edi, %edi
98c5759124SRafael J. Wysocki
99c171f465SUros Bizjak	pushl saved_context_eflags
100c171f465SUros Bizjak	popfl
101c5759124SRafael J. Wysocki
102cc456c4eSKonrad Rzeszutek Wilk	/* Saved in save_processor_state. */
103cc456c4eSKonrad Rzeszutek Wilk	movl $saved_context, %eax
104cc456c4eSKonrad Rzeszutek Wilk	lgdt saved_context_gdt_desc(%eax)
105cc456c4eSKonrad Rzeszutek Wilk
106c5759124SRafael J. Wysocki	xorl	%eax, %eax
107c5759124SRafael J. Wysocki
1081fca4ba0SZhimin Gu	/* tell the hibernation core that we've just restored the memory */
1091fca4ba0SZhimin Gu	movl	%eax, in_suspend
1101fca4ba0SZhimin Gu
111*f94909ceSPeter Zijlstra	RET
1126d685e53SJiri SlabySYM_FUNC_END(restore_registers)
113