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.2.2.1 2003/08/22 20:49:21 jhb Exp $
28 * $DragonFly: src/sys/i386/acpica/Attic/acpi_wakecode.S,v 1.1 2003/09/24 03:32:16 drhodus Exp $
33 #include <machine/specialreg.h>
41 /* Set up segment registers for real mode */
46 /* Load GDT for real mode */
49 /* Restore CR2, CR3 and CR4 */
57 /* Transfer some values to protected mode */
59 #define TRANSFER_STACK32(val, idx) \
61 mov %eax,wakeup_32stack+(idx+1)+(idx*4);
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))
74 mov physical_esp,%esi /* to be used in 32bit code */
76 /* Enable protected mode */
82 /* Switch to protected mode by intersegmental jump */
83 ljmpl $0x8,$0x12345678 /* Code location, to be replaced */
88 * Switched to protected mode w/o paging
89 * %esi: KERNEL stack pointer (physical address)
94 /* Set up segment registers for protected mode */
95 movw $0x10,%ax /* KDSEL to segment registers */
100 movw $0x18,%ax /* KPSEL to %fs */
102 movl %esi,%esp /* physical address stack pointer */
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 */
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)
131 /* Fixup TSS type field */
132 #define TSS_TYPEFIX_MASK 0xf9
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)
139 /* Prepare to return to sleep/wakeup code point */
149 movl PREVIOUS_DS,%ebx
150 movl PREVIOUS_FS,%ecx
151 movl PREVIOUS_SS,%edx
152 movw TASK_REGISTER,%si
154 movw PREVIOUS_LDT,%si
155 movl RECOVER_ADDR,%edi
157 /* Enable paging and etc. */
158 movl CR0_REGISTER,%eax
161 /* Flush the prefetch queue */
166 * Now that we are in kernel virtual memory addressing
171 * %edi: recover address
176 movl %esi,%eax /* LDTR + TR */
177 lldt %ax /* load LDT register */
179 ltr %ax /* load task register */
181 /* Restore segment registers */
182 movl %ebx,%eax /* ds + es */
186 movl %ecx,%eax /* fs + gs */
190 movl %edx,%eax /* ss */
193 /* Jump to acpi_restorecpu() */
196 /* used in real mode */
197 physical_gdt: .word 0
199 physical_esp: .long 0
200 previous_cr2: .long 0
201 previous_cr3: .long 0
202 previous_cr4: .long 0
204 /* transfer from real mode to protected mode */
205 previous_cr0: .long 0
207 previous_gdt: .word 0
209 previous_ldt: .word 0
210 previous_idt: .word 0
212 where_to_recover: .long 0