Merge from vendor branch LESS:
[dragonfly.git] / sys / platform / pc32 / acpica / acpi_wakecode.S
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: src/sys/i386/acpica/acpi_wakecode.S,v 1.2.2.1 2003/08/22 20:49:21 jhb Exp $
28  *      $DragonFly: src/sys/platform/pc32/acpica/Attic/acpi_wakecode.S,v 1.1 2003/09/24 03:32:16 drhodus Exp $ 
29  */
30
31 #define LOCORE
32
33 #include <machine/specialreg.h>
34
35         .align 4
36         .code16
37 wakeup_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
81 wakeup_sw32:
82         /* Switch to protected mode by intersegmental jump */
83         ljmpl   $0x8,$0x12345678        /* Code location, to be replaced */
84
85         .code32
86 wakeup_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
104 wakeup_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
163 1:      jmp     1f
164 1:
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 */
197 physical_gdt:           .word 0
198                         .long 0
199 physical_esp:           .long 0
200 previous_cr2:           .long 0
201 previous_cr3:           .long 0
202 previous_cr4:           .long 0
203
204 /* transfer from real mode to protected mode */
205 previous_cr0:           .long 0
206 previous_tr:            .word 0
207 previous_gdt:           .word 0
208                         .long 0
209 previous_ldt:           .word 0
210 previous_idt:           .word 0
211                         .long 0
212 where_to_recover:       .long 0
213 previous_ds:            .word 0
214 previous_es:            .word 0
215 previous_fs:            .word 0
216 previous_gs:            .word 0
217 previous_ss:            .word 0
218 dummy:                  .word 0
219