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

Last change on this file was 8be3230, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Revert "Remove realmode VESA code" - needs more work

This reverts commit 8781e9d05ac3f6aeaa3ad709c5af9efa3209b87a.

  • Property mode set to 100644
File size: 14.8 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#define START_STACK (BOOT_OFFSET - BOOT_STACK_SIZE)
41
42.section K_TEXT_START, "ax"
43
44.code32
45
46.macro pm_error msg
47 movl \msg, %esi
48 jmp pm_error_halt
49.endm
50
51.macro pm_status msg
52#ifdef CONFIG_EGA
53 pushl %esi
54 movl \msg, %esi
55 call pm_early_puts
56 popl %esi
57#endif
58.endm
59
60.macro pm2_status msg
61#ifndef CONFIG_FB
62 pm_status \msg
63#endif
64.endm
65
66.align 4
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_start
73 .long 0
74 .long 0
75 .long multiboot_image_start
76
77SYMBOL(multiboot_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 orl $CR4_PAE, %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 $AMD_MSR_EFER, %ecx
179 rdmsr /* read EFER */
180 orl $AMD_LME, %eax /* set LME = 1 */
181 wrmsr
182
183 /* Enable paging to activate long mode (set CR0.PG = 1) */
184 movl %cr0, %eax
185 orl $CR0_PG, %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 amd64_pre_main(multiboot_eax, multiboot_ebx) */
430 movl multiboot_eax, %edi
431 movl multiboot_ebx, %esi
432
433#ifdef MEMORY_MODEL_large
434 movabsq $amd64_pre_main, %rax
435 callq *%rax
436#else
437 callq amd64_pre_main
438#endif
439
440 long_status $status_main
441
442 /* Call main_bsp() */
443#ifdef MEMORY_MODEL_large
444 movabsq $main_bsp, %rax
445 callq *%rax
446#else
447 callq main_bsp
448#endif
449
450 /* Not reached */
451 cli
452 hlt0:
453 hlt
454 jmp hlt0
455
456/** Print string to EGA display.
457 *
458 * Should be called from long mode (with paging enabled
459 * and stack established). This function is ABI compliant
460 * (without red-zone).
461 *
462 * If CONFIG_EGA is undefined or CONFIG_FB is defined
463 * then this function does nothing.
464 *
465 * @param %rdi Pointer to the NULL-terminated string
466 * to be printed.
467 *
468 */
469early_puts:
470
471#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
472
473 /* Prologue, save preserved registers */
474 pushq %rbp
475 movq %rsp, %rbp
476 pushq %rbx
477
478 movq %rdi, %rsi
479 movq $(PA2KA(0xb8000)), %rdi /* base of EGA text mode memory */
480 xorq %rax, %rax
481
482 /* Read bits 8 - 15 of the cursor address */
483 movw $0x3d4, %dx
484 movb $0xe, %al
485 outb %al, %dx
486
487 movw $0x3d5, %dx
488 inb %dx, %al
489 shl $8, %ax
490
491 /* Read bits 0 - 7 of the cursor address */
492 movw $0x3d4, %dx
493 movb $0xf, %al
494 outb %al, %dx
495
496 movw $0x3d5, %dx
497 inb %dx, %al
498
499 /* Sanity check for the cursor on screen */
500 cmp $2000, %ax
501 jb early_puts_cursor_ok
502
503 movw $1998, %ax
504
505 early_puts_cursor_ok:
506
507 movw %ax, %bx
508 shl $1, %rax
509 addq %rax, %rdi
510
511 early_puts_ploop:
512 lodsb
513
514 cmp $0, %al
515 je early_puts_ploop_end
516
517 movb $0x0e, %ah /* black background, yellow foreground */
518 stosw
519
520 /* Sanity check for the cursor on the last line */
521 inc %bx
522 cmp $2000, %bx
523 jb early_puts_ploop
524
525 /* Scroll the screen (24 rows) */
526 movq %rsi, %rdx
527 movq $(PA2KA(0xb80a0)), %rsi
528 movq $(PA2KA(0xb8000)), %rdi
529 movl $480, %ecx
530 rep movsq
531
532 /* Clear the 24th row */
533 xorl %eax, %eax
534 movl $20, %ecx
535 rep stosq
536
537 /* Go to row 24 */
538 movq %rdx, %rsi
539 movq $(PA2KA(0xb8f00)), %rdi
540 movw $1920, %bx
541
542 jmp early_puts_ploop
543 early_puts_ploop_end:
544
545 /* Write bits 8 - 15 of the cursor address */
546 movw $0x3d4, %dx
547 movb $0xe, %al
548 outb %al, %dx
549
550 movw $0x3d5, %dx
551 movb %bh, %al
552 outb %al, %dx
553
554 /* Write bits 0 - 7 of the cursor address */
555 movw $0x3d4, %dx
556 movb $0xf, %al
557 outb %al, %dx
558
559 movw $0x3d5, %dx
560 movb %bl, %al
561 outb %al, %dx
562
563 /* Epilogue, restore preserved registers */
564 popq %rbx
565 leave
566
567#endif
568
569 ret
570
571#include "vesa_real.inc"
572
573.section K_INI_PTLS, "aw", @progbits
574
575/** Generate initial page table contents.
576 *
577 * @param cnt Number of entries to generate. Must be multiple of 8.
578 * @param g Number of GB that will be added to the mapping.
579 *
580 */
581.macro ptl2gen cnt g
582 .if \cnt
583 ptl2gen "\cnt - 8" \g
584 .quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
585 .quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
586 .quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
587 .quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
588 .quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
589 .quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
590 .quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
591 .quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
592 .endif
593.endm
594
595/* Page table for pages in the 1st gigabyte. */
596.align 4096
597ptl_2_0g:
598 ptl2gen 512 0
599
600/* Page table for pages in the 2nd gigabyte. */
601.align 4096
602ptl_2_1g:
603 ptl2gen 512 1
604
605/* Page table for pages in the 3rd gigabyte. */
606.align 4096
607ptl_2_2g:
608 ptl2gen 512 2
609
610/* Page table for pages in the 4th gigabyte. */
611.align 4096
612ptl_2_3g:
613 ptl2gen 512 3
614
615/* Page table for pages in the 5th gigabyte. */
616.align 4096
617ptl_2_4g:
618 ptl2gen 512 4
619
620/* Page table for pages in the 6th gigabyte. */
621.align 4096
622ptl_2_5g:
623 ptl2gen 512 5
624
625/* Page table for pages in the 7th gigabyte. */
626.align 4096
627ptl_2_6g:
628 ptl2gen 512 6
629
630/* Page table for pages in the 8th gigabyte. */
631.align 4096
632ptl_2_7g:
633 ptl2gen 512 7
634
635#ifdef MEMORY_MODEL_kernel
636.align 4096
637ptl_1:
638 /* Identity mapping for [0; 8G) */
639 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
640 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
641 .quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
642 .quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
643 .quad ptl_2_4g + (PTL_WRITABLE | PTL_PRESENT)
644 .quad ptl_2_5g + (PTL_WRITABLE | PTL_PRESENT)
645 .quad ptl_2_6g + (PTL_WRITABLE | PTL_PRESENT)
646 .quad ptl_2_7g + (PTL_WRITABLE | PTL_PRESENT)
647 .fill 502, 8, 0
648 /* Mapping of [0; 2G) at -2G */
649 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
650 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
651
652.align 4096
653SYMBOL(ptl_0)
654 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
655 .fill 510, 8, 0
656 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
657#endif
658
659#ifdef MEMORY_MODEL_large
660.align 4096
661ptl_1:
662 /* Identity mapping for [0; 8G) */
663 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
664 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
665 .quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
666 .quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
667 .quad ptl_2_4g + (PTL_WRITABLE | PTL_PRESENT)
668 .quad ptl_2_5g + (PTL_WRITABLE | PTL_PRESENT)
669 .quad ptl_2_6g + (PTL_WRITABLE | PTL_PRESENT)
670 .quad ptl_2_7g + (PTL_WRITABLE | PTL_PRESENT)
671 .fill 504, 8, 0
672
673.align 4096
674SYMBOL(ptl_0)
675 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
676 .fill 255, 8, 0
677 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
678 .fill 255, 8, 0
679#endif
680
681.section K_DATA_START, "aw", @progbits
682
683SYMBOL(bootstrap_idtr)
684 .word 0
685 .long 0
686
687SYMBOL(bootstrap_gdtr)
688 .word GDT_SELECTOR(GDT_ITEMS)
689 .long KA2PA(gdt)
690
691SYMBOL(multiboot_eax)
692 .long 0
693
694SYMBOL(multiboot_ebx)
695 .long 0
696
697err_extended_cpuid:
698 .asciz "Error: Extended CPUID not supported -- CPU is not 64-bit. System halted."
699err_long_mode:
700 .asciz "Error: 64-bit long mode not supported. System halted."
701err_noexecute:
702 .asciz "Error: No-execute pages not supported. System halted."
703err_fx:
704 .asciz "Error: FXSAVE/FXRESTORE instructions not supported. System halted."
705err_sse2:
706 .asciz "Error: SSE2 instructions not supported. System halted."
707
708status_prot:
709 .asciz "[prot] "
710status_vesa_copy:
711 .asciz "[vesa_copy] "
712status_multiboot_cmdline:
713 .asciz "[multiboot_cmdline] "
714status_vesa_real:
715 .asciz "[vesa_real] "
716status_prot2:
717 .asciz "[prot2] "
718status_long:
719 .asciz "[long] "
720status_main:
721 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.