source: mainline/kernel/arch/amd64/src/boot/boot.S@ 8ccd2ea

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8ccd2ea was 71eef11, checked in by Martin Decky <martin@…>, 17 years ago

remove config.memory_size, get_memory_size() and memory_init.{c|d}
the amount of available memory can be calculated from the sizes of the zones
add FRAMES2SIZE, SIZE2KB and SIZE2MB functions/macros (code readability)

  • 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 movl $START_STACK, %esp # initialize stack pointer
58 lgdtl bootstrap_gdtr # initialize Global Descriptor Table register
59
60 movw $gdtselector(KDATA_DES), %cx
61 movw %cx, %es
62 movw %cx, %ds # kernel data + stack
63 movw %cx, %ss
64 # Simics seems to remove hidden part of GS on entering user mode
65 # when _visible_ part of GS does not point to user-mode segment
66 movw $gdtselector(UDATA_DES), %cx
67 movw %cx, %fs
68 movw %cx, %gs
69
70 jmpl $gdtselector(KTEXT32_DES), $multiboot_meeting_point
71 multiboot_meeting_point:
72
73 movl %eax, grub_eax # save parameters from GRUB
74 movl %ebx, grub_ebx
75
76 # Protected 32-bit. We want to reuse the code-seg descriptor,
77 # the Default operand size must not be 1 when entering long mode
78
79 movl $(INTEL_CPUID_EXTENDED), %eax
80 cpuid
81 cmp $(INTEL_CPUID_EXTENDED), %eax
82 ja extended_cpuid_supported
83
84 movl $extended_cpuid_msg, %esi
85 jmp error_halt
86
87 extended_cpuid_supported:
88
89 movl $(AMD_CPUID_EXTENDED), %eax
90 cpuid
91 bt $(AMD_EXT_LONG_MODE), %edx
92 jc long_mode_supported
93
94 movl $long_mode_msg, %esi
95 jmp error_halt
96
97 long_mode_supported:
98
99 bt $(AMD_EXT_NOEXECUTE), %edx
100 jc noexecute_supported
101
102 movl $noexecute_msg, %esi
103 jmp error_halt
104
105 noexecute_supported:
106
107 movl $(INTEL_CPUID_STANDARD), %eax
108 cpuid
109 bt $(INTEL_FXSAVE), %edx
110 jc fx_supported
111
112 movl $fx_msg, %esi
113 jmp error_halt
114
115 fx_supported:
116
117 bt $(INTEL_SSE2), %edx
118 jc sse2_supported
119
120 movl $sse2_msg, %esi
121 jmp error_halt
122
123 sse2_supported:
124
125#ifdef CONFIG_FB
126 mov $vesa_init, %esi
127 mov $VESA_INIT_SEGMENT << 4, %edi
128 mov $e_vesa_init - vesa_init, %ecx
129 cld
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 $16, %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 cld
286 rep movsb
287
288#endif
289
290 call main_bsp # never returns
291
292 cli
293 hlt
294
295#ifdef CONFIG_FB
296.code32
297vesa_init:
298 jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
299
300.code16
301vesa_init_real:
302
303 mov %cr0, %eax
304 and $~1, %eax
305 mov %eax, %cr0
306
307 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
308
309vesa_init_real2:
310
311 mov $VESA_INIT_SEGMENT, %bx
312
313 mov %bx, %es
314 mov %bx, %fs
315 mov %bx, %gs
316 mov %bx, %ds
317 mov %bx, %ss
318
319 movl $0x0000fffc, %esp
320 movl $0x0000fffc, %ebp
321
322#define VESA_INFO_SIZE 1024
323
324#define VESA_MODE_ATTRIBUTES_OFFSET 0
325#define VESA_MODE_LIST_PTR_OFFSET 14
326#define VESA_MODE_SCANLINE_OFFSET 16
327#define VESA_MODE_WIDTH_OFFSET 18
328#define VESA_MODE_HEIGHT_OFFSET 20
329#define VESA_MODE_BPP_OFFSET 25
330#define VESA_MODE_PHADDR_OFFSET 40
331
332#define VESA_END_OF_MODES 0xffff
333
334#define VESA_OK 0x4f
335
336#define VESA_GET_INFO 0x4f00
337#define VESA_GET_MODE_INFO 0x4f01
338#define VESA_SET_MODE 0x4f02
339#define VESA_SET_PALETTE 0x4f09
340
341#define CONFIG_VESA_BPP_a 255
342
343#if CONFIG_VESA_BPP == 24
344#define CONFIG_VESA_BPP_VARIANT 32
345#endif
346
347 mov $VESA_GET_INFO, %ax
348 mov $e_vesa_init - vesa_init, %di
349 push %di
350 int $0x10
351
352 pop %di
353 cmp $VESA_OK, %al
354 jnz 0f
355
356 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
357 mov %si, %gs
358 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
359
360 add $VESA_INFO_SIZE, %di
361
3621:# Try next mode
363 mov %gs:(%si), %cx
364 cmp $VESA_END_OF_MODES, %cx
365 jz 0f
366
367 inc %si
368 inc %si
369 push %cx
370 push %di
371 push %si
372 mov $VESA_GET_MODE_INFO, %ax
373 int $0x10
374
375 pop %si
376 pop %di
377 pop %cx
378 cmp $VESA_OK, %al
379 jnz 0f
380
381 mov $CONFIG_VESA_WIDTH, %ax
382 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
383 jnz 1b
384
385 mov $CONFIG_VESA_HEIGHT, %ax
386 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
387 jnz 1b
388
389 mov $CONFIG_VESA_BPP, %al
390 cmp VESA_MODE_BPP_OFFSET(%di), %al
391
392#ifdef CONFIG_VESA_BPP_VARIANT
393 jz 2f
394
395 mov $CONFIG_VESA_BPP_VARIANT, %al
396 cmp VESA_MODE_BPP_OFFSET(%di), %al
397#endif
398 jnz 1b
399
4002:
401
402 mov %cx, %bx
403 or $0xc000, %bx
404 push %di
405 mov $VESA_SET_MODE, %ax
406 int $0x10
407
408 pop %di
409 cmp $VESA_OK, %al
410 jnz 0f
411
412#if CONFIG_VESA_BPP == 8
413
414 # Set 3:2:3 VGA palette
415
416 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
417 push %di
418 mov $vga323 - vesa_init, %di
419 mov $0x100, %ecx
420
421 bt $5, %ax # Test if VGA compatible registers are present
422 jnc vga_compat
423
424 # Try VESA routine to set palette
425
426 mov $VESA_SET_PALETTE, %ax
427 xor %bl, %bl
428 xor %dx, %dx
429 int $0x10
430
431 jmp 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 cld
560
561 ploop:
562 lodsb
563 cmp $0, %al
564 je ploop_end
565 stosw
566 inc %bx
567 jmp ploop
568 ploop_end:
569
570 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
571 movb $0xe, %al
572 outb %al, %dx
573
574 movw $0x3d5, %dx
575 movb %bh, %al
576 outb %al, %dx
577
578 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
579 movb $0xf, %al
580 outb %al, %dx
581
582 movw $0x3d5, %dx
583 movb %bl, %al
584 outb %al, %dx
585
586 cli
587 hlt
588
589
590.section K_INI_PTLS, "aw", @progbits
591
592#
593# Macro for generating initial page table contents.
594# @param cnt Number of entries to generat. Must be multiple of 8.
595# @param g Number of GB that will be added to the mapping.
596#
597.macro ptl2gen cnt g
598.if \cnt
599 ptl2gen "\cnt - 8" \g
600 .quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
601 .quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
602 .quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
603 .quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
604 .quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
605 .quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
606 .quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
607 .quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
608.endif
609.endm
610
611# Page table for pages in the first gigabyte.
612.align 4096
613.global ptl_2_0g
614ptl_2_0g:
615 ptl2gen 512 0
616
617# Page table for pages in the second gigabyte.
618.align 4096
619.global ptl_2_1g
620ptl_2_1g:
621 ptl2gen 512 1
622
623# Page table for pages in the third gigabyte.
624.align 4096
625.global ptl_2_2g
626ptl_2_2g:
627 ptl2gen 512 2
628
629# Page table for pages in the fourth gigabyte.
630.align 4096
631.global ptl_2_3g
632ptl_2_3g:
633 ptl2gen 512 3
634
635.align 4096
636.global ptl_1
637ptl_1:
638 # Identity mapping for [0; 4G)
639 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
640 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
641 .quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
642 .quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
643 .fill 506, 8, 0
644 # Mapping of [0; 1G) at -2G
645 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
646 .fill 1, 8, 0
647
648.align 4096
649.global ptl_0
650ptl_0:
651 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
652 .fill 255,8,0
653 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
654 .fill 254,8,0
655 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
656
657.section K_DATA_START, "aw", @progbits
658
659.global bootstrap_gdtr
660bootstrap_gdtr:
661 .word gdtselector(GDT_ITEMS)
662 .long KA2PA(gdt)
663
664grub_eax:
665 .long 0
666
667grub_ebx:
668 .long 0
669
670extended_cpuid_msg:
671 .asciz "Extended CPUID not supported. System halted."
672long_mode_msg:
673 .asciz "64 bit long mode not supported. System halted."
674noexecute_msg:
675 .asciz "No-execute pages not supported. System halted."
676fx_msg:
677 .asciz "FXSAVE/FXRESTORE instructions not supported. System halted."
678sse2_msg:
679 .asciz "SSE2 instructions not supported. System halted."
Note: See TracBrowser for help on using the repository browser.