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