1 /*-
2 * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
3 * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * $FreeBSD: releng/5.0/sys/i386/acpica/acpi_wakecode.S 80028 2001-07-20 06:07:34Z takawata $
28 */
29
30 #define LOCORE
31
32 #include <machine/specialreg.h>
33
34 .align 4
35 .code16
36 wakeup_16:
37 nop
38 cli
39
40 /* Set up segment registers for real mode */
41 movw %cs,%ax
42 movw %ax,%ds
43 movw %ax,%ss
44
45 /* Load GDT for real mode */
46 lgdt physical_gdt
47
48 /* Restore CR2, CR3 and CR4 */
49 mov previous_cr2,%eax
50 mov %eax,%cr2
51 mov previous_cr3,%eax
52 mov %eax,%cr3
53 mov previous_cr4,%eax
54 mov %eax,%cr4
55
56 /* Transfer some values to protected mode */
57 #define NVALUES 9
58 #define TRANSFER_STACK32(val, idx) \
59 mov val,%eax; \
60 mov %eax,wakeup_32stack+(idx+1)+(idx*4);
61
62 TRANSFER_STACK32(previous_ss, (NVALUES - 9))
63 TRANSFER_STACK32(previous_fs, (NVALUES - 8))
64 TRANSFER_STACK32(previous_ds, (NVALUES - 7))
65 TRANSFER_STACK32(physical_gdt+2, (NVALUES - 6))
66 TRANSFER_STACK32(where_to_recover, (NVALUES - 5))
67 TRANSFER_STACK32(previous_idt+2, (NVALUES - 4))
68 TRANSFER_STACK32(previous_ldt, (NVALUES - 3))
69 TRANSFER_STACK32(previous_gdt+2, (NVALUES - 2))
70 TRANSFER_STACK32(previous_tr, (NVALUES - 1))
71 TRANSFER_STACK32(previous_cr0, (NVALUES - 0))
72
73 mov physical_esp,%esi /* to be used in 32bit code */
74
75 /* Enable protected mode */
76 mov %cr0,%eax
77 orl $(CR0_PE),%eax
78 mov %eax,%cr0
79
80 wakeup_sw32:
81 /* Switch to protected mode by intersegmental jump */
82 ljmpl $0x8,$0x12345678 /* Code location, to be replaced */
83
84 .code32
85 wakeup_32:
86 /*
87 * Switched to protected mode w/o paging
88 * %esi: KERNEL stack pointer (physical address)
89 */
90
91 nop
92
93 /* Set up segment registers for protected mode */
94 movw $0x10,%ax /* KDSEL to segment registers */
95 movw %ax,%ds
96 movw %ax,%es
97 movw %ax,%gs
98 movw %ax,%ss
99 movw $0x18,%ax /* KPSEL to %fs */
100 movw %ax,%fs
101 movl %esi,%esp /* physical address stack pointer */
102
103 wakeup_32stack:
104 /* Operands are overwritten in 16bit code */
105 pushl $0xabcdef09 /* ss + dummy */
106 pushl $0xabcdef08 /* fs + gs */
107 pushl $0xabcdef07 /* ds + es */
108 pushl $0xabcdef06 /* gdt:base (physical address) */
109 pushl $0xabcdef05 /* recover address */
110 pushl $0xabcdef04 /* idt:base */
111 pushl $0xabcdef03 /* ldt + idt:limit */
112 pushl $0xabcdef02 /* gdt:base */
113 pushl $0xabcdef01 /* TR + gdt:limit */
114 pushl $0xabcdef00 /* CR0 */
115
116 movl %esp,%ebp
117 #define CR0_REGISTER 0(%ebp)
118 #define TASK_REGISTER 4(%ebp)
119 #define PREVIOUS_GDT 6(%ebp)
120 #define PREVIOUS_LDT 12(%ebp)
121 #define PREVIOUS_IDT 14(%ebp)
122 #define RECOVER_ADDR 20(%ebp)
123 #define PHYSICAL_GDT_BASE 24(%ebp)
124 #define PREVIOUS_DS 28(%ebp)
125 #define PREVIOUS_ES 30(%ebp)
126 #define PREVIOUS_FS 32(%ebp)
127 #define PREVIOUS_GS 34(%ebp)
128 #define PREVIOUS_SS 36(%ebp)
129
130 /* Fixup TSS type field */
131 #define TSS_TYPEFIX_MASK 0xf9
132 xorl %esi,%esi
133 movl PHYSICAL_GDT_BASE,%ebx
134 movw TASK_REGISTER,%si
135 leal (%ebx,%esi),%eax /* get TSS segment descriptor */
136 andb $TSS_TYPEFIX_MASK,5(%eax)
137
138 /* Prepare to return to sleep/wakeup code point */
139 lgdt PREVIOUS_GDT
140 lidt PREVIOUS_IDT
141
142 xorl %eax,%eax
143 movl %eax,%ebx
144 movl %eax,%ecx
145 movl %eax,%edx
146 movl %eax,%esi
147 movl %eax,%edi
148 movl PREVIOUS_DS,%ebx
149 movl PREVIOUS_FS,%ecx
150 movl PREVIOUS_SS,%edx
151 movw TASK_REGISTER,%si
152 shll $16,%esi
153 movw PREVIOUS_LDT,%si
154 movl RECOVER_ADDR,%edi
155
156 /* Enable paging and etc. */
157 movl CR0_REGISTER,%eax
158 movl %eax,%cr0
159
160 /* Flush the prefetch queue */
161 jmp 1f
162 1: jmp 1f
163 1:
164 /*
165 * Now that we are in kernel virtual memory addressing
166 * %ebx: ds + es
167 * %ecx: fs + gs
168 * %edx: ss + dummy
169 * %esi: LDTR + TR
170 * %edi: recover address
171 */
172
173 nop
174
175 movl %esi,%eax /* LDTR + TR */
176 lldt %ax /* load LDT register */
177 shrl $16,%eax
178 ltr %ax /* load task register */
179
180 /* Restore segment registers */
181 movl %ebx,%eax /* ds + es */
182 movw %ax,%ds
183 shrl $16,%eax
184 movw %ax,%es
185 movl %ecx,%eax /* fs + gs */
186 movw %ax,%fs
187 shrl $16,%eax
188 movw %ax,%gs
189 movl %edx,%eax /* ss */
190 movw %ax,%ss
191
192 /* Jump to acpi_restorecpu() */
193 jmp *%edi
194
195 /* used in real mode */
196 physical_gdt: .word 0
197 .long 0
198 physical_esp: .long 0
199 previous_cr2: .long 0
200 previous_cr3: .long 0
201 previous_cr4: .long 0
202
203 /* transfer from real mode to protected mode */
204 previous_cr0: .long 0
205 previous_tr: .word 0
206 previous_gdt: .word 0
207 .long 0
208 previous_ldt: .word 0
209 previous_idt: .word 0
210 .long 0
211 where_to_recover: .long 0
212 previous_ds: .word 0
213 previous_es: .word 0
214 previous_fs: .word 0
215 previous_gs: .word 0
216 previous_ss: .word 0
217 dummy: .word 0
218
Cache object: 19970e7e5a6085ef60c4d4d442d2b8cd
|