Deleted Added
sdiff udiff text old ( 115681 ) new ( 119530 )
full compact
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
28#include <machine/asm.h>
29__FBSDID("$FreeBSD: head/sys/i386/acpica/acpi_wakecode.S 115681 2003-06-02 06:16:45Z obrien $");
30
31#define LOCORE
32
33#include <machine/specialreg.h>
34
35 .align 4
36 .code16
37wakeup_16:
38 nop
39 cli
40
41 /* Set up segment registers for real mode */
42 movw %cs,%ax
43 movw %ax,%ds
44 movw %ax,%ss
45
46 /* Load GDT for real mode */
47 lgdt physical_gdt
48
49 /* Restore CR2, CR3 and CR4 */
50 mov previous_cr2,%eax
51 mov %eax,%cr2
52 mov previous_cr3,%eax
53 mov %eax,%cr3
54 mov previous_cr4,%eax
55 mov %eax,%cr4
56
57 /* Transfer some values to protected mode */
58#define NVALUES 9
59#define TRANSFER_STACK32(val, idx) \
60 mov val,%eax; \
61 mov %eax,wakeup_32stack+(idx+1)+(idx*4);
62
63 TRANSFER_STACK32(previous_ss, (NVALUES - 9))
64 TRANSFER_STACK32(previous_fs, (NVALUES - 8))
65 TRANSFER_STACK32(previous_ds, (NVALUES - 7))
66 TRANSFER_STACK32(physical_gdt+2, (NVALUES - 6))
67 TRANSFER_STACK32(where_to_recover, (NVALUES - 5))
68 TRANSFER_STACK32(previous_idt+2, (NVALUES - 4))
69 TRANSFER_STACK32(previous_ldt, (NVALUES - 3))
70 TRANSFER_STACK32(previous_gdt+2, (NVALUES - 2))
71 TRANSFER_STACK32(previous_tr, (NVALUES - 1))
72 TRANSFER_STACK32(previous_cr0, (NVALUES - 0))
73
74 mov physical_esp,%esi /* to be used in 32bit code */
75
76 /* Enable protected mode */
77 mov %cr0,%eax
78 orl $(CR0_PE),%eax
79 mov %eax,%cr0
80
81wakeup_sw32:
82 /* Switch to protected mode by intersegmental jump */
83 ljmpl $0x8,$0x12345678 /* Code location, to be replaced */
84
85 .code32
86wakeup_32:
87 /*
88 * Switched to protected mode w/o paging
89 * %esi: KERNEL stack pointer (physical address)
90 */
91
92 nop
93
94 /* Set up segment registers for protected mode */
95 movw $0x10,%ax /* KDSEL to segment registers */
96 movw %ax,%ds
97 movw %ax,%es
98 movw %ax,%gs
99 movw %ax,%ss
100 movw $0x18,%ax /* KPSEL to %fs */
101 movw %ax,%fs
102 movl %esi,%esp /* physical address stack pointer */
103
104wakeup_32stack:
105 /* Operands are overwritten in 16bit code */
106 pushl $0xabcdef09 /* ss + dummy */
107 pushl $0xabcdef08 /* fs + gs */
108 pushl $0xabcdef07 /* ds + es */
109 pushl $0xabcdef06 /* gdt:base (physical address) */
110 pushl $0xabcdef05 /* recover address */
111 pushl $0xabcdef04 /* idt:base */
112 pushl $0xabcdef03 /* ldt + idt:limit */
113 pushl $0xabcdef02 /* gdt:base */
114 pushl $0xabcdef01 /* TR + gdt:limit */
115 pushl $0xabcdef00 /* CR0 */
116
117 movl %esp,%ebp
118#define CR0_REGISTER 0(%ebp)
119#define TASK_REGISTER 4(%ebp)
120#define PREVIOUS_GDT 6(%ebp)
121#define PREVIOUS_LDT 12(%ebp)
122#define PREVIOUS_IDT 14(%ebp)
123#define RECOVER_ADDR 20(%ebp)
124#define PHYSICAL_GDT_BASE 24(%ebp)
125#define PREVIOUS_DS 28(%ebp)
126#define PREVIOUS_ES 30(%ebp)
127#define PREVIOUS_FS 32(%ebp)
128#define PREVIOUS_GS 34(%ebp)
129#define PREVIOUS_SS 36(%ebp)
130
131 /* Fixup TSS type field */
132#define TSS_TYPEFIX_MASK 0xf9
133 xorl %esi,%esi
134 movl PHYSICAL_GDT_BASE,%ebx
135 movw TASK_REGISTER,%si
136 leal (%ebx,%esi),%eax /* get TSS segment descriptor */
137 andb $TSS_TYPEFIX_MASK,5(%eax)
138
139 /* Prepare to return to sleep/wakeup code point */
140 lgdt PREVIOUS_GDT
141 lidt PREVIOUS_IDT
142
143 xorl %eax,%eax
144 movl %eax,%ebx
145 movl %eax,%ecx
146 movl %eax,%edx
147 movl %eax,%esi
148 movl %eax,%edi
149 movl PREVIOUS_DS,%ebx
150 movl PREVIOUS_FS,%ecx
151 movl PREVIOUS_SS,%edx
152 movw TASK_REGISTER,%si
153 shll $16,%esi
154 movw PREVIOUS_LDT,%si
155 movl RECOVER_ADDR,%edi
156
157 /* Enable paging and etc. */
158 movl CR0_REGISTER,%eax
159 movl %eax,%cr0
160
161 /* Flush the prefetch queue */
162 jmp 1f
1631: jmp 1f
1641:
165 /*
166 * Now that we are in kernel virtual memory addressing
167 * %ebx: ds + es
168 * %ecx: fs + gs
169 * %edx: ss + dummy
170 * %esi: LDTR + TR
171 * %edi: recover address
172 */
173
174 nop
175
176 movl %esi,%eax /* LDTR + TR */
177 lldt %ax /* load LDT register */
178 shrl $16,%eax
179 ltr %ax /* load task register */
180
181 /* Restore segment registers */
182 movl %ebx,%eax /* ds + es */
183 movw %ax,%ds
184 shrl $16,%eax
185 movw %ax,%es
186 movl %ecx,%eax /* fs + gs */
187 movw %ax,%fs
188 shrl $16,%eax
189 movw %ax,%gs
190 movl %edx,%eax /* ss */
191 movw %ax,%ss
192
193 /* Jump to acpi_restorecpu() */
194 jmp *%edi
195
196/* used in real mode */
197physical_gdt: .word 0
198 .long 0
199physical_esp: .long 0
200previous_cr2: .long 0
201previous_cr3: .long 0
202previous_cr4: .long 0
203
204/* transfer from real mode to protected mode */
205previous_cr0: .long 0
206previous_tr: .word 0
207previous_gdt: .word 0
208 .long 0
209previous_ldt: .word 0
210previous_idt: .word 0
211 .long 0
212where_to_recover: .long 0
213previous_ds: .word 0
214previous_es: .word 0
215previous_fs: .word 0
216previous_gs: .word 0
217previous_ss: .word 0
218dummy: .word 0
219