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