source: mainline/kernel/arch/amd64/src/boot/multiboot.S@ 4fc93d5

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4fc93d5 was f66c203d, checked in by Martin Decky <martin@…>, 13 years ago

explicitly load default BIOS IDT for real-mode VESA BIOS access (GRUB 2.00 setups an empty IDT for bootstrap)
always use an empty IDT during bootstrap (for consistency)
make sure the interrupts are disabled during bootstrap
make sure correct GDT is set after returning from VESA BIOS

  • 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/mm/page.h>
33#include <arch/mm/ptl.h>
34#include <arch/pm.h>
35#include <genarch/multiboot/multiboot.h>
36#include <arch/cpuid.h>
37#include <arch/cpu.h>
38
39#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
40
41.section K_TEXT_START, "ax"
42
43.code32
44
45.macro pm_error msg
46 movl \msg, %esi
47 jmp pm_error_halt
48.endm
49
50.macro pm_status msg
51#ifdef CONFIG_EGA
52 pushl %esi
53 movl \msg, %esi
54 call pm_early_puts
55 popl %esi
56#endif
57.endm
58
59.macro pm2_status msg
60#ifndef CONFIG_FB
61 pm_status \msg
62#endif
63.endm
64
65.align 4
66.global multiboot_image_start
67multiboot_header:
68 .long MULTIBOOT_HEADER_MAGIC
69 .long MULTIBOOT_HEADER_FLAGS
70 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) /* checksum */
71 .long multiboot_header
72 .long unmapped_ktext_start
73 .long 0
74 .long 0
75 .long multiboot_image_start
76
77multiboot_image_start:
78 cli
79 cld
80
81 /* Initialize stack pointer */
82 movl $START_STACK, %esp
83
84 /*
85 * Initialize Global Descriptor Table and
86 * Interrupt Descriptor Table registers
87 */
88 lgdtl bootstrap_gdtr
89 lidtl bootstrap_idtr
90
91 /* Kernel data + stack */
92 movw $GDT_SELECTOR(KDATA_DES), %cx
93 movw %cx, %es
94 movw %cx, %ds
95 movw %cx, %ss
96
97 /*
98 * Simics seems to remove hidden part of GS on entering user mode
99 * when _visible_ part of GS does not point to user-mode segment.
100 */
101 movw $GDT_SELECTOR(UDATA_DES), %cx
102 movw %cx, %fs
103 movw %cx, %gs
104
105 jmpl $GDT_SELECTOR(KTEXT32_DES), $multiboot_meeting_point
106 multiboot_meeting_point:
107
108 /*
109 * Protected 32-bit. We want to reuse the code-seg descriptor,
110 * the Default operand size must not be 1 when entering long mode.
111 */
112
113 /* Save multiboot arguments */
114 movl %eax, multiboot_eax
115 movl %ebx, multiboot_ebx
116
117 pm_status $status_prot
118
119 movl $(INTEL_CPUID_EXTENDED), %eax
120 cpuid
121 cmp $(INTEL_CPUID_EXTENDED), %eax
122 ja extended_cpuid_supported
123
124 pm_error $err_extended_cpuid
125
126 extended_cpuid_supported:
127
128 movl $(AMD_CPUID_EXTENDED), %eax
129 cpuid
130 bt $(AMD_EXT_LONG_MODE), %edx
131 jc long_mode_supported
132
133 pm_error $err_long_mode
134
135 long_mode_supported:
136
137 bt $(AMD_EXT_NOEXECUTE), %edx
138 jc noexecute_supported
139
140 pm_error $err_noexecute
141
142 noexecute_supported:
143
144 movl $(INTEL_CPUID_STANDARD), %eax
145 cpuid
146 bt $(INTEL_FXSAVE), %edx
147 jc fx_supported
148
149 pm_error $err_fx
150
151 fx_supported:
152
153 bt $(INTEL_SSE2), %edx
154 jc sse2_supported
155
156 pm_error $err_sse2
157
158 sse2_supported:
159
160#include "vesa_prot.inc"
161
162 pm2_status $status_prot2
163
164 /*
165 * Enable 64-bit page translation entries - CR4.PAE = 1.
166 * Paging is not enabled until after long mode is enabled.
167 */
168
169 movl %cr4, %eax
170 btsl $5, %eax
171 movl %eax, %cr4
172
173 /* Set up paging tables */
174 leal ptl_0, %eax
175 movl %eax, %cr3
176
177 /* Enable long mode */
178 movl $EFER_MSR_NUM, %ecx
179 rdmsr /* read EFER */
180 btsl $AMD_LME_FLAG, %eax /* set LME = 1 */
181 wrmsr
182
183 /* Enable paging to activate long mode (set CR0.PG = 1) */
184 movl %cr0, %eax
185 btsl $31, %eax
186 movl %eax, %cr0
187
188 /* At this point we are in compatibility mode */
189 jmpl $GDT_SELECTOR(KTEXT_DES), $start64
190
191/** Print string to EGA display (in light red) and halt.
192 *
193 * Should be executed from 32 bit protected mode with paging
194 * turned off. Stack is not required. This routine is used even
195 * if CONFIG_EGA is not enabled. Since we are going to halt the
196 * CPU anyway, it is always better to at least try to print
197 * some hints.
198 *
199 * @param %esi Pointer to the NULL-terminated string
200 * to be print.
201 *
202 */
203pm_error_halt:
204 movl $0xb8000, %edi /* base of EGA text mode memory */
205 xorl %eax, %eax
206
207 /* Read bits 8 - 15 of the cursor address */
208 movw $0x3d4, %dx
209 movb $0xe, %al
210 outb %al, %dx
211
212 movw $0x3d5, %dx
213 inb %dx, %al
214 shl $8, %ax
215
216 /* Read bits 0 - 7 of the cursor address */
217 movw $0x3d4, %dx
218 movb $0xf, %al
219 outb %al, %dx
220
221 movw $0x3d5, %dx
222 inb %dx, %al
223
224 /* Sanity check for the cursor on screen */
225 cmp $2000, %ax
226 jb err_cursor_ok
227
228 movw $1998, %ax
229
230 err_cursor_ok:
231
232 movw %ax, %bx
233 shl $1, %eax
234 addl %eax, %edi
235
236 err_ploop:
237 lodsb
238
239 cmp $0, %al
240 je err_ploop_end
241
242 movb $0x0c, %ah /* black background, light red foreground */
243 stosw
244
245 /* Sanity check for the cursor on the last line */
246 inc %bx
247 cmp $2000, %bx
248 jb err_ploop
249
250 /* Scroll the screen (24 rows) */
251 movl %esi, %edx
252 movl $0xb80a0, %esi
253 movl $0xb8000, %edi
254 movl $960, %ecx
255 rep movsl
256
257 /* Clear the 24th row */
258 xorl %eax, %eax
259 movl $40, %ecx
260 rep stosl
261
262 /* Go to row 24 */
263 movl %edx, %esi
264 movl $0xb8f00, %edi
265 movw $1920, %bx
266
267 jmp err_ploop
268 err_ploop_end:
269
270 /* Write bits 8 - 15 of the cursor address */
271 movw $0x3d4, %dx
272 movb $0xe, %al
273 outb %al, %dx
274
275 movw $0x3d5, %dx
276 movb %bh, %al
277 outb %al, %dx
278
279 /* Write bits 0 - 7 of the cursor address */
280 movw $0x3d4, %dx
281 movb $0xf, %al
282 outb %al, %dx
283
284 movw $0x3d5, %dx
285 movb %bl, %al
286 outb %al, %dx
287
288 cli
289 hlt1:
290 hlt
291 jmp hlt1
292
293/** Print string to EGA display (in light green).
294 *
295 * Should be called from 32 bit protected mode with paging
296 * turned off. A stack space of at least 24 bytes is required,
297 * but the function does not establish a stack frame.
298 *
299 * Macros such as pm_status and pm2_status take care that
300 * this function is used only when CONFIG_EGA is enabled
301 * and CONFIG_FB is disabled.
302 *
303 * @param %esi Pointer to the NULL-terminated string
304 * to be print.
305 *
306 */
307pm_early_puts:
308 pushl %eax
309 pushl %ebx
310 pushl %ecx
311 pushl %edx
312 pushl %edi
313
314 movl $0xb8000, %edi /* base of EGA text mode memory */
315 xorl %eax, %eax
316
317 /* Read bits 8 - 15 of the cursor address */
318 movw $0x3d4, %dx
319 movb $0xe, %al
320 outb %al, %dx
321
322 movw $0x3d5, %dx
323 inb %dx, %al
324 shl $8, %ax
325
326 /* Read bits 0 - 7 of the cursor address */
327 movw $0x3d4, %dx
328 movb $0xf, %al
329 outb %al, %dx
330
331 movw $0x3d5, %dx
332 inb %dx, %al
333
334 /* Sanity check for the cursor on screen */
335 cmp $2000, %ax
336 jb pm_puts_cursor_ok
337
338 movw $1998, %ax
339
340 pm_puts_cursor_ok:
341
342 movw %ax, %bx
343 shl $1, %eax
344 addl %eax, %edi
345
346 pm_puts_ploop:
347 lodsb
348
349 cmp $0, %al
350 je pm_puts_ploop_end
351
352 movb $0x0a, %ah /* black background, light green foreground */
353 stosw
354
355 /* Sanity check for the cursor on the last line */
356 inc %bx
357 cmp $2000, %bx
358 jb pm_puts_ploop
359
360 /* Scroll the screen (24 rows) */
361 movl %esi, %edx
362 movl $0xb80a0, %esi
363 movl $0xb8000, %edi
364 movl $960, %ecx
365 rep movsl
366
367 /* Clear the 24th row */
368 xorl %eax, %eax
369 movl $40, %ecx
370 rep stosl
371
372 /* Go to row 24 */
373 movl %edx, %esi
374 movl $0xb8f00, %edi
375 movw $1920, %bx
376
377 jmp pm_puts_ploop
378 pm_puts_ploop_end:
379
380 /* Write bits 8 - 15 of the cursor address */
381 movw $0x3d4, %dx
382 movb $0xe, %al
383 outb %al, %dx
384
385 movw $0x3d5, %dx
386 movb %bh, %al
387 outb %al, %dx
388
389 /* Write bits 0 - 7 of the cursor address */
390 movw $0x3d4, %dx
391 movb $0xf, %al
392 outb %al, %dx
393
394 movw $0x3d5, %dx
395 movb %bl, %al
396 outb %al, %dx
397
398 popl %edi
399 popl %edx
400 popl %ecx
401 popl %ebx
402 popl %eax
403
404 ret
405
406.code64
407
408.macro long_status msg
409 pushq %rdi
410 movq \msg, %rdi
411 call early_puts
412 popq %rdi
413.endm
414
415start64:
416
417 /*
418 * Long mode.
419 */
420
421 movq $(PA2KA(START_STACK)), %rsp
422
423 /* Create the first stack frame */
424 pushq $0
425 movq %rsp, %rbp
426
427 long_status $status_long
428
429 /* Call arch_pre_main(multiboot_eax, multiboot_ebx) */
430 xorq %rdi, %rdi
431 movl multiboot_eax, %edi
432 xorq %rsi, %rsi
433 movl multiboot_ebx, %esi
434
435 movabsq $arch_pre_main, %rax
436 callq *%rax
437
438 long_status $status_main
439
440 /* Call main_bsp() */
441 movabsq $main_bsp, %rax
442 call *%rax
443
444 /* Not reached */
445 cli
446 hlt0:
447 hlt
448 jmp hlt0
449
450/** Print string to EGA display.
451 *
452 * Should be called from long mode (with paging enabled
453 * and stack established). This function is ABI compliant
454 * (without red-zone).
455 *
456 * If CONFIG_EGA is undefined or CONFIG_FB is defined
457 * then this function does nothing.
458 *
459 * @param %rdi Pointer to the NULL-terminated string
460 * to be printed.
461 *
462 */
463early_puts:
464
465#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
466
467 /* Prologue, save preserved registers */
468 pushq %rbp
469 movq %rsp, %rbp
470 pushq %rbx
471
472 movq %rdi, %rsi
473 movq $(PA2KA(0xb8000)), %rdi /* base of EGA text mode memory */
474 xorq %rax, %rax
475
476 /* Read bits 8 - 15 of the cursor address */
477 movw $0x3d4, %dx
478 movb $0xe, %al
479 outb %al, %dx
480
481 movw $0x3d5, %dx
482 inb %dx, %al
483 shl $8, %ax
484
485 /* Read bits 0 - 7 of the cursor address */
486 movw $0x3d4, %dx
487 movb $0xf, %al
488 outb %al, %dx
489
490 movw $0x3d5, %dx
491 inb %dx, %al
492
493 /* Sanity check for the cursor on screen */
494 cmp $2000, %ax
495 jb early_puts_cursor_ok
496
497 movw $1998, %ax
498
499 early_puts_cursor_ok:
500
501 movw %ax, %bx
502 shl $1, %rax
503 addq %rax, %rdi
504
505 early_puts_ploop:
506 lodsb
507
508 cmp $0, %al
509 je early_puts_ploop_end
510
511 movb $0x0e, %ah /* black background, yellow foreground */
512 stosw
513
514 /* Sanity check for the cursor on the last line */
515 inc %bx
516 cmp $2000, %bx
517 jb early_puts_ploop
518
519 /* Scroll the screen (24 rows) */
520 movq %rsi, %rdx
521 movq $(PA2KA(0xb80a0)), %rsi
522 movq $(PA2KA(0xb8000)), %rdi
523 movl $480, %ecx
524 rep movsq
525
526 /* Clear the 24th row */
527 xorl %eax, %eax
528 movl $20, %ecx
529 rep stosq
530
531 /* Go to row 24 */
532 movq %rdx, %rsi
533 movq $(PA2KA(0xb8f00)), %rdi
534 movw $1920, %bx
535
536 jmp early_puts_ploop
537 early_puts_ploop_end:
538
539 /* Write bits 8 - 15 of the cursor address */
540 movw $0x3d4, %dx
541 movb $0xe, %al
542 outb %al, %dx
543
544 movw $0x3d5, %dx
545 movb %bh, %al
546 outb %al, %dx
547
548 /* Write bits 0 - 7 of the cursor address */
549 movw $0x3d4, %dx
550 movb $0xf, %al
551 outb %al, %dx
552
553 movw $0x3d5, %dx
554 movb %bl, %al
555 outb %al, %dx
556
557 /* Epilogue, restore preserved registers */
558 popq %rbx
559 leave
560
561#endif
562
563 ret
564
565#include "vesa_real.inc"
566
567.section K_INI_PTLS, "aw", @progbits
568
569/** Generate initial page table contents.
570 *
571 * @param cnt Number of entries to generate. Must be multiple of 8.
572 * @param g Number of GB that will be added to the mapping.
573 *
574 */
575.macro ptl2gen cnt g
576 .if \cnt
577 ptl2gen "\cnt - 8" \g
578 .quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
579 .quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
580 .quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
581 .quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
582 .quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
583 .quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
584 .quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
585 .quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
586 .endif
587.endm
588
589/* Page table for pages in the 1st gigabyte. */
590.align 4096
591ptl_2_0g:
592 ptl2gen 512 0
593
594/* Page table for pages in the 2nd gigabyte. */
595.align 4096
596ptl_2_1g:
597 ptl2gen 512 1
598
599/* Page table for pages in the 3rd gigabyte. */
600.align 4096
601ptl_2_2g:
602 ptl2gen 512 2
603
604/* Page table for pages in the 4th gigabyte. */
605.align 4096
606ptl_2_3g:
607 ptl2gen 512 3
608
609/* Page table for pages in the 5th gigabyte. */
610.align 4096
611ptl_2_4g:
612 ptl2gen 512 4
613
614/* Page table for pages in the 6th gigabyte. */
615.align 4096
616ptl_2_5g:
617 ptl2gen 512 5
618
619/* Page table for pages in the 7th gigabyte. */
620.align 4096
621ptl_2_6g:
622 ptl2gen 512 6
623
624/* Page table for pages in the 8th gigabyte. */
625.align 4096
626ptl_2_7g:
627 ptl2gen 512 7
628
629.align 4096
630ptl_1:
631 /* Identity mapping for [0; 8G) */
632 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
633 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
634 .quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
635 .quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
636 .quad ptl_2_4g + (PTL_WRITABLE | PTL_PRESENT)
637 .quad ptl_2_5g + (PTL_WRITABLE | PTL_PRESENT)
638 .quad ptl_2_6g + (PTL_WRITABLE | PTL_PRESENT)
639 .quad ptl_2_7g + (PTL_WRITABLE | PTL_PRESENT)
640 .fill 504, 8, 0
641
642.align 4096
643.global ptl_0
644ptl_0:
645 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
646 .fill 255, 8, 0
647 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
648 .fill 255, 8, 0
649
650.section K_DATA_START, "aw", @progbits
651
652.global bootstrap_idtr
653bootstrap_idtr:
654 .word 0
655 .long 0
656
657.global bootstrap_gdtr
658bootstrap_gdtr:
659 .word GDT_SELECTOR(GDT_ITEMS)
660 .long KA2PA(gdt)
661
662.global multiboot_eax
663multiboot_eax:
664 .long 0
665
666.global multiboot_ebx
667multiboot_ebx:
668 .long 0
669
670err_extended_cpuid:
671 .asciz "Error: Extended CPUID not supported -- CPU is not 64-bit. System halted."
672err_long_mode:
673 .asciz "Error: 64-bit long mode not supported. System halted."
674err_noexecute:
675 .asciz "Error: No-execute pages not supported. System halted."
676err_fx:
677 .asciz "Error: FXSAVE/FXRESTORE instructions not supported. System halted."
678err_sse2:
679 .asciz "Error: SSE2 instructions not supported. System halted."
680
681status_prot:
682 .asciz "[prot] "
683status_vesa_copy:
684 .asciz "[vesa_copy] "
685status_multiboot_cmdline:
686 .asciz "[multiboot_cmdline] "
687status_vesa_real:
688 .asciz "[vesa_real] "
689status_prot2:
690 .asciz "[prot2] "
691status_long:
692 .asciz "[long] "
693status_main:
694 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.