source: mainline/kernel/arch/amd64/src/boot/multiboot.S@ 8781e9d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 8781e9d was 8781e9d, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Remove realmode VESA code

This simply enables framebuffer setup via multiboot1
(multiboot2 already did it), and removes the obsolete code.

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