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

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

add early_putchar() which can be used to do early kernel console output for debugging purposes
(the availability of this feature depends on each platform and specific configuration, currently it works only on ia32/amd64 with EGA and no framebuffer)
instrument more kernel functions
mark some functions as no_instrument (context_restore(), overlaps(), main_bsp())

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