1
2
3
4
5
6
7
8
9
10
11 .text
12 #include <linux/config.h>
13 #include <linux/tasks.h>
14 #include <linux/fd.h>
15 #include <linux/linkage.h>
16 #include <asm/segment.h>
17
18 #define CL_MAGIC_ADDR 0x90020
19 #define CL_MAGIC 0xA33F
20 #define CL_BASE_ADDR 0x90000
21 #define CL_OFFSET 0x90022
22
23
24
25
26
27 ENTRY(stext)
28 ENTRY(_stext)
29 startup_32:
30 cld
31 movl $(KERNEL_DS),%eax
32 mov %ax,%ds
33 mov %ax,%es
34 mov %ax,%fs
35 mov %ax,%gs
36 #ifdef CONFIG_SMP
37 orw %bx,%bx
38 jz 1f
39
40
41
42 mov %ax,%ss
43 xorl %eax,%eax
44 movw %cx, %ax
45 movl %eax,%esp
46 pushl $0
47 popfl
48 jmp checkCPUtype
49 1:
50 lss stack_start,%esp
51 #endif CONFIG_SMP
52
53
54
55 xorl %eax,%eax
56 movl $ SYMBOL_NAME(_edata),%edi
57 movl $ SYMBOL_NAME(_end),%ecx
58 subl %edi,%ecx
59 cld
60 rep
61 stosb
62
63
64
65
66 call setup_idt
67 xorl %eax,%eax
68 1: incl %eax # check that A20 really IS enabled
69 movl %eax,0x000000 # loop forever if it isn't
70 cmpl %eax,0x100000
71 je 1b
72
73
74
75
76
77 pushl $0
78 popfl
79
80
81
82
83
84 movl $0x90000,%esi
85 movl $ SYMBOL_NAME(empty_zero_page),%edi
86 movl $512,%ecx
87 cld
88 rep
89 movsl
90 xorl %eax,%eax
91 movl $512,%ecx
92 rep
93 stosl
94 cmpw $(CL_MAGIC),CL_MAGIC_ADDR
95 jne 1f
96 movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
97 movzwl CL_OFFSET,%esi
98 addl $(CL_BASE_ADDR),%esi
99 movl $2048,%ecx
100 rep
101 movsb
102 1:
103 #ifdef CONFIG_SMP
104 checkCPUtype:
105 #endif
106
107
108
109
110
111
112
113 movl $3, SYMBOL_NAME(x86)
114 pushfl # push EFLAGS
115 popl %eax # get EFLAGS
116 movl %eax,%ecx # save original EFLAGS
117 xorl $0x40000,%eax # flip AC bit in EFLAGS
118 pushl %eax # copy to EFLAGS
119 popfl # set EFLAGS
120 pushfl # get new EFLAGS
121 popl %eax # put it in eax
122 xorl %ecx,%eax # change in flags
123 andl $0x40000,%eax # check if AC bit changed
124 je is386
125 movl $4,SYMBOL_NAME(x86)
126 movl %ecx,%eax
127 xorl $0x200000,%eax # check ID flag
128 pushl %eax
129 popfl # if we are on a straight 486DX, SX, or
130 pushfl # 487SX we can't change it
131 popl %eax
132 xorl %ecx,%eax
133 andl $0x200000,%eax
134 je is486
135 isnew: pushl %ecx # restore original EFLAGS
136 popfl
137
138 movl $1, %eax # Use the CPUID instruction to
139 .byte 0x0f, 0xa2 # check the processor type
140 movb %al, %cl # save reg for future use
141 andb $0x0f,%ah # mask processor family
142 movb %ah,SYMBOL_NAME(x86)
143 andb $0xf0, %eax # mask model
144 shrb $4, %al
145 movb %al,SYMBOL_NAME(x86_model)
146 andb $0x0f, %cl # mask mask revision
147 movb %cl,SYMBOL_NAME(x86_mask)
148 movl %edx,SYMBOL_NAME(x86_capability)
149
150 xorl %eax, %eax # call CPUID with 0 -> return vendor ID
151 .byte 0x0f, 0xa2 # CPUID
152 movl %ebx,SYMBOL_NAME(x86_vendor_id) # lo 4 chars
153 movl %edx,SYMBOL_NAME(x86_vendor_id)+4 # next 4 chars
154 movl %ecx,SYMBOL_NAME(x86_vendor_id)+8 # last 4 chars
155
156 movl %cr0,%eax # 486+
157 andl $0x80000011,%eax # Save PG,PE,ET
158 orl $0x50022,%eax # set AM, WP, NE and MP
159 jmp 2f
160 is486: pushl %ecx # restore original EFLAGS
161 popfl
162 movl %cr0,%eax # 486
163 andl $0x80000011,%eax # Save PG,PE,ET
164 orl $0x50022,%eax # set AM, WP, NE and MP
165 jmp 2f
166 is386: pushl %ecx # restore original EFLAGS
167 popfl
168 movl %cr0,%eax # 386
169 andl $0x80000011,%eax # Save PG,PE,ET
170 orl $2,%eax # set MP
171 2: movl %eax,%cr0
172 call check_x87
173 #ifdef CONFIG_SMP
174 movb ready,%eax
175 orb %eax,%eax
176 jz 3f
177 movl $ SYMBOL_NAME(swapper_pg_dir), %eax
178 movl %eax, %cr3
179 #ifdef GAS_KNOWS_CR4
180 movl %cr4,%eax
181 orl $16,%eax
182 movl %eax,%cr4
183 #else
184 .byte 0x0f,0x20,0xe0
185 orl $16,%eax
186 .byte 0x0f,0x22,0xe0
187 #endif
188 movl %cr0, %eax
189 orl $0x80000000, %eax
190 movl %eax, %cr0
191 jmp 4f
192 #endif
193 3:
194 call setup_paging
195 #ifdef CONFIG_SMP
196 incb ready
197 #endif
198 4:
199 lgdt gdt_descr
200 lidt idt_descr
201 ljmp $(KERNEL_CS),$1f
202 1: movl $(KERNEL_DS),%eax # reload all the segment registers
203 mov %ax,%ds # after changing gdt.
204 mov %ax,%es
205 mov %ax,%fs
206 mov %ax,%gs
207 #ifdef CONFIG_SMP
208 movl $(KERNEL_DS), %eax
209 mov %ax,%ss # Reload the stack pointer (segment only)
210 #else
211 lss stack_start,%esp # Load processor stack
212 #endif
213 xorl %eax,%eax
214 lldt %ax
215 pushl %eax # These are the parameters to main :-)
216 pushl %eax
217 pushl %eax
218 cld # gcc2 wants the direction flag cleared at all times
219 call SYMBOL_NAME(start_kernel)
220 L6:
221 jmp L6 # main should never return here, but
222
223
224 #ifdef CONFIG_SMP
225 ready: .byte 0
226 #endif
227
228
229
230
231 check_x87:
232 movb $0,SYMBOL_NAME(hard_math)
233 clts
234 fninit
235 fstsw %ax
236 cmpb $0,%al
237 je 1f
238 movl %cr0,%eax
239 xorl $4,%eax
240 movl %eax,%cr0
241 ret
242 ALIGN
243 1: movb $1,SYMBOL_NAME(hard_math)
244 .byte 0xDB,0xE4
245 ret
246
247
248
249
250
251
252
253
254
255
256
257 setup_idt:
258 lea ignore_int,%edx
259 movl $(KERNEL_CS << 16),%eax
260 movw %dx,%ax
261 movw $0x8E00,%dx
262
263 lea SYMBOL_NAME(idt),%edi
264 mov $256,%ecx
265 rp_sidt:
266 movl %eax,(%edi)
267 movl %edx,4(%edi)
268 addl $8,%edi
269 dec %ecx
270 jne rp_sidt
271 ret
272
273
274
275
276
277
278
279
280
281
282
283
284
285 ALIGN
286 setup_paging:
287 movl $1024*2,%ecx
288 xorl %eax,%eax
289 movl $ SYMBOL_NAME(swapper_pg_dir),%edi
290 cld;rep;stosl
291
292
293 movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)
294
295
296 movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)+3072
297 movl $ SYMBOL_NAME(pg0)+4092,%edi
298 movl $0x03ff007,%eax
299 std
300 1: stosl
301 subl $0x1000,%eax
302 jge 1b
303 cld
304 movl $ SYMBOL_NAME(swapper_pg_dir),%eax
305 movl %eax,%cr3
306 movl %cr0,%eax
307 orl $0x80000000,%eax
308 movl %eax,%cr0
309 ret
310
311
312
313
314
315
316
317
318
319
320
321 .org 0x1000
322 ENTRY(swapper_pg_dir)
323
324
325
326
327 .org 0x2000
328 ENTRY(pg0)
329
330 .org 0x3000
331 ENTRY(empty_bad_page)
332
333 .org 0x4000
334 ENTRY(empty_bad_page_table)
335
336 .org 0x5000
337 ENTRY(empty_zero_page)
338
339 .org 0x6000
340
341 stack_start:
342 .long SYMBOL_NAME(init_user_stack)+4096
343 .long KERNEL_DS
344
345
346 int_msg:
347 .asciz "Unknown interrupt\n"
348 ALIGN
349 ignore_int:
350 cld
351 pushl %eax
352 pushl %ecx
353 pushl %edx
354 push %ds
355 push %es
356 push %fs
357 movl $(KERNEL_DS),%eax
358 mov %ax,%ds
359 mov %ax,%es
360 mov %ax,%fs
361 pushl $int_msg
362 call SYMBOL_NAME(printk)
363 popl %eax
364 pop %fs
365 pop %es
366 pop %ds
367 popl %edx
368 popl %ecx
369 popl %eax
370 iret
371
372
373
374
375 ALIGN
376 .word 0
377 idt_descr:
378 .word 256*8-1 # idt contains 256 entries
379 .long 0xc0000000+SYMBOL_NAME(idt)
380
381 ENTRY(idt)
382 .fill 256,8,0 # idt is uninitialized
383
384 ALIGN
385 .word 0
386 gdt_descr:
387 .word (8+2*NR_TASKS)*8-1
388 .long 0xc0000000+SYMBOL_NAME(gdt)
389
390
391
392
393
394 ENTRY(gdt)
395 .quad 0x0000000000000000
396 .quad 0x0000000000000000
397 .quad 0xc0c39a000000ffff
398 .quad 0xc0c392000000ffff
399 .quad 0x00cbfa000000ffff
400 .quad 0x00cbf2000000ffff
401 .quad 0x0000000000000000
402 .quad 0x0000000000000000
403 .fill 2*NR_TASKS,8,0