copy_and_run: drop boot_complete parameter
[gnutoo-for-coreboot:coreboot.git] / src / arch / x86 / lib / c_start.S
1 #include <cpu/x86/post_code.h>
2
3 /* Place the stack in the bss section. It's not necessary to define it in the
4  * the linker script. */
5         .section .bss, "aw", @nobits
6 .global _stack
7 .global _estack
8
9 .align CONFIG_STACK_SIZE
10 _stack:
11 .space CONFIG_MAX_CPUS*CONFIG_STACK_SIZE
12 _estack:
13
14         .section ".textfirst", "ax", @progbits
15         .code32
16         .globl _start
17 _start:
18         cli
19         lgdt    %cs:gdtaddr
20         ljmp    $0x10, $1f
21 1:      movl    $0x18, %eax
22         movl    %eax, %ds
23         movl    %eax, %es
24         movl    %eax, %ss
25         movl    %eax, %fs
26         movl    %eax, %gs
27
28         post_code(POST_ENTRY_C_START)           /* post 13 */
29
30         cld
31
32         /** poison the stack. Code should not count on the
33          * stack being full of zeros. This stack poisoning
34          * recently uncovered a bug in the broadcast SIPI
35          * code.
36          */
37         leal    _stack, %edi
38         movl    $_estack, %ecx
39         subl    %edi, %ecx
40         shrl    $2, %ecx   /* it is 32 bit aligned, right? */
41         movl    $0xDEADBEEF, %eax
42         rep
43         stosl
44
45         /* set new stack */
46         movl    $_estack, %esp
47
48         /* Push the cpu index and struct cpu */
49         pushl   $0
50         pushl   $0
51
52         /* Initialize the Interrupt Descriptor table */
53         leal    _idt, %edi
54         leal    vec0, %ebx
55         movl    $(0x10 << 16), %eax     /* cs selector */
56
57 1:      movw    %bx, %ax
58         movl    %ebx, %edx
59         movw    $0x8E00, %dx            /* Interrupt gate - dpl=0, present */
60         movl    %eax, 0(%edi)
61         movl    %edx, 4(%edi)
62         addl    $6, %ebx
63         addl    $8, %edi
64         cmpl    $_idt_end, %edi
65         jne     1b
66
67         /* Load the Interrupt descriptor table */
68         lidt    idtarg
69
70         /*
71          *      Now we are finished. Memory is up, data is copied and
72          *      bss is cleared.   Now we call the main routine and
73          *      let it do the rest.
74          */
75         post_code(POST_PRE_HARDWAREMAIN)        /* post fe */
76
77 #if CONFIG_GDB_WAIT
78         call gdb_stub_breakpoint
79 #endif
80         call    hardwaremain
81         /* NOTREACHED */
82 .Lhlt:
83         post_code(POST_DEAD_CODE)       /* post ee */
84         hlt
85         jmp     .Lhlt
86
87 vec0:
88         pushl   $0 /* error code */
89         pushl   $0 /* vector */
90         jmp int_hand
91 vec1:
92         pushl   $0 /* error code */
93         pushl   $1 /* vector */
94         jmp int_hand
95
96 vec2:
97         pushl   $0 /* error code */
98         pushl   $2 /* vector */
99         jmp int_hand
100
101 vec3:
102         pushl   $0 /* error code */
103         pushl   $3 /* vector */
104         jmp     int_hand
105
106 vec4:
107         pushl   $0 /* error code */
108         pushl   $4 /* vector */
109         jmp     int_hand
110
111 vec5:
112         pushl   $0 /* error code */
113         pushl   $5 /* vector */
114         jmp     int_hand
115
116 vec6:
117         pushl   $0 /* error code */
118         pushl   $6 /* vector */
119         jmp     int_hand
120
121 vec7:
122         pushl   $0 /* error code */
123         pushl   $7 /* vector */
124         jmp     int_hand
125
126 vec8:
127         /* error code */
128         pushl   $8 /* vector */
129         jmp     int_hand
130         .word   0x9090
131
132 vec9:
133         pushl   $0 /* error code */
134         pushl   $9 /* vector */
135         jmp int_hand
136
137 vec10:
138         /* error code */
139         pushl   $10 /* vector */
140         jmp     int_hand
141         .word   0x9090
142
143 vec11:
144         /* error code */
145         pushl   $11 /* vector */
146         jmp     int_hand
147         .word   0x9090
148
149 vec12:
150         /* error code */
151         pushl   $12 /* vector */
152         jmp     int_hand
153         .word   0x9090
154
155 vec13:
156         /* error code */
157         pushl   $13 /* vector */
158         jmp     int_hand
159         .word   0x9090
160
161 vec14:
162         /* error code */
163         pushl   $14 /* vector */
164         jmp     int_hand
165         .word   0x9090
166
167 vec15:
168         pushl   $0 /* error code */
169         pushl   $15 /* vector */
170         jmp     int_hand
171
172 vec16:
173         pushl   $0 /* error code */
174         pushl   $16 /* vector */
175         jmp     int_hand
176
177 vec17:
178         /* error code */
179         pushl   $17 /* vector */
180         jmp     int_hand
181         .word   0x9090
182
183 vec18:
184         pushl   $0 /* error code */
185         pushl   $18 /* vector */
186         jmp     int_hand
187
188 vec19:
189         pushl   $0 /* error code */
190         pushl   $19 /* vector */
191         jmp     int_hand
192
193 int_hand:
194         /* At this point on the stack there is:
195          *  0(%esp) vector
196          *  4(%esp) error code
197          *  8(%esp) eip
198          * 12(%esp) cs
199          * 16(%esp) eflags
200          */
201         pushl   %edi
202         pushl   %esi
203         pushl   %ebp
204         /* Original stack pointer */
205         leal    32(%esp), %ebp
206         pushl   %ebp
207         pushl   %ebx
208         pushl   %edx
209         pushl   %ecx
210         pushl   %eax
211
212         pushl   %esp    /* Pointer to structure on the stack */
213         call    x86_exception
214         pop     %eax    /* Drop the pointer */
215
216         popl    %eax
217         popl    %ecx
218         popl    %edx
219         popl    %ebx
220         popl    %ebp    /* Ignore saved %esp value */
221         popl    %ebp
222         popl    %esi
223         popl    %edi
224
225         addl    $8, %esp /* pop of the vector and error code */
226
227         iret
228
229 #if CONFIG_GDB_WAIT
230
231         .globl gdb_stub_breakpoint
232 gdb_stub_breakpoint:
233         popl    %eax    /* Return address */
234         pushfl
235         pushl   %cs
236         pushl   %eax    /* Return address */
237         pushl   $0      /* No error code */
238         pushl   $32     /* vector 32 is user defined */
239         jmp     int_hand
240
241 #endif
242
243         .globl gdt, gdt_end, idtarg
244
245 gdtaddr:
246         .word   gdt_end - gdt - 1
247         .long   gdt             /* we know the offset */
248
249          .data
250
251         /* This is the gdt for GCC part of coreboot.
252          * It is different from the gdt in ROMCC/ASM part of coreboot
253          * which is defined in entry32.inc
254          *
255          * When the machine is initially started, we use a very simple
256          * gdt from rom (that in entry32.inc) which only contains those
257          * entries we need for protected mode.
258          *
259          * When we're executing code from RAM, we want to do more complex
260          * stuff, like initializing PCI option roms in real mode, or doing
261          * a resume from a suspend to ram.
262          */
263 gdt:
264         /* selgdt 0, unused */
265         .word   0x0000, 0x0000          /* dummy */
266         .byte   0x00, 0x00, 0x00, 0x00
267
268         /* selgdt 8, unused */
269         .word   0x0000, 0x0000          /* dummy */
270         .byte   0x00, 0x00, 0x00, 0x00
271
272         /* selgdt 0x10, flat code segment */
273         .word   0xffff, 0x0000
274         .byte   0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
275
276         /* selgdt 0x18, flat data segment */
277         .word   0xffff, 0x0000
278         .byte   0x00, 0x93, 0xcf, 0x00
279
280         /* selgdt 0x20, unused */
281         .word   0x0000, 0x0000          /* dummy */
282         .byte   0x00, 0x00, 0x00, 0x00
283
284         /* The next two entries are used for executing VGA option ROMs */
285
286         /* selgdt 0x28 16 bit 64k code at 0x00000000 */
287         .word   0xffff, 0x0000
288         .byte   0, 0x9a, 0, 0
289
290         /* selgdt 0x30 16 bit 64k data at 0x00000000 */
291         .word   0xffff, 0x0000
292         .byte   0, 0x92, 0, 0
293
294         /* The next two entries are used for ACPI S3 RESUME */
295
296         /* selgdt 0x38, flat data segment 16 bit */
297         .word   0x0000, 0x0000          /* dummy */
298         .byte   0x00, 0x93, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
299
300         /* selgdt 0x40, flat code segment 16 bit */
301         .word   0xffff, 0x0000
302         .byte   0x00, 0x9b, 0x8f, 0x00 /* G=1 and 0x0f, So we get 4Gbytes for limit */
303 gdt_end:
304
305 idtarg:
306         .word   _idt_end - _idt - 1     /* limit */
307         .long   _idt
308         .word   0
309 _idt:
310         .fill   20, 8, 0        # idt is uninitialized
311 _idt_end:
312
313         .previous
314 .code32