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