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 #include <linux/config.h>
16
17 #define CL_MAGIC_ADDR 0x90020
18 #define CL_MAGIC 0xA33F
19 #define CL_BASE_ADDR 0x90000
20 #define CL_OFFSET 0x90022
21
22
23
24
25
26 ENTRY(stext)
27 ENTRY(_stext)
28 startup_32:
29 cld
30 movl $(KERNEL_DS),%eax
31 mov %ax,%ds
32 mov %ax,%es
33 mov %ax,%fs
34 mov %ax,%gs
35 #ifdef __SMP__
36 orw %bx,%bx
37 jz 1f
38
39
40
41 mov %ax,%ss
42 xorl %eax,%eax
43 movw %cx, %ax
44 movl %eax,%esp
45 pushl $0
46 popfl
47 jmp checkCPUtype
48 1:
49 lss stack_start,%esp
50 #endif __SMP__
51
52
53
54 xorl %eax,%eax
55 movl $ SYMBOL_NAME(_edata),%edi
56 movl $ SYMBOL_NAME(_end),%ecx
57 subl %edi,%ecx
58 cld
59 rep
60 stosb
61
62
63
64
65 call setup_idt
66 xorl %eax,%eax
67 1: incl %eax # check that A20 really IS enabled
68 movl %eax,0x000000 # loop forever if it isn't
69 cmpl %eax,0x100000
70 je 1b
71
72
73
74
75
76 pushl $0
77 popfl
78
79
80
81
82
83 movl $0x90000,%esi
84 movl $ SYMBOL_NAME(empty_zero_page),%edi
85 movl $512,%ecx
86 cld
87 rep
88 movsl
89 xorl %eax,%eax
90 movl $512,%ecx
91 rep
92 stosl
93 cmpw $(CL_MAGIC),CL_MAGIC_ADDR
94 jne 1f
95 movl $ SYMBOL_NAME(empty_zero_page)+2048,%edi
96 movzwl CL_OFFSET,%esi
97 addl $(CL_BASE_ADDR),%esi
98 movl $2048,%ecx
99 rep
100 movsb
101 1:
102 #ifdef __SMP__
103 checkCPUtype:
104 #endif
105
106
107
108
109
110
111
112 movl $3, SYMBOL_NAME(x86)
113 pushfl # push EFLAGS
114 popl %eax # get EFLAGS
115 movl %eax,%ecx # save original EFLAGS
116 xorl $0x40000,%eax # flip AC bit in EFLAGS
117 pushl %eax # copy to EFLAGS
118 popfl # set EFLAGS
119 pushfl # get new EFLAGS
120 popl %eax # put it in eax
121 xorl %ecx,%eax # change in flags
122 andl $0x40000,%eax # check if AC bit changed
123 je is386
124 movl $4,SYMBOL_NAME(x86)
125 movl %ecx,%eax
126 xorl $0x200000,%eax # check ID flag
127 pushl %eax
128 popfl # if we are on a straight 486DX, SX, or
129 pushfl # 487SX we can't change it
130 popl %eax
131 xorl %ecx,%eax
132 andl $0x200000,%eax
133 je is486
134 isnew: pushl %ecx # restore original EFLAGS
135 popfl
136 incl SYMBOL_NAME(have_cpuid) # we have CPUID
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 __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 __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 __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 __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 #ifdef CONFIG_APM
388 .word (11+2*NR_TASKS)*8-1
389 #else
390 .word (8+2*NR_TASKS)*8-1
391 #endif
392 .long 0xc0000000+SYMBOL_NAME(gdt)
393
394
395
396
397
398 ENTRY(gdt)
399 .quad 0x0000000000000000
400 .quad 0x0000000000000000
401 .quad 0xc0c39a000000ffff
402 .quad 0xc0c392000000ffff
403 .quad 0x00cbfa000000ffff
404 .quad 0x00cbf2000000ffff
405 .quad 0x0000000000000000
406 .quad 0x0000000000000000
407 .fill 2*NR_TASKS,8,0
408 #ifdef CONFIG_APM
409 .quad 0x00c09a0000000000
410 .quad 0x00809a0000000000
411 .quad 0x00c0920000000000
412 #endif