source: mainline/kernel/arch/amd64/src/boot/boot.S@ 3014e2b2

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

Move multiboot parsing to genarch/*/multiboot and adapt it for use with both ia32 and amd64. Multiboot info parsing now supported on amd64, too.

  • Property mode set to 100644
File size: 12.2 KB
RevLine 
[53634f9]1#
[df4ed85]2# Copyright (c) 2005 Ondrej Palkovsky
3# Copyright (c) 2006 Martin Decky
[19077a5]4# Copyright (c) 2008 Jakub Jermar
[1141c1a]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
[46d26ee]31#include <arch/boot/boot.h>
32#include <arch/boot/memmap.h>
[8fc0d455]33#include <arch/mm/page.h>
[6f878b7]34#include <arch/mm/ptl.h>
[8fc0d455]35#include <arch/pm.h>
[89344d85]36#include <arch/cpu.h>
[c4b3e3e]37#include <arch/cpuid.h>
[1141c1a]38
[8725fb4]39#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
[c4b3e3e]40
[874e312a]41.section K_TEXT_START, "ax"
[46d26ee]42
[8ccec3c1]43.code32
44.align 4
[46d26ee]45.global multiboot_image_start
[8ccec3c1]46multiboot_header:
47 .long MULTIBOOT_HEADER_MAGIC
48 .long MULTIBOOT_HEADER_FLAGS
49 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
[8725fb4]50 .long multiboot_header
51 .long unmapped_ktext_start
[8ccec3c1]52 .long 0
53 .long 0
[8725fb4]54 .long multiboot_image_start
[8ccec3c1]55
56multiboot_image_start:
[e13daa5d]57 cld
[46d26ee]58 movl $START_STACK, %esp # initialize stack pointer
[19077a5]59 lgdtl bootstrap_gdtr # initialize Global Descriptor Table register
[1a67595]60
61 movw $gdtselector(KDATA_DES), %cx
62 movw %cx, %es
63 movw %cx, %ds # kernel data + stack
64 movw %cx, %ss
[65640fef]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
[1a67595]70
[46d26ee]71 jmpl $gdtselector(KTEXT32_DES), $multiboot_meeting_point
[1a67595]72 multiboot_meeting_point:
73
[19077a5]74 movl %eax, grub_eax # save parameters from GRUB
[46d26ee]75 movl %ebx, grub_ebx
76
[ac88c93]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
[4fb6bf36]80 movl $(INTEL_CPUID_EXTENDED), %eax
[ac88c93]81 cpuid
[4fb6bf36]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
[ac88c93]91 cpuid
[4fb6bf36]92 bt $(AMD_EXT_LONG_MODE), %edx
[ac88c93]93 jc long_mode_supported
[4fb6bf36]94
[ac88c93]95 movl $long_mode_msg, %esi
96 jmp error_halt
[4fb6bf36]97
[ac88c93]98 long_mode_supported:
99
[4fb6bf36]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
[de07bcf]126#ifdef CONFIG_FB
[ac88c93]127 mov $vesa_init, %esi
[8778271]128 mov $VESA_INIT_SEGMENT << 4, %edi
129 mov $e_vesa_init - vesa_init, %ecx
130 rep movsb
[de07bcf]131
[8778271]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)
[de07bcf]144#endif
[42edee68]145
[4fb6bf36]146 # Enable 64-bit page translation entries - CR4.PAE = 1.
[6f878b7]147 # Paging is not enabled until after long mode is enabled
[8725fb4]148
[6f878b7]149 movl %cr4, %eax
150 btsl $5, %eax
151 movl %eax, %cr4
152
153 # Set up paging tables
[8725fb4]154
[6f878b7]155 leal ptl_0, %eax
156 movl %eax, %cr3
[c4b3e3e]157
[6f878b7]158 # Enable long mode
[8725fb4]159
[19077a5]160 movl $EFER_MSR_NUM, %ecx # EFER MSR number
[8725fb4]161 rdmsr # Read EFER
[19077a5]162 btsl $AMD_LME_FLAG, %eax # Set LME = 1
[8725fb4]163 wrmsr # Write EFER
[c245372b]164
[4fb6bf36]165 # Enable paging to activate long mode (set CR0.PG = 1)
[8725fb4]166
[6f878b7]167 movl %cr0, %eax
168 btsl $31, %eax
169 movl %eax, %cr0
[c245372b]170
[6f878b7]171 # At this point we are in compatibility mode
[8725fb4]172
[b9e97fb]173 jmpl $gdtselector(KTEXT_DES), $start64
[c245372b]174
[6f878b7]175.code64
176start64:
[c4b3e3e]177 movq $(PA2KA(START_STACK)), %rsp
[5d8d71e]178
179 # arch_pre_main(grub_eax, grub_ebx)
180 xorq %rdi, %rdi
181 movl grub_eax, %edi
182 xorq %rsi, %rsi
183 movl grub_ebx, %esi
184 call arch_pre_main
185
186 call main_bsp
187
188 # Not reached.
[8725fb4]189
190 cli
191 hlt
[de07bcf]192
193#ifdef CONFIG_FB
194.code32
195vesa_init:
[8778271]196 jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
197
[de07bcf]198.code16
[8778271]199vesa_init_real:
200
201 mov %cr0, %eax
202 and $~1, %eax
203 mov %eax, %cr0
204
205 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
206
207vesa_init_real2:
208
209 mov $VESA_INIT_SEGMENT, %bx
210
211 mov %bx, %es
212 mov %bx, %fs
213 mov %bx, %gs
214 mov %bx, %ds
215 mov %bx, %ss
216
217 movl $0x0000fffc, %esp
[9652bd59]218 movl $0x0000fffc, %ebp
[de07bcf]219
220#define VESA_INFO_SIZE 1024
221
[4f42d52]222#define VESA_MODE_ATTRIBUTES_OFFSET 0
[8778271]223#define VESA_MODE_LIST_PTR_OFFSET 14
[4f42d52]224#define VESA_MODE_SCANLINE_OFFSET 16
[de07bcf]225#define VESA_MODE_WIDTH_OFFSET 18
226#define VESA_MODE_HEIGHT_OFFSET 20
227#define VESA_MODE_BPP_OFFSET 25
228#define VESA_MODE_PHADDR_OFFSET 40
229
[8778271]230#define VESA_END_OF_MODES 0xffff
[de07bcf]231
[8778271]232#define VESA_OK 0x4f
[de07bcf]233
[8778271]234#define VESA_GET_INFO 0x4f00
[de07bcf]235#define VESA_GET_MODE_INFO 0x4f01
236#define VESA_SET_MODE 0x4f02
[4f42d52]237#define VESA_SET_PALETTE 0x4f09
[de07bcf]238
239#define CONFIG_VESA_BPP_a 255
240
[8778271]241#if CONFIG_VESA_BPP == 24
[4f42d52]242#define CONFIG_VESA_BPP_VARIANT 32
[de07bcf]243#endif
[4f42d52]244
[8778271]245 mov $VESA_GET_INFO, %ax
246 mov $e_vesa_init - vesa_init, %di
247 push %di
248 int $0x10
249
250 pop %di
251 cmp $VESA_OK, %al
252 jnz 0f
253
254 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
255 mov %si, %gs
256 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
257
258 add $VESA_INFO_SIZE, %di
[4f42d52]259
[de07bcf]2601:# Try next mode
[8778271]261 mov %gs:(%si), %cx
262 cmp $VESA_END_OF_MODES, %cx
263 jz 0f
264
265 inc %si
266 inc %si
267 push %cx
268 push %di
269 push %si
270 mov $VESA_GET_MODE_INFO, %ax
271 int $0x10
272
273 pop %si
274 pop %di
275 pop %cx
276 cmp $VESA_OK, %al
277 jnz 0f
278
279 mov $CONFIG_VESA_WIDTH, %ax
280 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
281 jnz 1b
282
283 mov $CONFIG_VESA_HEIGHT, %ax
284 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
285 jnz 1b
286
287 mov $CONFIG_VESA_BPP, %al
288 cmp VESA_MODE_BPP_OFFSET(%di), %al
[4f42d52]289
290#ifdef CONFIG_VESA_BPP_VARIANT
[8778271]291 jz 2f
292
[4f42d52]293 mov $CONFIG_VESA_BPP_VARIANT, %al
[8778271]294 cmp VESA_MODE_BPP_OFFSET(%di), %al
[4f42d52]295#endif
[8778271]296 jnz 1b
297
[de07bcf]2982:
299
[8778271]300 mov %cx, %bx
301 or $0xc000, %bx
302 push %di
303 mov $VESA_SET_MODE, %ax
304 int $0x10
[de07bcf]305
[8778271]306 pop %di
307 cmp $VESA_OK, %al
308 jnz 0f
[4f42d52]309
310#if CONFIG_VESA_BPP == 8
311
312 # Set 3:2:3 VGA palette
313
314 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
315 push %di
316 mov $vga323 - vesa_init, %di
317 mov $0x100, %ecx
318
[19077a5]319 bt $5, %ax # Test if VGA compatible registers are present
[4f42d52]320 jnc vga_compat
321
322 # Try VESA routine to set palette
323
324 mov $VESA_SET_PALETTE, %ax
325 xor %bl, %bl
326 xor %dx, %dx
327 int $0x10
328
[b1747a5]329 cmp $0x00, %ah
330 je vga_not_compat
[4f42d52]331
332 vga_compat:
333
334 # Try VGA registers to set palette
335
[19077a5]336 movw $0x3c6, %dx # Set palette mask
[4f42d52]337 movb $0xff, %al
338 outb %al, %dx
339
[19077a5]340 movw $0x3c8, %dx # First index to set
[4f42d52]341 xor %al, %al
342 outb %al, %dx
343
[19077a5]344 movw $0x3c9, %dx # Data port
[4f42d52]345 vga_loop:
346 movb %es:2(%di), %al
347 outb %al, %dx
348
349 movb %es:1(%di), %al
350 outb %al, %dx
351
352 movb %es:(%di), %al
353 outb %al, %dx
354
355 addw $4, %di
356 loop vga_loop
357
358 vga_not_compat:
359
360 pop %di
361
362#endif
[8778271]363
364 mov VESA_MODE_PHADDR_OFFSET(%di), %esi
365 mov VESA_MODE_WIDTH_OFFSET(%di), %ax
366 shl $16, %eax
367 mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
368 mov VESA_MODE_BPP_OFFSET(%di), %bl
369 xor %bh, %bh
370 shl $16, %ebx
371 mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
372 mov %eax, %edi
373
3748:
375
376 mov %cr0, %eax
377 or $1, %eax
378 mov %eax, %cr0
379
380 jmp 9f
[de07bcf]3819:
[8778271]382
383 ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
384
3850:# No prefered mode found
386 mov $0x111, %cx
387 push %di
388 push %cx
389 mov $VESA_GET_MODE_INFO, %ax
390 int $0x10
391
392 pop %cx
393 pop %di
394 cmp $VESA_OK, %al
395 jnz 1f
396 jz 2b # Force relative jump
397
3981:
399 mov $0x0003, %ax
400 int $0x10
[19077a5]401 mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
[8778271]402 xor %ax, %ax
403 jz 8b # Force relative jump
[4f42d52]404
405vga323:
406#include "vga323.pal"
[8778271]407
[de07bcf]408.code32
[8778271]409vesa_init_protect:
410 movw $gdtselector(KDATA_DES), %cx
411 movw %cx, %es
[19077a5]412 movw %cx, %ds # kernel data + stack
[8778271]413 movw %cx, %ss
414 # Simics seems to remove hidden part of GS on entering user mode
415 # when _visible_ part of GS does not point to user-mode segment
416 movw $gdtselector(UDATA_DES), %cx
417 movw %cx, %fs
418 movw %cx, %gs
419
[19077a5]420 movl $START_STACK, %esp # initialize stack pointer
[7cb567cd]421
[8778271]422 jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point
423
[de07bcf]424.align 4
425e_vesa_init:
[ac88c93]426#endif
427
428# Print string from %esi to EGA display (in red) and halt
429error_halt:
[19077a5]430 movl $0xb8000, %edi # base of EGA text mode memory
[ac88c93]431 xorl %eax, %eax
432
[19077a5]433 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
[ac88c93]434 movb $0xe, %al
435 outb %al, %dx
436
437 movw $0x3d5, %dx
438 inb %dx, %al
439 shl $8, %ax
440
[19077a5]441 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
[ac88c93]442 movb $0xf, %al
443 outb %al, %dx
444
445 movw $0x3d5, %dx
446 inb %dx, %al
447
448 cmp $1920, %ax
449 jbe cursor_ok
[19077a5]450 movw $1920, %ax # sanity check for the cursor on the last line
[ac88c93]451 cursor_ok:
452
453 movw %ax, %bx
454 shl $1, %eax
455 addl %eax, %edi
456
[19077a5]457 movw $0x0c00, %ax # black background, light red foreground
[ac88c93]458
459 ploop:
460 lodsb
461 cmp $0, %al
462 je ploop_end
463 stosw
464 inc %bx
465 jmp ploop
466 ploop_end:
467
[19077a5]468 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
[ac88c93]469 movb $0xe, %al
470 outb %al, %dx
471
472 movw $0x3d5, %dx
473 movb %bh, %al
474 outb %al, %dx
475
[19077a5]476 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
[ac88c93]477 movb $0xf, %al
478 outb %al, %dx
479
480 movw $0x3d5, %dx
481 movb %bl, %al
482 outb %al, %dx
483
484 cli
485 hlt
[b9e97fb]486
[19077a5]487
488.section K_INI_PTLS, "aw", @progbits
489
490#
491# Macro for generating initial page table contents.
492# @param cnt Number of entries to generat. Must be multiple of 8.
493# @param g Number of GB that will be added to the mapping.
494#
495.macro ptl2gen cnt g
496.if \cnt
497 ptl2gen "\cnt - 8" \g
498 .quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
499 .quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
500 .quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
501 .quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
502 .quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
503 .quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
504 .quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
505 .quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
506.endif
507.endm
508
509# Page table for pages in the first gigabyte.
[1141c1a]510.align 4096
[19077a5]511.global ptl_2_0g
512ptl_2_0g:
513 ptl2gen 512 0
514
515# Page table for pages in the second gigabyte.
516.align 4096
517.global ptl_2_1g
518ptl_2_1g:
519 ptl2gen 512 1
520
521# Page table for pages in the third gigabyte.
522.align 4096
523.global ptl_2_2g
524ptl_2_2g:
525 ptl2gen 512 2
526
527# Page table for pages in the fourth gigabyte.
528.align 4096
529.global ptl_2_3g
530ptl_2_3g:
531 ptl2gen 512 3
[b9e97fb]532
[6f878b7]533.align 4096
534.global ptl_1
535ptl_1:
[19077a5]536 # Identity mapping for [0; 4G)
537 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
538 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
539 .quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
540 .quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
541 .fill 506, 8, 0
542 # Mapping of [0; 1G) at -2G
543 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
544 .fill 1, 8, 0
[6f878b7]545
546.align 4096
547.global ptl_0
548ptl_0:
549 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
[93165be]550 .fill 255,8,0
551 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
552 .fill 254,8,0
[6f878b7]553 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
554
[19077a5]555.section K_DATA_START, "aw", @progbits
556
[46d26ee]557.global bootstrap_gdtr
558bootstrap_gdtr:
[1a67595]559 .word gdtselector(GDT_ITEMS)
560 .long KA2PA(gdt)
[46d26ee]561
562grub_eax:
563 .long 0
564
565grub_ebx:
566 .long 0
[ac88c93]567
[4fb6bf36]568extended_cpuid_msg:
569 .asciz "Extended CPUID not supported. System halted."
[ac88c93]570long_mode_msg:
[4f42d52]571 .asciz "64 bit long mode not supported. System halted."
[4fb6bf36]572noexecute_msg:
573 .asciz "No-execute pages not supported. System halted."
574fx_msg:
575 .asciz "FXSAVE/FXRESTORE instructions not supported. System halted."
576sse2_msg:
577 .asciz "SSE2 instructions not supported. System halted."
Note: See TracBrowser for help on using the repository browser.