2 * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
3 * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
27 * $FreeBSD: src/sys/i386/acpica/acpi_wakecode.S,v 1.9 2004/01/01 22:57:22 njl Exp $
28 * $DragonFly: src/sys/platform/pc32/acpica5/acpi_wakecode.S,v 1.1 2004/02/21 06:48:05 dillon Exp $
33 #include <machine/asmacros.h>
34 #include <machine/param.h>
35 #include <machine/specialreg.h>
44 * Set up segment registers for real mode and a small stack for
52 /* Re-initialize video BIOS if the reset_video tunable is set. */
58 * Set up segment registers for real mode again in case the
59 * previous BIOS call clobbers them.
66 /* Load GDT for real mode */
69 /* Restore CR2, CR3 and CR4 */
77 /* Transfer some values to protected mode */
79 #define TRANSFER_STACK32(val, idx) \
81 mov %eax,wakeup_32stack+(idx+1)+(idx*4);
83 TRANSFER_STACK32(previous_ss, (NVALUES - 9))
84 TRANSFER_STACK32(previous_fs, (NVALUES - 8))
85 TRANSFER_STACK32(previous_ds, (NVALUES - 7))
86 TRANSFER_STACK32(physical_gdt+2, (NVALUES - 6))
87 TRANSFER_STACK32(where_to_recover, (NVALUES - 5))
88 TRANSFER_STACK32(previous_idt+2, (NVALUES - 4))
89 TRANSFER_STACK32(previous_ldt, (NVALUES - 3))
90 TRANSFER_STACK32(previous_gdt+2, (NVALUES - 2))
91 TRANSFER_STACK32(previous_tr, (NVALUES - 1))
92 TRANSFER_STACK32(previous_cr0, (NVALUES - 0))
94 mov physical_esp,%esi /* to be used in 32bit code */
96 /* Enable protected mode */
102 /* Switch to protected mode by intersegmental jump */
103 ljmpl $0x8,$0x12345678 /* Code location, to be replaced */
108 * Switched to protected mode w/o paging
109 * %esi: KERNEL stack pointer (physical address)
114 /* Set up segment registers for protected mode */
115 movw $0x10,%ax /* KDSEL to segment registers */
120 movw $0x18,%ax /* KPSEL to %fs */
122 movl %esi,%esp /* physical address stack pointer */
125 /* Operands are overwritten in 16bit code */
126 pushl $0xabcdef09 /* ss + dummy */
127 pushl $0xabcdef08 /* fs + gs */
128 pushl $0xabcdef07 /* ds + es */
129 pushl $0xabcdef06 /* gdt:base (physical address) */
130 pushl $0xabcdef05 /* recover address */
131 pushl $0xabcdef04 /* idt:base */
132 pushl $0xabcdef03 /* ldt + idt:limit */
133 pushl $0xabcdef02 /* gdt:base */
134 pushl $0xabcdef01 /* TR + gdt:limit */
135 pushl $0xabcdef00 /* CR0 */
138 #define CR0_REGISTER 0(%ebp)
139 #define TASK_REGISTER 4(%ebp)
140 #define PREVIOUS_GDT 6(%ebp)
141 #define PREVIOUS_LDT 12(%ebp)
142 #define PREVIOUS_IDT 14(%ebp)
143 #define RECOVER_ADDR 20(%ebp)
144 #define PHYSICAL_GDT_BASE 24(%ebp)
145 #define PREVIOUS_DS 28(%ebp)
146 #define PREVIOUS_ES 30(%ebp)
147 #define PREVIOUS_FS 32(%ebp)
148 #define PREVIOUS_GS 34(%ebp)
149 #define PREVIOUS_SS 36(%ebp)
151 /* Fixup TSS type field */
152 #define TSS_TYPEFIX_MASK 0xf9
154 movl PHYSICAL_GDT_BASE,%ebx
155 movw TASK_REGISTER,%si
156 leal (%ebx,%esi),%eax /* get TSS segment descriptor */
157 andb $TSS_TYPEFIX_MASK,5(%eax)
159 /* Prepare to return to sleep/wakeup code point */
169 movl PREVIOUS_DS,%ebx
170 movl PREVIOUS_FS,%ecx
171 movl PREVIOUS_SS,%edx
172 movw TASK_REGISTER,%si
174 movw PREVIOUS_LDT,%si
175 movl RECOVER_ADDR,%edi
177 /* Enable paging and etc. */
178 movl CR0_REGISTER,%eax
181 /* Flush the prefetch queue */
186 * Now that we are in kernel virtual memory addressing
191 * %edi: recover address
196 movl %esi,%eax /* LDTR + TR */
197 lldt %ax /* load LDT register */
199 ltr %ax /* load task register */
201 /* Restore segment registers */
202 movl %ebx,%eax /* ds + es */
206 movl %ecx,%eax /* fs + gs */
210 movl %edx,%eax /* ss */
213 /* Jump to acpi_restorecpu() */
216 /* used in real mode */
217 physical_gdt: .word 0
219 physical_esp: .long 0
220 previous_cr2: .long 0
221 previous_cr3: .long 0
222 previous_cr4: .long 0
225 /* transfer from real mode to protected mode */
226 previous_cr0: .long 0
228 previous_gdt: .word 0
230 previous_ldt: .word 0
231 previous_idt: .word 0
233 where_to_recover: .long 0