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