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

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

rename gdtselector to GDT_SELECTOR to make explicit it is a macro
unify how bootstrap_gdtr is defined on amd64 and ia32

  • 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 $GDT_SELECTOR(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 $GDT_SELECTOR(UDATA_DES), %cx
97 movw %cx, %fs
98 movw %cx, %gs
99
100 jmpl $GDT_SELECTOR(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 $GDT_SELECTOR(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 $960, %ecx
250 rep movsl
251
252 /* Clear the 24th row */
253 xorl %eax, %eax
254 movl $40, %ecx
255 rep stosl
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 $960, %ecx
360 rep movsl
361
362 /* Clear the 24th row */
363 xorl %eax, %eax
364 movl $40, %ecx
365 rep stosl
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 $480, %rcx
519 rep movsq
520
521 /* Clear the 24th row */
522 xorq %rax, %rax
523 movq $20, %rcx
524 rep stosq
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 4
608
609/* Page table for pages in the 6th gigabyte. */
610.align 4096
611ptl_2_5g:
612 ptl2gen 512 5
613
614/* Page table for pages in the 7th gigabyte. */
615.align 4096
616ptl_2_6g:
617 ptl2gen 512 6
618
619/* Page table for pages in the 8th gigabyte. */
620.align 4096
621ptl_2_7g:
622 ptl2gen 512 7
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
647bootstrap_gdtr:
648 .word GDT_SELECTOR(GDT_ITEMS)
649 .long KA2PA(gdt)
650
651grub_eax:
652 .long 0
653
654grub_ebx:
655 .long 0
656
657err_extended_cpuid:
658 .asciz "Error: Extended CPUID not supported -- CPU is not 64-bit. System halted."
659err_long_mode:
660 .asciz "Error: 64-bit long mode not supported. System halted."
661err_noexecute:
662 .asciz "Error: No-execute pages not supported. System halted."
663err_fx:
664 .asciz "Error: FXSAVE/FXRESTORE instructions not supported. System halted."
665err_sse2:
666 .asciz "Error: SSE2 instructions not supported. System halted."
667
668status_prot:
669 .asciz "[prot] "
670status_vesa_copy:
671 .asciz "[vesa_copy] "
672status_grub_cmdline:
673 .asciz "[grub_cmdline] "
674status_vesa_real:
675 .asciz "[vesa_real] "
676status_prot2:
677 .asciz "[prot2] "
678status_long:
679 .asciz "[long] "
680status_main:
681 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.