]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/kern/ia32/tramp-acpi.S
Some minor fixes.
[l4.git] / kernel / fiasco / src / kern / ia32 / tramp-acpi.S
1 /* -*- c -*- */
2 #include "config_gdt.h"
3 #include "linking.h"
4 #include "regdefs.h"
5 #include "tramp-realmode.h"
6
7 #ifdef CONFIG_AMD64
8 # define BX rbx
9 #else
10 # define BX ebx
11 #endif
12
13 #define SET_VIDEO_MODE 0
14 #define WAK_STS 0x8000
15 #define SLEEP_EN 0x2000
16
17 /* (c) 2013 Steffen Liebergeld <steffen.liebergeld@kernkonzept.com> */
18
19 /* 
20  * Acpi wakeup code.
21  * 
22  * We are thrown out of sleep directly into real mode. Therefore we must be
23  * below 1MB! We pack it into the .realmode_tramp section, which starts at
24  * 0x1000. 
25  */
26   .section .realmode_tramp , "awx", @progbits
27
28   .code16
29   .align 16
30   .globl _tramp_acpi_wakeup
31 _tramp_acpi_wakeup:
32   cli
33   cld
34   RM_LOAD_SEGMENT_BASE
35   movw  $RM_OFFS(_acpi_rm_stack_top), %sp
36
37   /* Clear all CPU flags */
38   pushl $0
39   popfl
40
41 #if SET_VIDEO_MODE
42   /*
43    * Mask everything in the PIC for some reason the PIT timer is
44    * unmasked which causes spurious calls to IDT vecotor zero at least
45    * during video mode reset.
46    */
47   mov $0xff, %al
48   outb %al, $0xa1
49   outb %al, $0x21
50
51   /* IDT needed for BIOS */
52   lidtw RM_OFFS(rm_idt_desc)
53
54   cld
55   cli
56
57   /* Call the bios */
58   lcallw $0xc000,$3
59   RM_LOAD_SEGMENT_BASE
60
61   cld
62   cli
63
64   /* set graphics mode */
65   mov  $3, %ax
66   int  $0x10
67
68   RM_LOAD_SEGMENT_BASE
69 #endif
70
71   ENTER_PROTECTED_MODE
72   /* 32bit code follows */
73   ENABLE_PAGING cr0=_cr0 cr3=_cr3 cr4=_cr4 gdt=_gdt
74
75   lidt _idt
76   lldt _ldt
77
78 #if 0
79   movw _fs, %ax
80   movw %ax, %fs
81   movw _gs, %ax
82   movw %ax, %gs
83 #endif
84
85   /* restore general purpose registers */
86 #ifdef CONFIG_AMD64
87   mov _sp, %rsp
88   pop %rbx
89   pop %rbp
90   pop %r8
91   pop %r9
92   pop %r10
93   pop %r11
94   pop %r12
95   pop %r13
96   pop %r14
97   pop %r15
98   popfq
99 #else
100   mov _sp, %esp
101   pop %ebx
102   pop %esi
103   pop %edi
104   pop %ebp
105   popfl
106 #endif
107
108   /* we cleared the busy flag in C++ code before suspend, so its save to load the TR here */
109   ltr _tr
110   movl $0, %eax // return 0 (success)
111   ret                   // return from function "acpi_save_cpu_and_suspend"
112
113   /* small stack needed for bios call */
114   .align 16
115   .space 0x90, 0
116 _acpi_rm_stack_top:
117
118 #if SET_VIDEO_MODE
119   /* Real mode IDT descriptor for bios IDT at physical address zero. */
120 .align 16
121 rm_idt_desc:
122   .word 0xffff
123   .long 0
124 #endif
125
126
127 _wakeup_header:
128 _cr0:   .quad 0
129 _cr3:   .quad 0
130 _cr4:   .quad 0
131 _sp:    .quad 0
132 _gdt:   .quad 0
133         .quad 0
134 _idt:   .quad 0
135         .quad 0
136 _ldt:   .quad 0
137         .quad 0
138 #if 0
139 _fs:    .word 0
140 _gs:    .word 0
141 #endif
142
143 _tr:    .quad 0 /* task register */
144         .quad 0
145
146 // normal code called from C++
147
148 .section .text.acpi_suspend , "ax", @progbits
149   .align 16, 0x90
150   .globl acpi_save_cpu_and_suspend
151 acpi_save_cpu_and_suspend:
152   /**
153    * int FIASCO_FASTCALL acpi_save_cpu_and_suspend(Unsigned32 sleep_type,
154    *                                               Unsigned32 pm1_control_block,
155    *                                               Unsigned32 pm1_event_block);
156    * sleep_type = sleep_type_a | sleep_type_b
157    * pm1_control_block = (pm1b_cntl_blk << 16) | pm1a_cntl_blk
158    * pm1_event_block = (pm1b_evt_blk << 16) | pm1b_evt_blk
159    * Called from do_suspend_system in platform_control-acpi_sleep.cpp
160    * Function will return 1 on error (suspend failed).
161    * It will return 0 after system wakeup (suspend succeeded).
162    */
163
164 #ifdef CONFIG_AMD64
165   pushfq
166   push %r15
167   push %r14
168   push %r13
169   push %r12
170   push %r11
171   push %r10
172   push %r9
173   push %r8
174   push %rbp
175   push %rbx
176   mov %rsp, _sp
177 #else
178   pushfl
179   push %ebp
180   push %edi
181   push %esi
182   push %ebx
183   mov %esp, _sp
184 #endif
185
186   /* save control registers */
187   mov %cr0, %BX
188   mov %BX, _cr0
189   mov %cr3, %BX
190   mov %BX, _cr3
191   mov %cr4, %BX
192   mov %BX, _cr4
193
194 #if 0
195   movw %fs, %bx
196   movw %bx, _fs
197   movw %gs, %bx
198   movw %bx, _gs
199 #endif
200
201   str _tr
202   /* save descriptor table (registers) */
203   sgdt _gdt
204   sidt _idt
205   sldt _ldt
206
207   wbinvd
208
209   /* 32bit: eax = sleep_type,
210             edx = (pm1b_cntl << 16) | pm1a_cntl,
211             ecx = (pm1b_sts  << 16) | pm1a_sts */
212   /* 64bit: rdi = sleep_type,
213             rsi = (pm1b_cntl << 16) | pm1a_cntl,
214             rdx = (pm1b_sts  << 16) | pm1a_sts */
215
216 #ifdef CONFIG_AMD64
217   mov %rdx, %rcx
218 #else
219   mov %eax, %edi
220   mov %edx, %esi
221 #endif
222
223   /* 32/64bit: di = sleep_type,
224               esi = (pm1b_cntl << 16) | pm1a_cntl,
225               ecx = (pm1b_sts  << 16) | pm1a_sts */
226
227   mov %edi, %ebx
228   shl $10, %ebx
229   mov %esi, %edx
230
231   in  %dx,      %ax   // read from dx into ax
232   or  %bx,      %ax
233   or  $SLEEP_EN, %ax
234   out %ax,      %dx  // write ax to dx
235
236   shr $16, %esi
237   cmp $0, %si
238   je  out
239
240   mov %edi, %ebx
241   shr $8, %ebx
242   shl $10, %ebx
243   mov %esi, %edx
244
245   in  %dx,      %ax
246   or  %bx,      %ax
247   or  $SLEEP_EN, %ax
248   out %ax,      %dx
249
250   // platform will now enter S3, which may or may not take some time
251   // until then we loop on the WAK_STS bit as implemented in
252   // pkg/acpica/lib-acpi/src/acpica/components/hardware/hwsleep.c
253   // (AcpiHwLegacySleep)
254 out:
255   /* 32/64 bit ecx = (pm1b_sts << 16) | pm1a_sts */
256   mov %ecx, %edx
257   in  %dx, %ax
258   and $WAK_STS, %ax
259   mov %ax, %bx
260   shr $16, %edx
261   in  %dx, %ax
262   and $WAK_STS, %ax
263   or  %bx, %ax
264   cmp $WAK_STS, %ax
265   jnz out
266
267   /* if we reach this code, suspend failed (this should *never* happen) */
268   /* otherwise the machine started up from from _tramp_acpi_wakeup */
269   movl $1, %eax
270   ret
271