import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / i386 / kernel / acpi_wakeup.S
1
2 .text
3 #include <linux/linkage.h>
4 #include <asm/segment.h>
5
6
7 ALIGN
8 wakeup_start:
9 wakeup_code:
10         wakeup_code_start = .
11         .code16
12
13         cli
14         cld
15
16         # setup data segment
17         movw    %cs, %ax
18
19         addw    $(wakeup_data - wakeup_code) >> 4, %ax
20         movw    %ax, %ds
21         movw    %ax, %ss
22
23         # Private stack is needed for ASUS board
24         mov     $(wakeup_stack - wakeup_data), %sp
25
26         # set up page table
27         movl    (real_save_cr3 - wakeup_data), %eax
28         movl    %eax, %cr3
29
30         # make sure %cr4 is set correctly (features, etc)
31         movl    (real_save_cr4 - wakeup_data), %eax
32         movl    %eax, %cr4
33
34         # need a gdt
35         lgdt    real_save_gdt - wakeup_data
36
37         # Flush the prefetch queue
38         jmp 1f
39 1:
40
41         movl    %cr0, %eax
42         orl     $0x80000001, %eax
43         movl    %eax, %cr0
44
45         ljmpl   $__KERNEL_CS,$SYMBOL_NAME(wakeup_pmode_return)
46
47         .code32
48         ALIGN
49
50 .org    0x100
51 wakeup_data:
52                 .word 0
53 real_save_gdt:  .word 0
54                 .long 0
55 real_save_cr3:  .long 0
56 real_save_cr4:  .long 0
57
58 .org    0x300
59 wakeup_stack:
60 wakeup_end:
61
62 wakeup_pmode_return:
63         # restore data segment
64         movl    $__KERNEL_DS, %eax
65         movw    %ax, %ds
66         movw    %ax, %es
67
68         # and restore the stack
69         movw    %ax, %ss
70         movl    saved_esp, %esp
71
72         # restore other segment registers
73         xorl    %eax, %eax
74         movw    %ax, %fs
75         movw    %ax, %gs
76
77         # reload the gdt, as we need the full 32 bit address
78         lgdt    saved_gdt
79         lidt    saved_idt
80         lldt    saved_ldt
81
82         # restore the other general registers
83         movl    saved_ebx, %ebx
84         movl    saved_edi, %edi
85         movl    saved_esi, %esi
86         movl    saved_ebp, %ebp
87
88         # jump to place where we left off
89         movl    saved_eip,%eax
90         jmp     *%eax
91
92 ##
93 # acpi_copy_wakeup_routine
94 #
95 # Copy the above routine to low memory.
96 #
97 # Parameters:
98 # %eax: place to copy wakeup routine to
99 #
100 # Returned address is location of code in low memory (past data and stack)
101 #
102 ENTRY(acpi_copy_wakeup_routine)
103
104         pushl   %esi
105         pushl   %edi
106
107         sgdt    saved_gdt
108         sidt    saved_idt
109         sldt    saved_ldt
110         str     saved_tss
111
112         movl    %eax, %edi
113         leal    wakeup_start, %esi
114         movl    $(wakeup_end - wakeup_start) >> 2, %ecx
115
116         rep ;  movsl
117
118         movl    %cr3, %edx
119         movl    %edx, real_save_cr3 - wakeup_start (%eax)
120         movl    %cr4, %edx
121         movl    %edx, real_save_cr4 - wakeup_start (%eax)
122         sgdt    real_save_gdt - wakeup_start (%eax)
123
124         # restore the regs we used
125         popl    %edi
126         popl    %esi
127         ret
128
129
130 .data
131 ALIGN
132 # saved registers
133 saved_gdt:      .long   0,0
134 saved_idt:      .long   0,0
135 saved_ldt:      .long   0
136 saved_tss:      .long   0
137 saved_cr0:      .long   0
138
139 ENTRY(saved_ebp)        .long   0
140 ENTRY(saved_esi)        .long   0
141 ENTRY(saved_edi)        .long   0
142 ENTRY(saved_ebx)        .long   0
143
144 ENTRY(saved_eip)        .long   0
145 ENTRY(saved_esp)        .long   0