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