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
137 movl $1, %eax # Use the CPUID instruction to
138 .byte 0x0f, 0xa2 # check the processor type
139 movb %al, %cl # save reg for future use
140 andb $0x0f,%ah # mask processor family
141 movb %ah,SYMBOL_NAME(x86)
142 andb $0xf0, %eax # mask model
143 shrb $4, %al
144 movb %al,SYMBOL_NAME(x86_model)
145 andb $0x0f, %cl # mask mask revision
146 movb %cl,SYMBOL_NAME(x86_mask)
147 movl %edx,SYMBOL_NAME(x86_capability)
148
149 xorl %eax, %eax # call CPUID with 0 -> return vendor ID
150 .byte 0x0f, 0xa2 # CPUID
151 movl %ebx,SYMBOL_NAME(x86_vendor_id) # lo 4 chars
152 movl %edx,SYMBOL_NAME(x86_vendor_id)+4 # next 4 chars
153 movl %ecx,SYMBOL_NAME(x86_vendor_id)+8 # last 4 chars
154
155 movl %cr0,%eax # 486+
156 andl $0x80000011,%eax # Save PG,PE,ET
157 orl $0x50022,%eax # set AM, WP, NE and MP
158 jmp 2f
159 is486: pushl %ecx # restore original EFLAGS
160 popfl
161 movl %cr0,%eax # 486
162 andl $0x80000011,%eax # Save PG,PE,ET
163 orl $0x50022,%eax # set AM, WP, NE and MP
164 jmp 2f
165 is386: pushl %ecx # restore original EFLAGS
166 popfl
167 movl %cr0,%eax # 386
168 andl $0x80000011,%eax # Save PG,PE,ET
169 orl $2,%eax # set MP
170 2: movl %eax,%cr0
171 call check_x87
172 #ifdef __SMP__
173 movb ready,%eax
174 orb %eax,%eax
175 jz 3f
176 movl $ SYMBOL_NAME(swapper_pg_dir), %eax
177 movl %eax, %cr3
178 #ifdef GAS_KNOWS_CR4
179 movl %cr4,%eax
180 orl $16,%eax
181 movl %eax,%cr4
182 #else
183 .byte 0x0f,0x20,0xe0
184 orl $16,%eax
185 .byte 0x0f,0x22,0xe0
186 #endif
187 movl %cr0, %eax
188 orl $0x80000000, %eax
189 movl %eax, %cr0
190 jmp 4f
191 #endif
192 3:
193 call setup_paging
194 #ifdef __SMP__
195 incb ready
196 #endif
197 4:
198 lgdt gdt_descr
199 lidt idt_descr
200 ljmp $(KERNEL_CS),$1f
201 1: movl $(KERNEL_DS),%eax # reload all the segment registers
202 mov %ax,%ds # after changing gdt.
203 mov %ax,%es
204 mov %ax,%fs
205 mov %ax,%gs
206 #ifdef __SMP__
207 movl $(KERNEL_DS), %eax
208 mov %ax,%ss # Reload the stack pointer (segment only)
209 #else
210 lss stack_start,%esp # Load processor stack
211 #endif
212 xorl %eax,%eax
213 lldt %ax
214 pushl %eax # These are the parameters to main :-)
215 pushl %eax
216 pushl %eax
217 cld # gcc2 wants the direction flag cleared at all times
218 call SYMBOL_NAME(start_kernel)
219 L6:
220 jmp L6 # main should never return here, but
221
222
223 #ifdef __SMP__
224 ready: .byte 0
225 #endif
226
227
228
229
230 check_x87:
231 movb $0,SYMBOL_NAME(hard_math)
232 clts
233 fninit
234 fstsw %ax
235 cmpb $0,%al
236 je 1f
237 movl %cr0,%eax
238 xorl $4,%eax
239 movl %eax,%cr0
240 ret
241 ALIGN
242 1: movb $1,SYMBOL_NAME(hard_math)
243 .byte 0xDB,0xE4
244 ret
245
246
247
248
249
250
251
252
253
254
255
256 setup_idt:
257 lea ignore_int,%edx
258 movl $(KERNEL_CS << 16),%eax
259 movw %dx,%ax
260 movw $0x8E00,%dx
261
262 lea SYMBOL_NAME(idt),%edi
263 mov $256,%ecx
264 rp_sidt:
265 movl %eax,(%edi)
266 movl %edx,4(%edi)
267 addl $8,%edi
268 dec %ecx
269 jne rp_sidt
270 ret
271
272
273
274
275
276
277
278
279
280
281
282
283
284 ALIGN
285 setup_paging:
286 movl $1024*2,%ecx
287 xorl %eax,%eax
288 movl $ SYMBOL_NAME(swapper_pg_dir),%edi
289 cld;rep;stosl
290
291
292 movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)
293
294
295 movl $ SYMBOL_NAME(pg0)+7,SYMBOL_NAME(swapper_pg_dir)+3072
296 movl $ SYMBOL_NAME(pg0)+4092,%edi
297 movl $0x03ff007,%eax
298 std
299 1: stosl
300 subl $0x1000,%eax
301 jge 1b
302 cld
303 movl $ SYMBOL_NAME(swapper_pg_dir),%eax
304 movl %eax,%cr3
305 movl %cr0,%eax
306 orl $0x80000000,%eax
307 movl %eax,%cr0
308 ret
309
310
311
312
313
314
315
316
317
318
319
320 .org 0x1000
321 ENTRY(swapper_pg_dir)
322
323
324
325
326 .org 0x2000
327 ENTRY(pg0)
328
329 .org 0x3000
330 ENTRY(empty_bad_page)
331
332 .org 0x4000
333 ENTRY(empty_bad_page_table)
334
335 .org 0x5000
336 ENTRY(empty_zero_page)
337
338 .org 0x6000
339
340 stack_start:
341 .long SYMBOL_NAME(init_user_stack)+4096
342 .long KERNEL_DS
343
344
345 int_msg:
346 .asciz "Unknown interrupt\n"
347 ALIGN
348 ignore_int:
349 cld
350 pushl %eax
351 pushl %ecx
352 pushl %edx
353 push %ds
354 push %es
355 push %fs
356 movl $(KERNEL_DS),%eax
357 mov %ax,%ds
358 mov %ax,%es
359 mov %ax,%fs
360 pushl $int_msg
361 call SYMBOL_NAME(printk)
362 popl %eax
363 pop %fs
364 pop %es
365 pop %ds
366 popl %edx
367 popl %ecx
368 popl %eax
369 iret
370
371
372
373
374 ALIGN
375 .word 0
376 idt_descr:
377 .word 256*8-1 # idt contains 256 entries
378 .long 0xc0000000+SYMBOL_NAME(idt)
379
380 ENTRY(idt)
381 .fill 256,8,0 # idt is uninitialized
382
383 ALIGN
384 .word 0
385 gdt_descr:
386 #ifdef CONFIG_APM
387 .word (11+2*NR_TASKS)*8-1
388 #else
389 .word (8+2*NR_TASKS)*8-1
390 #endif
391 .long 0xc0000000+SYMBOL_NAME(gdt)
392
393
394
395
396
397 ENTRY(gdt)
398 .quad 0x0000000000000000
399 .quad 0x0000000000000000
400 .quad 0xc0c39a000000ffff
401 .quad 0xc0c392000000ffff
402 .quad 0x00cbfa000000ffff
403 .quad 0x00cbf2000000ffff
404 .quad 0x0000000000000000
405 .quad 0x0000000000000000
406 .fill 2*NR_TASKS,8,0
407 #ifdef CONFIG_APM
408 .quad 0x00c09a0000000000
409 .quad 0x00809a0000000000
410 .quad 0x00c0920000000000
411 #endif