source: mainline/kernel/arch/amd64/src/boot/boot.S@ 0f94c3d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0f94c3d was 0f94c3d, checked in by Jiri Svoboda <jirik.svoboda@…>, 16 years ago

Read command line for multiboot modules on ia32 and copy it to task name. Other arches will need to initialize task names in the init structure to an empty string.

  • Property mode set to 100644
File size: 14.1 KB
Line 
1#
2# Copyright (c) 2005 Ondrej Palkovsky
3# Copyright (c) 2006 Martin Decky
4# Copyright (c) 2008 Jakub Jermar
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11# - Redistributions of source code must retain the above copyright
12# notice, this list of conditions and the following disclaimer.
13# - Redistributions in binary form must reproduce the above copyright
14# notice, this list of conditions and the following disclaimer in the
15# documentation and/or other materials provided with the distribution.
16# - The name of the author may not be used to endorse or promote products
17# derived from this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29#
30
31#include <arch/boot/boot.h>
32#include <arch/boot/memmap.h>
33#include <arch/mm/page.h>
34#include <arch/mm/ptl.h>
35#include <arch/pm.h>
36#include <arch/cpu.h>
37#include <arch/cpuid.h>
38
39#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
40
41.section K_TEXT_START, "ax"
42
43.code32
44.align 4
45.global multiboot_image_start
46multiboot_header:
47 .long MULTIBOOT_HEADER_MAGIC
48 .long MULTIBOOT_HEADER_FLAGS
49 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
50 .long multiboot_header
51 .long unmapped_ktext_start
52 .long 0
53 .long 0
54 .long multiboot_image_start
55
56multiboot_image_start:
57 cld
58 movl $START_STACK, %esp # initialize stack pointer
59 lgdtl bootstrap_gdtr # initialize Global Descriptor Table register
60
61 movw $gdtselector(KDATA_DES), %cx
62 movw %cx, %es
63 movw %cx, %ds # kernel data + stack
64 movw %cx, %ss
65 # Simics seems to remove hidden part of GS on entering user mode
66 # when _visible_ part of GS does not point to user-mode segment
67 movw $gdtselector(UDATA_DES), %cx
68 movw %cx, %fs
69 movw %cx, %gs
70
71 jmpl $gdtselector(KTEXT32_DES), $multiboot_meeting_point
72 multiboot_meeting_point:
73
74 movl %eax, grub_eax # save parameters from GRUB
75 movl %ebx, grub_ebx
76
77 # Protected 32-bit. We want to reuse the code-seg descriptor,
78 # the Default operand size must not be 1 when entering long mode
79
80 movl $(INTEL_CPUID_EXTENDED), %eax
81 cpuid
82 cmp $(INTEL_CPUID_EXTENDED), %eax
83 ja extended_cpuid_supported
84
85 movl $extended_cpuid_msg, %esi
86 jmp error_halt
87
88 extended_cpuid_supported:
89
90 movl $(AMD_CPUID_EXTENDED), %eax
91 cpuid
92 bt $(AMD_EXT_LONG_MODE), %edx
93 jc long_mode_supported
94
95 movl $long_mode_msg, %esi
96 jmp error_halt
97
98 long_mode_supported:
99
100 bt $(AMD_EXT_NOEXECUTE), %edx
101 jc noexecute_supported
102
103 movl $noexecute_msg, %esi
104 jmp error_halt
105
106 noexecute_supported:
107
108 movl $(INTEL_CPUID_STANDARD), %eax
109 cpuid
110 bt $(INTEL_FXSAVE), %edx
111 jc fx_supported
112
113 movl $fx_msg, %esi
114 jmp error_halt
115
116 fx_supported:
117
118 bt $(INTEL_SSE2), %edx
119 jc sse2_supported
120
121 movl $sse2_msg, %esi
122 jmp error_halt
123
124 sse2_supported:
125
126#ifdef CONFIG_FB
127 mov $vesa_init, %esi
128 mov $VESA_INIT_SEGMENT << 4, %edi
129 mov $e_vesa_init - vesa_init, %ecx
130 rep movsb
131
132 mov $VESA_INIT_SEGMENT << 4, %edi
133 jmpl *%edi
134
135 vesa_meeting_point:
136
137 mov %esi, KA2PA(vesa_ph_addr)
138 mov %di, KA2PA(vesa_height)
139 shr $16, %edi
140 mov %di, KA2PA(vesa_width)
141 mov %bx, KA2PA(vesa_scanline)
142 shr $16, %ebx
143 mov %bx, KA2PA(vesa_bpp)
144#endif
145
146 # Enable 64-bit page translation entries - CR4.PAE = 1.
147 # Paging is not enabled until after long mode is enabled
148
149 movl %cr4, %eax
150 btsl $5, %eax
151 movl %eax, %cr4
152
153 # Set up paging tables
154
155 leal ptl_0, %eax
156 movl %eax, %cr3
157
158 # Enable long mode
159
160 movl $EFER_MSR_NUM, %ecx # EFER MSR number
161 rdmsr # Read EFER
162 btsl $AMD_LME_FLAG, %eax # Set LME = 1
163 wrmsr # Write EFER
164
165 # Enable paging to activate long mode (set CR0.PG = 1)
166
167 movl %cr0, %eax
168 btsl $31, %eax
169 movl %eax, %cr0
170
171 # At this point we are in compatibility mode
172
173 jmpl $gdtselector(KTEXT_DES), $start64
174
175.code64
176start64:
177 movq $(PA2KA(START_STACK)), %rsp
178 movl grub_eax, %eax
179 movl grub_ebx, %ebx
180
181 cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature
182 je valid_boot
183
184 xorl %ecx, %ecx # no memory size or map available
185 movl %ecx, e820counter
186
187 jmp invalid_boot
188
189 valid_boot:
190
191 movl (%ebx), %eax # ebx = physical address of struct multiboot_info
192
193 bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid)
194 jc mods_valid
195
196 xorq %rcx, %rcx
197 movq %rcx, init
198 jmp mods_end
199
200 mods_valid:
201
202 xorq %rcx, %rcx
203 movl 20(%ebx), %ecx # mbi->mods_count
204 movq %rcx, init
205
206 cmpl $0, %ecx
207 je mods_end
208
209 movl 24(%ebx), %esi # mbi->mods_addr
210 movq $init, %rdi
211
212 mods_loop:
213
214 xorq %rdx, %rdx
215 movl 0(%esi), %edx # mods->mod_start
216 movq $0xffff800000000000, %r10
217 addq %r10, %rdx
218 movq %rdx, 8(%rdi)
219
220 xorq %rdx, %rdx
221 movl 4(%esi), %edx
222 subl 0(%esi), %edx # mods->mod_end - mods->mod_start
223 movq %rdx, 16(%rdi)
224
225 addl $16, %esi
226 addq $48, %rdi
227
228 loop mods_loop
229
230 mods_end:
231
232 bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid)
233 jc mmap_valid
234
235 xorl %edx, %edx
236 jmp mmap_invalid
237
238 mmap_valid:
239 movl 44(%ebx), %ecx # mbi->mmap_length
240 movl 48(%ebx), %esi # mbi->mmap_addr
241 movq $e820table, %rdi
242 xorl %edx, %edx
243
244 mmap_loop:
245 cmpl $0, %ecx
246 jle mmap_end
247
248 movl 4(%esi), %eax # mmap->base_addr_low
249 movl %eax, (%rdi)
250
251 movl 8(%esi), %eax # mmap->base_addr_high
252 movl %eax, 4(%rdi)
253
254 movl 12(%esi), %eax # mmap->length_low
255 movl %eax, 8(%rdi)
256
257 movl 16(%esi), %eax # mmap->length_high
258 movl %eax, 12(%rdi)
259
260 movl 20(%esi), %eax # mmap->type
261 movl %eax, 16(%rdi)
262
263 movl (%esi), %eax # mmap->size
264 addl $0x4, %eax
265 addl %eax, %esi
266 subl %eax, %ecx
267 addq $MEMMAP_E820_RECORD_SIZE, %rdi
268 incl %edx
269 jmp mmap_loop
270
271 mmap_end:
272
273 mmap_invalid:
274 movl %edx, e820counter
275
276 invalid_boot:
277
278#ifdef CONFIG_SMP
279
280 # copy AP bootstrap routines below 1 MB
281
282 movq $BOOT_OFFSET, %rsi
283 movq $AP_BOOT_OFFSET, %rdi
284 movq $_hardcoded_unmapped_size, %rcx
285 rep movsb
286
287#endif
288
289 call main_bsp # never returns
290
291 cli
292 hlt
293
294#ifdef CONFIG_FB
295.code32
296vesa_init:
297 jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
298
299.code16
300vesa_init_real:
301
302 mov %cr0, %eax
303 and $~1, %eax
304 mov %eax, %cr0
305
306 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
307
308vesa_init_real2:
309
310 mov $VESA_INIT_SEGMENT, %bx
311
312 mov %bx, %es
313 mov %bx, %fs
314 mov %bx, %gs
315 mov %bx, %ds
316 mov %bx, %ss
317
318 movl $0x0000fffc, %esp
319 movl $0x0000fffc, %ebp
320
321#define VESA_INFO_SIZE 1024
322
323#define VESA_MODE_ATTRIBUTES_OFFSET 0
324#define VESA_MODE_LIST_PTR_OFFSET 14
325#define VESA_MODE_SCANLINE_OFFSET 16
326#define VESA_MODE_WIDTH_OFFSET 18
327#define VESA_MODE_HEIGHT_OFFSET 20
328#define VESA_MODE_BPP_OFFSET 25
329#define VESA_MODE_PHADDR_OFFSET 40
330
331#define VESA_END_OF_MODES 0xffff
332
333#define VESA_OK 0x4f
334
335#define VESA_GET_INFO 0x4f00
336#define VESA_GET_MODE_INFO 0x4f01
337#define VESA_SET_MODE 0x4f02
338#define VESA_SET_PALETTE 0x4f09
339
340#define CONFIG_VESA_BPP_a 255
341
342#if CONFIG_VESA_BPP == 24
343#define CONFIG_VESA_BPP_VARIANT 32
344#endif
345
346 mov $VESA_GET_INFO, %ax
347 mov $e_vesa_init - vesa_init, %di
348 push %di
349 int $0x10
350
351 pop %di
352 cmp $VESA_OK, %al
353 jnz 0f
354
355 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
356 mov %si, %gs
357 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
358
359 add $VESA_INFO_SIZE, %di
360
3611:# Try next mode
362 mov %gs:(%si), %cx
363 cmp $VESA_END_OF_MODES, %cx
364 jz 0f
365
366 inc %si
367 inc %si
368 push %cx
369 push %di
370 push %si
371 mov $VESA_GET_MODE_INFO, %ax
372 int $0x10
373
374 pop %si
375 pop %di
376 pop %cx
377 cmp $VESA_OK, %al
378 jnz 0f
379
380 mov $CONFIG_VESA_WIDTH, %ax
381 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
382 jnz 1b
383
384 mov $CONFIG_VESA_HEIGHT, %ax
385 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
386 jnz 1b
387
388 mov $CONFIG_VESA_BPP, %al
389 cmp VESA_MODE_BPP_OFFSET(%di), %al
390
391#ifdef CONFIG_VESA_BPP_VARIANT
392 jz 2f
393
394 mov $CONFIG_VESA_BPP_VARIANT, %al
395 cmp VESA_MODE_BPP_OFFSET(%di), %al
396#endif
397 jnz 1b
398
3992:
400
401 mov %cx, %bx
402 or $0xc000, %bx
403 push %di
404 mov $VESA_SET_MODE, %ax
405 int $0x10
406
407 pop %di
408 cmp $VESA_OK, %al
409 jnz 0f
410
411#if CONFIG_VESA_BPP == 8
412
413 # Set 3:2:3 VGA palette
414
415 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
416 push %di
417 mov $vga323 - vesa_init, %di
418 mov $0x100, %ecx
419
420 bt $5, %ax # Test if VGA compatible registers are present
421 jnc vga_compat
422
423 # Try VESA routine to set palette
424
425 mov $VESA_SET_PALETTE, %ax
426 xor %bl, %bl
427 xor %dx, %dx
428 int $0x10
429
430 cmp $0x00, %ah
431 je vga_not_compat
432
433 vga_compat:
434
435 # Try VGA registers to set palette
436
437 movw $0x3c6, %dx # Set palette mask
438 movb $0xff, %al
439 outb %al, %dx
440
441 movw $0x3c8, %dx # First index to set
442 xor %al, %al
443 outb %al, %dx
444
445 movw $0x3c9, %dx # Data port
446 vga_loop:
447 movb %es:2(%di), %al
448 outb %al, %dx
449
450 movb %es:1(%di), %al
451 outb %al, %dx
452
453 movb %es:(%di), %al
454 outb %al, %dx
455
456 addw $4, %di
457 loop vga_loop
458
459 vga_not_compat:
460
461 pop %di
462
463#endif
464
465 mov VESA_MODE_PHADDR_OFFSET(%di), %esi
466 mov VESA_MODE_WIDTH_OFFSET(%di), %ax
467 shl $16, %eax
468 mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
469 mov VESA_MODE_BPP_OFFSET(%di), %bl
470 xor %bh, %bh
471 shl $16, %ebx
472 mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
473 mov %eax, %edi
474
4758:
476
477 mov %cr0, %eax
478 or $1, %eax
479 mov %eax, %cr0
480
481 jmp 9f
4829:
483
484 ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
485
4860:# No prefered mode found
487 mov $0x111, %cx
488 push %di
489 push %cx
490 mov $VESA_GET_MODE_INFO, %ax
491 int $0x10
492
493 pop %cx
494 pop %di
495 cmp $VESA_OK, %al
496 jnz 1f
497 jz 2b # Force relative jump
498
4991:
500 mov $0x0003, %ax
501 int $0x10
502 mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
503 xor %ax, %ax
504 jz 8b # Force relative jump
505
506vga323:
507#include "vga323.pal"
508
509.code32
510vesa_init_protect:
511 movw $gdtselector(KDATA_DES), %cx
512 movw %cx, %es
513 movw %cx, %ds # kernel data + stack
514 movw %cx, %ss
515 # Simics seems to remove hidden part of GS on entering user mode
516 # when _visible_ part of GS does not point to user-mode segment
517 movw $gdtselector(UDATA_DES), %cx
518 movw %cx, %fs
519 movw %cx, %gs
520
521 movl $START_STACK, %esp # initialize stack pointer
522
523 jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point
524
525.align 4
526e_vesa_init:
527#endif
528
529# Print string from %esi to EGA display (in red) and halt
530error_halt:
531 movl $0xb8000, %edi # base of EGA text mode memory
532 xorl %eax, %eax
533
534 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
535 movb $0xe, %al
536 outb %al, %dx
537
538 movw $0x3d5, %dx
539 inb %dx, %al
540 shl $8, %ax
541
542 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
543 movb $0xf, %al
544 outb %al, %dx
545
546 movw $0x3d5, %dx
547 inb %dx, %al
548
549 cmp $1920, %ax
550 jbe cursor_ok
551 movw $1920, %ax # sanity check for the cursor on the last line
552 cursor_ok:
553
554 movw %ax, %bx
555 shl $1, %eax
556 addl %eax, %edi
557
558 movw $0x0c00, %ax # black background, light red foreground
559
560 ploop:
561 lodsb
562 cmp $0, %al
563 je ploop_end
564 stosw
565 inc %bx
566 jmp ploop
567 ploop_end:
568
569 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
570 movb $0xe, %al
571 outb %al, %dx
572
573 movw $0x3d5, %dx
574 movb %bh, %al
575 outb %al, %dx
576
577 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
578 movb $0xf, %al
579 outb %al, %dx
580
581 movw $0x3d5, %dx
582 movb %bl, %al
583 outb %al, %dx
584
585 cli
586 hlt
587
588
589.section K_INI_PTLS, "aw", @progbits
590
591#
592# Macro for generating initial page table contents.
593# @param cnt Number of entries to generat. Must be multiple of 8.
594# @param g Number of GB that will be added to the mapping.
595#
596.macro ptl2gen cnt g
597.if \cnt
598 ptl2gen "\cnt - 8" \g
599 .quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
600 .quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
601 .quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
602 .quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
603 .quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
604 .quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
605 .quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
606 .quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
607.endif
608.endm
609
610# Page table for pages in the first gigabyte.
611.align 4096
612.global ptl_2_0g
613ptl_2_0g:
614 ptl2gen 512 0
615
616# Page table for pages in the second gigabyte.
617.align 4096
618.global ptl_2_1g
619ptl_2_1g:
620 ptl2gen 512 1
621
622# Page table for pages in the third gigabyte.
623.align 4096
624.global ptl_2_2g
625ptl_2_2g:
626 ptl2gen 512 2
627
628# Page table for pages in the fourth gigabyte.
629.align 4096
630.global ptl_2_3g
631ptl_2_3g:
632 ptl2gen 512 3
633
634.align 4096
635.global ptl_1
636ptl_1:
637 # Identity mapping for [0; 4G)
638 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
639 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
640 .quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
641 .quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
642 .fill 506, 8, 0
643 # Mapping of [0; 1G) at -2G
644 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
645 .fill 1, 8, 0
646
647.align 4096
648.global ptl_0
649ptl_0:
650 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
651 .fill 255,8,0
652 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
653 .fill 254,8,0
654 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
655
656.section K_DATA_START, "aw", @progbits
657
658.global bootstrap_gdtr
659bootstrap_gdtr:
660 .word gdtselector(GDT_ITEMS)
661 .long KA2PA(gdt)
662
663grub_eax:
664 .long 0
665
666grub_ebx:
667 .long 0
668
669extended_cpuid_msg:
670 .asciz "Extended CPUID not supported. System halted."
671long_mode_msg:
672 .asciz "64 bit long mode not supported. System halted."
673noexecute_msg:
674 .asciz "No-execute pages not supported. System halted."
675fx_msg:
676 .asciz "FXSAVE/FXRESTORE instructions not supported. System halted."
677sse2_msg:
678 .asciz "SSE2 instructions not supported. System halted."
Note: See TracBrowser for help on using the repository browser.