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