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