Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openbios / arch / x86 / entry.S
1         .globl  entry, __switch_context, __exit_context, halt, init_exceptions
2
3         .text
4         .align  4
5
6 /*
7  * Entry point
8  * We start execution from here.
9  * It is assumed that CPU is in 32-bit protected mode and
10  * all segments are 4GB and base zero (flat model).
11  */
12 entry:
13         /* Save boot context and switch to our main context.
14          * Main context is statically defined in C.
15          */
16         pushl   %cs
17         call    __switch_context
18
19         /* We get here when the main context switches back to
20          * the boot context.
21          * Return to previous bootloader.
22          */
23         ret
24
25 /*
26  * Switch execution context
27  * This saves registers, segments, and GDT in the stack, then
28  * switches the stack, and restores everything from the new stack.
29  * This function takes no argument. New stack pointer is
30  * taken from global variable __context, and old stack pointer
31  * is also saved to __context. This way we can just jump to
32  * this routine to get back to the original context.
33  *
34  * Call this routine with lcall or pushl %cs; call.
35  */
36 __switch_context:
37         /* Save everything in current stack */
38         pushfl              /* 56 */
39         pushl   %ds         /* 52 */
40         pushl   %es         /* 48 */
41         pushl   %fs         /* 44 */
42         pushl   %gs         /* 40 */
43         pushal              /* 8 */
44         subl    $8, %esp
45         movw    %ss, (%esp) /* 0 */
46         sgdt    2(%esp)     /* 2 */
47
48 #if 0
49         /* Swap %cs and %eip on the stack, so lret will work */
50         movl    60(%esp), %eax
51         xchgl   %eax, 64(%esp)
52         movl    %eax, 60(%esp)
53 #endif
54
55         /* At this point we don't know if we are on flat segment
56          * or relocated. So compute the address offset from %eip.
57          * Assuming CS.base==DS.base==SS.base.
58          */
59         call    1f
60 1:      popl    %ebx
61         subl    $1b, %ebx
62
63         /* Interrupts are not allowed... */
64         cli
65
66         /* Current context pointer is our stack pointer */
67         movl    %esp, %esi
68
69         /* Normalize the ctx pointer */
70         subl    %ebx, %esi
71
72         /* Swap it with new value */
73         xchgl   %esi, __context(%ebx)
74
75         /* Adjust new ctx pointer for current address offset */
76         addl    %ebx, %esi
77
78         /* Load new %ss and %esp to temporary */
79         movzwl  (%esi), %edx
80         movl    20(%esi), %eax
81
82         /* Load new GDT */
83         lgdt    2(%esi)
84
85         /* Load new stack segment with new GDT */
86         movl    %edx, %ss
87
88         /* Set new stack pointer, but we have to adjust it because
89          * pushal saves %esp value before pushal, and we want the value
90          * after pushal.
91          */
92         leal    -32(%eax), %esp
93
94         /* Load the rest from new stack */
95         popal
96         popl    %gs
97         popl    %fs
98         popl    %es
99         popl    %ds
100         popfl
101
102         /* Finally, load new %cs and %eip */
103         lret
104
105 __exit_context:
106         /* Get back to the original context */
107         pushl   %cs
108         call    __switch_context
109
110         /* We get here if the other context attempt to switch to this
111          * dead context. This should not happen. */
112
113 halt:
114         cli
115         hlt
116         jmp     halt
117
118 /*
119  * initialize exception handler. All exceptions end up in the same
120  * C function.
121  */
122
123 init_exceptions:
124         pushl   %ebx
125         pushl   %edi
126
127         /* Initialize the Interrupt Descriptor table */
128         leal    _idt, %edi
129         leal    vec0, %ebx
130         movl    $(0x08 << 16), %eax     /* cs selector */
131
132 1:      movw    %bx, %ax
133         movl    %ebx, %edx
134         movw    $0x8E00, %dx            /* Interrupt gate - dpl=0, present */
135         movl    %eax, 0(%edi)
136         movl    %edx, 4(%edi)
137         addl    $6, %ebx
138         addl    $8, %edi
139         cmpl    $_idt_end, %edi
140         jne     1b
141
142         /* Load the Interrupt descriptor table */
143         lidt    idtarg
144
145         movl    $0, %eax
146         popl    %edi
147         popl    %ebx
148         ret
149
150 vec0:
151         pushl   $0 /* error code */
152         pushl   $0 /* vector */
153         jmp int_hand
154 vec1:
155         pushl   $0 /* error code */
156         pushl   $1 /* vector */
157         jmp int_hand
158
159 vec2:
160         pushl   $0 /* error code */
161         pushl   $2 /* vector */
162         jmp int_hand
163
164 vec3:
165         pushl   $0 /* error code */
166         pushl   $3 /* vector */
167         jmp     int_hand
168
169 vec4:
170         pushl   $0 /* error code */
171         pushl   $4 /* vector */
172         jmp     int_hand
173
174 vec5:
175         pushl   $0 /* error code */
176         pushl   $5 /* vector */
177         jmp     int_hand
178
179 vec6:
180         pushl   $0 /* error code */
181         pushl   $6 /* vector */
182         jmp     int_hand
183 vec7:
184         pushl   $0 /* error code */
185         pushl   $7 /* vector */
186         jmp     int_hand
187
188 vec8:
189         /* error code */
190         pushl   $8 /* vector */
191         jmp     int_hand
192         .word   0x9090
193
194 vec9:
195         pushl   $0 /* error code */
196         pushl   $9 /* vector */
197         jmp int_hand
198
199 vec10:
200         /* error code */
201         pushl   $10 /* vector */
202         jmp     int_hand
203         .word   0x9090
204
205 vec11:
206         /* error code */
207         pushl   $11 /* vector */
208         jmp     int_hand
209         .word   0x9090
210
211 vec12:
212         /* error code */
213         pushl   $12 /* vector */
214         jmp     int_hand
215         .word   0x9090
216
217 vec13:
218         /* error code */
219         pushl   $13 /* vector */
220         jmp     int_hand
221         .word   0x9090
222
223 vec14:
224         /* error code */
225         pushl   $14 /* vector */
226         jmp     int_hand
227         .word   0x9090
228
229 vec15:
230         pushl   $0 /* error code */
231         pushl   $15 /* vector */
232         jmp     int_hand
233
234 vec16:
235         pushl   $0 /* error code */
236         pushl   $16 /* vector */
237         jmp     int_hand
238
239 vec17:
240         /* error code */
241         pushl   $17 /* vector */
242         jmp     int_hand
243         .word   0x9090
244
245 vec18:
246         pushl   $0 /* error code */
247         pushl   $18 /* vector */
248         jmp     int_hand
249
250 vec19:
251         pushl   $0 /* error code */
252         pushl   $19 /* vector */
253         jmp     int_hand
254
255 __divide_error:
256         pushl   $0 /* error code */
257         pushl   $20 /* vector */
258         jmp     int_hand
259         .global __divide_error
260
261 int_hand:
262         /* At this point on the stack there is:
263          *  0(%esp) vector
264          *  4(%esp) error code
265          *  8(%esp) eip
266          * 12(%esp) cs
267          * 16(%esp) eflags
268          */
269         pushl   %edi
270         pushl   %esi
271         pushl   %ebp
272         /* Original stack pointer */
273         leal    32(%esp), %ebp
274         pushl   %ebp
275         pushl   %ebx
276         pushl   %edx
277         pushl   %ecx
278         pushl   %eax
279
280         pushl   %esp    /* Pointer to structure on the stack */
281
282         call    x86_exception
283         pop     %eax    /* Drop the pointer */
284
285         popl    %eax
286         popl    %ecx
287         popl    %edx
288         popl    %ebx
289         popl    %ebp /* Ignore saved %esp value */
290         popl    %ebp
291         popl    %esi
292         popl    %edi
293
294         addl    $8, %esp /* pop of the vector and error code */
295
296         iret
297
298 idtarg:
299         .word   _idt_end - _idt - 1     /* limit */
300         .long   _idt
301         .word   0
302 _idt:
303         .fill   20, 8, 0        # idt is unitiailzed
304 _idt_end:
305
306         .globl  arch_nvram_size, arch_nvram_get, arch_nvram_put
307 arch_nvram_size:
308         xor     %eax, %eax
309         ret
310
311 arch_nvram_get:
312         ret
313
314 arch_nvram_put:
315         ret