source: mainline/kernel/arch/amd64/src/boot/multiboot.S@ 4236b18

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4236b18 was 17af882, checked in by Jakub Jermar <jakub@…>, 11 years ago

Switch the amd64 kernel (back) from 'large' to 'kernel' memory model.

  • This makes the amd64 kernel 6% smaller and more comfortable to debug.
  • Unlike in the original 'kernel' memory model implementation, KA2PA(PA2KA(x)) == x; for x from kernel identity.
  • Memory outside of the kernel identity region continues to be available by the standard means.
  • 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 movl multiboot_eax, %edi
431 movl multiboot_ebx, %esi
432 callq arch_pre_main
433
434 long_status $status_main
435
436 /* Call main_bsp() */
437 callq main_bsp
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 movl $480, %ecx
519 rep movsq
520
521 /* Clear the 24th row */
522 xorl %eax, %eax
523 movl $20, %ecx
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 502, 8, 0
636 /* Mapping of [0; 2G) at -2G */
637 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
638 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
639
640
641.align 4096
642.global ptl_0
643ptl_0:
644 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
645 .fill 510, 8, 0
646 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
647
648.section K_DATA_START, "aw", @progbits
649
650.global bootstrap_idtr
651bootstrap_idtr:
652 .word 0
653 .long 0
654
655.global bootstrap_gdtr
656bootstrap_gdtr:
657 .word GDT_SELECTOR(GDT_ITEMS)
658 .long KA2PA(gdt)
659
660.global multiboot_eax
661multiboot_eax:
662 .long 0
663
664.global multiboot_ebx
665multiboot_ebx:
666 .long 0
667
668err_extended_cpuid:
669 .asciz "Error: Extended CPUID not supported -- CPU is not 64-bit. System halted."
670err_long_mode:
671 .asciz "Error: 64-bit long mode not supported. System halted."
672err_noexecute:
673 .asciz "Error: No-execute pages not supported. System halted."
674err_fx:
675 .asciz "Error: FXSAVE/FXRESTORE instructions not supported. System halted."
676err_sse2:
677 .asciz "Error: SSE2 instructions not supported. System halted."
678
679status_prot:
680 .asciz "[prot] "
681status_vesa_copy:
682 .asciz "[vesa_copy] "
683status_multiboot_cmdline:
684 .asciz "[multiboot_cmdline] "
685status_vesa_real:
686 .asciz "[vesa_real] "
687status_prot2:
688 .asciz "[prot2] "
689status_long:
690 .asciz "[long] "
691status_main:
692 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.