1/* SPDX-License-Identifier: GPL-2.0 */
2.text
3#include <linux/linkage.h>
4#include <asm/segment.h>
5#include <asm/page.h>
6#include <asm/pgtable_32.h>
7
8	.macro writepost,value
9		movb $0x34, %al
10		outb %al, $0x70
11		movb $\value, %al
12		outb %al, $0x71
13	.endm
14
15wakeup_start:
16	# OFW lands us here, running in protected mode, with a
17	# kernel-compatible GDT already setup.
18
19	# Clear any dangerous flags
20	pushl $0
21	popfl
22
23	writepost 0x31
24
25	# Set up %cr3
26	movl $initial_page_table - __PAGE_OFFSET, %eax
27	movl %eax, %cr3
28
29	movl saved_cr4, %eax
30	movl %eax, %cr4
31
32	movl saved_cr0, %eax
33	movl %eax, %cr0
34
35	# Control registers were modified, pipeline resync is needed
36	jmp 1f
371:
38
39	movw    $__KERNEL_DS, %ax
40	movw    %ax, %ss
41	movw    %ax, %ds
42	movw    %ax, %es
43	movw    %ax, %fs
44	movw    %ax, %gs
45
46	lgdt    saved_gdt
47	lidt    saved_idt
48	lldt    saved_ldt
49	ljmp    $(__KERNEL_CS),$1f
501:
51	movl    %cr3, %eax
52	movl    %eax, %cr3
53	wbinvd
54
55	# Go back to the return point
56	jmp ret_point
57
58save_registers:
59	sgdt  saved_gdt
60	sidt  saved_idt
61	sldt  saved_ldt
62
63	pushl %edx
64	movl %cr4, %edx
65	movl %edx, saved_cr4
66
67	movl %cr0, %edx
68	movl %edx, saved_cr0
69
70	popl %edx
71
72	movl %ebx, saved_context_ebx
73	movl %ebp, saved_context_ebp
74	movl %esi, saved_context_esi
75	movl %edi, saved_context_edi
76
77	pushfl
78	popl saved_context_eflags
79
80	ret
81
82restore_registers:
83	movl saved_context_ebp, %ebp
84	movl saved_context_ebx, %ebx
85	movl saved_context_esi, %esi
86	movl saved_context_edi, %edi
87
88	pushl saved_context_eflags
89	popfl
90
91	ret
92
93SYM_CODE_START(do_olpc_suspend_lowlevel)
94	call	save_processor_state
95	call	save_registers
96
97	# This is the stack context we want to remember
98	movl %esp, saved_context_esp
99
100	pushl	$3
101	call	xo1_do_sleep
102
103	jmp	wakeup_start
104	.p2align 4,,7
105ret_point:
106	movl    saved_context_esp, %esp
107
108	writepost 0x32
109
110	call	restore_registers
111	call	restore_processor_state
112	ret
113SYM_CODE_END(do_olpc_suspend_lowlevel)
114
115.data
116saved_gdt:             .long   0,0
117saved_idt:             .long   0,0
118saved_ldt:             .long   0
119saved_cr4:             .long   0
120saved_cr0:             .long   0
121saved_context_esp:     .long   0
122saved_context_edi:     .long   0
123saved_context_esi:     .long   0
124saved_context_ebx:     .long   0
125saved_context_ebp:     .long   0
126saved_context_eflags:  .long   0
127