source: mainline/kernel/arch/ia32/src/boot/multiboot.S@ 4928165

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

Use macros for setting up the initial page tables

  • Property mode set to 100644
File size: 14.1 KB
Line 
1/*
2 * Copyright (c) 2001 Jakub Jermar
3 * Copyright (c) 2005 Martin Decky
4 * Copyright (c) 2011 Martin Sucha
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/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 pushl \msg
61 call early_puts
62.endm
63
64.align 4
65multiboot_header:
66 .long MULTIBOOT_HEADER_MAGIC
67 .long MULTIBOOT_HEADER_FLAGS
68 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) /* checksum */
69 .long multiboot_header
70 .long unmapped_ktext_start
71 .long 0
72 .long 0
73 .long multiboot_image_start
74
75SYMBOL(multiboot_image_start)
76 cli
77 cld
78
79 /* Initialize stack pointer */
80 movl $START_STACK, %esp
81
82 /*
83 * Initialize Global Descriptor Table and
84 * Interrupt Descriptor Table registers
85 */
86 lgdtl bootstrap_gdtr
87 lidtl bootstrap_idtr
88
89 /* Kernel data + stack */
90 movw $GDT_SELECTOR(KDATA_DES), %cx
91 movw %cx, %es
92 movw %cx, %fs
93 movw %cx, %gs
94 movw %cx, %ds
95 movw %cx, %ss
96
97 jmpl $GDT_SELECTOR(KTEXT_DES), $multiboot_meeting_point
98 multiboot_meeting_point:
99
100 /* Save multiboot arguments */
101 movl %eax, multiboot_eax
102 movl %ebx, multiboot_ebx
103
104 pm_status $status_prot
105
106#include "vesa_prot.inc"
107
108#ifndef PROCESSOR_i486
109
110 pm_status $status_prot2
111
112 movl $(INTEL_CPUID_LEVEL), %eax
113 cpuid
114 cmp $0x0, %eax /* any function > 0? */
115 jbe pse_unsupported
116
117 movl $(INTEL_CPUID_STANDARD), %eax
118 cpuid
119 bt $(INTEL_PSE), %edx
120 jnc pse_unsupported
121
122 /* Map kernel and turn paging on */
123 pm_status $status_pse
124 call map_kernel_pse
125 jmp stack_init
126
127#endif /* PROCESSOR_i486 */
128
129 pse_unsupported:
130
131 /* Map kernel and turn paging on */
132 pm_status $status_non_pse
133 call map_kernel_non_pse
134
135 stack_init:
136
137 /* Create the first stack frame */
138 pushl $0
139 movl %esp, %ebp
140
141 pm2_status $status_prot3
142
143 /* Call arch_pre_main(multiboot_eax, multiboot_ebx) */
144 pushl multiboot_ebx
145 pushl multiboot_eax
146 call arch_pre_main
147
148 pm2_status $status_main
149
150 /* Call main_bsp() */
151 call main_bsp
152
153 /* Not reached */
154 cli
155 hlt0:
156 hlt
157 jmp hlt0
158
159/** Setup mapping for the kernel (PSE variant)
160 *
161 * Setup mapping for both the unmapped and mapped sections
162 * of the kernel. For simplicity, we map the entire 4G space.
163 *
164 */
165FUNCTION_BEGIN(map_kernel_pse)
166map_kernel_pse:
167 /* Paging features */
168 movl %cr4, %ecx
169 orl $CR4_PSE, %ecx /* PSE on */
170 andl $~CR4_PAE, %ecx /* PAE off */
171 movl %ecx, %cr4
172
173 movl $(page_directory + 0), %esi
174 movl $(page_directory + 2048), %edi
175 xorl %ecx, %ecx
176 xorl %ebx, %ebx
177
178 floop_pse:
179 movl $(PDE_4M | PDE_RW | PDE_P), %eax
180 orl %ebx, %eax
181 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
182 movl %eax, (%esi, %ecx, 4)
183 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
184 movl %eax, (%edi, %ecx, 4)
185 addl $(4 * 1024 * 1024), %ebx
186
187 incl %ecx
188 cmpl $512, %ecx
189 jl floop_pse
190
191 movl %esi, %cr3
192
193 movl %cr0, %ebx
194 orl $CR0_PG, %ebx /* paging on */
195 movl %ebx, %cr0
196 ret
197FUNCTION_END(map_kernel_pse)
198
199/** Setup mapping for the kernel (non-PSE variant).
200 *
201 * Setup mapping for both the unmapped and mapped sections
202 * of the kernel. For simplicity, we map the entire 4G space.
203 *
204 */
205FUNCTION_BEGIN(map_kernel_non_pse)
206 /* Paging features */
207 movl %cr4, %ecx
208 andl $~CR4_PAE, %ecx /* PAE off */
209 movl %ecx, %cr4
210
211 call calc_kernel_end
212 call find_mem_for_pt
213
214 mov kernel_end, %esi
215 mov free_area, %ecx
216
217 cmpl %esi, %ecx
218 jbe use_kernel_end
219
220 mov %ecx, %esi
221
222 /* Align address down to 4k */
223 andl $(~4095), %esi
224
225 use_kernel_end:
226
227 /* Align address to 4k */
228 addl $4095, %esi
229 andl $(~4095), %esi
230
231 /* Allocate space for page tables */
232 movl %esi, pt_loc
233 movl $ballocs, %edi
234 andl $0x7fffffff, %edi
235
236 movl %esi, (%edi)
237 addl $4, %edi
238 movl $(2 * 1024 * 1024), (%edi)
239
240 /* Fill page tables */
241 xorl %ecx, %ecx
242 xorl %ebx, %ebx
243
244 floop_pt:
245 movl $(PTE_RW | PTE_P), %eax
246 orl %ebx, %eax
247 movl %eax, (%esi, %ecx, 4)
248 addl $(4 * 1024), %ebx
249
250 incl %ecx
251 cmpl $(512 * 1024), %ecx
252
253 jl floop_pt
254
255 /* Fill page directory */
256 movl $(page_directory + 0), %esi
257 movl $(page_directory + 2048), %edi
258 xorl %ecx, %ecx
259 movl pt_loc, %ebx
260
261 floop:
262 movl $(PDE_RW | PDE_P), %eax
263 orl %ebx, %eax
264
265 /* Mapping 0x00000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
266 movl %eax, (%esi, %ecx, 4)
267
268 /* Mapping 0x80000000 + %ecx * 4M => 0x00000000 + %ecx * 4M */
269 movl %eax, (%edi, %ecx, 4)
270 addl $(4 * 1024), %ebx
271
272 incl %ecx
273 cmpl $512, %ecx
274
275 jl floop
276
277 movl %esi, %cr3
278
279 movl %cr0, %ebx
280 orl $CR0_PG, %ebx /* paging on */
281 movl %ebx, %cr0
282
283 ret
284FUNCTION_END(map_kernel_non_pse)
285
286/** Calculate unmapped address of the end of the kernel. */
287calc_kernel_end:
288 movl $hardcoded_load_address, %edi
289 andl $0x7fffffff, %edi
290 movl (%edi), %esi
291 andl $0x7fffffff, %esi
292
293 movl $hardcoded_ktext_size, %edi
294 andl $0x7fffffff, %edi
295 addl (%edi), %esi
296 andl $0x7fffffff, %esi
297
298 movl $hardcoded_kdata_size, %edi
299 andl $0x7fffffff, %edi
300 addl (%edi), %esi
301 andl $0x7fffffff, %esi
302 movl %esi, kernel_end
303
304 ret
305
306/** Find free 2M (+4k for alignment) region where to store page tables */
307find_mem_for_pt:
308 /* Check if multiboot info is present */
309 cmpl $MULTIBOOT_LOADER_MAGIC, multiboot_eax
310 je check_multiboot_map
311
312 ret
313
314 check_multiboot_map:
315
316 /* Copy address of the multiboot info to ebx */
317 movl multiboot_ebx, %ebx
318
319 /* Check if memory map flag is present */
320 movl (%ebx), %edx
321 andl $(1 << 6), %edx
322 jnz use_multiboot_map
323
324 ret
325
326 use_multiboot_map:
327
328 /* Copy address of the memory map to edx */
329 movl 48(%ebx), %edx
330 movl %edx, %ecx
331
332 addl 44(%ebx), %ecx
333
334 /* Find a free region at least 2M in size */
335 check_memmap_loop:
336
337 /* Is this a free region? */
338 cmp $1, 20(%edx)
339 jnz next_region
340
341 /* Check size */
342 cmp $0, 16(%edx)
343 jnz next_region
344
345 cmpl $(2 * 1024 * 1024 + 4 * 1024), 12(%edx)
346 jbe next_region
347
348 cmp $0, 8(%edx)
349 jz found_region
350
351 next_region:
352
353 cmp %ecx, %edx
354 jbe next_region_do
355
356 ret
357
358 next_region_do:
359
360 addl (%edx), %edx
361 addl $4, %edx
362 jmp check_memmap_loop
363
364 found_region:
365
366 /* Use end of the found region */
367 mov 4(%edx), %ecx
368 add 12(%edx), %ecx
369 sub $(2 * 1024 * 1024), %ecx
370 mov %ecx, free_area
371
372 ret
373
374/** Print string to EGA display (in light red) and halt.
375 *
376 * Should be executed from 32 bit protected mode with paging
377 * turned off. Stack is not required. This routine is used even
378 * if CONFIG_EGA is not enabled. Since we are going to halt the
379 * CPU anyway, it is always better to at least try to print
380 * some hints.
381 *
382 * @param %esi NULL-terminated string to print.
383 *
384 */
385pm_error_halt:
386 movl $0xb8000, %edi /* base of EGA text mode memory */
387 xorl %eax, %eax
388
389 /* Read bits 8 - 15 of the cursor address */
390 movw $0x3d4, %dx
391 movb $0xe, %al
392 outb %al, %dx
393
394 movw $0x3d5, %dx
395 inb %dx, %al
396 shl $8, %ax
397
398 /* Read bits 0 - 7 of the cursor address */
399 movw $0x3d4, %dx
400 movb $0xf, %al
401 outb %al, %dx
402
403 movw $0x3d5, %dx
404 inb %dx, %al
405
406 /* Sanity check for the cursor on screen */
407 cmp $2000, %ax
408 jb err_cursor_ok
409
410 movw $1998, %ax
411
412 err_cursor_ok:
413
414 movw %ax, %bx
415 shl $1, %eax
416 addl %eax, %edi
417
418 err_ploop:
419 lodsb
420
421 cmp $0, %al
422 je err_ploop_end
423
424 movb $0x0c, %ah /* black background, light red foreground */
425 stosw
426
427 /* Sanity check for the cursor on the last line */
428 inc %bx
429 cmp $2000, %bx
430 jb err_ploop
431
432 /* Scroll the screen (24 rows) */
433 movl %esi, %edx
434 movl $0xb80a0, %esi
435 movl $0xb8000, %edi
436 movl $960, %ecx
437 rep movsl
438
439 /* Clear the 24th row */
440 xorl %eax, %eax
441 movl $40, %ecx
442 rep stosl
443
444 /* Go to row 24 */
445 movl %edx, %esi
446 movl $0xb8f00, %edi
447 movw $1920, %bx
448
449 jmp err_ploop
450 err_ploop_end:
451
452 /* Write bits 8 - 15 of the cursor address */
453 movw $0x3d4, %dx
454 movb $0xe, %al
455 outb %al, %dx
456
457 movw $0x3d5, %dx
458 movb %bh, %al
459 outb %al, %dx
460
461 /* Write bits 0 - 7 of the cursor address */
462 movw $0x3d4, %dx
463 movb $0xf, %al
464 outb %al, %dx
465
466 movw $0x3d5, %dx
467 movb %bl, %al
468 outb %al, %dx
469
470 cli
471 hlt1:
472 hlt
473 jmp hlt1
474
475/** Print string to EGA display (in light green).
476 *
477 * Should be called from 32 bit protected mode with paging
478 * turned off. A stack space of at least 24 bytes is required,
479 * but the function does not establish a stack frame.
480 *
481 * Macros such as pm_status take care that this function
482 * is used only when CONFIG_EGA is enabled.
483 *
484 * @param %esi NULL-terminated string to print.
485 *
486 */
487pm_early_puts:
488 pushl %eax
489 pushl %ebx
490 pushl %ecx
491 pushl %edx
492 pushl %edi
493
494 movl $0xb8000, %edi /* base of EGA text mode memory */
495 xorl %eax, %eax
496
497 /* Read bits 8 - 15 of the cursor address */
498 movw $0x3d4, %dx
499 movb $0xe, %al
500 outb %al, %dx
501
502 movw $0x3d5, %dx
503 inb %dx, %al
504 shl $8, %ax
505
506 /* Read bits 0 - 7 of the cursor address */
507 movw $0x3d4, %dx
508 movb $0xf, %al
509 outb %al, %dx
510
511 movw $0x3d5, %dx
512 inb %dx, %al
513
514 /* Sanity check for the cursor on screen */
515 cmp $2000, %ax
516 jb pm_puts_cursor_ok
517
518 movw $1998, %ax
519
520 pm_puts_cursor_ok:
521
522 movw %ax, %bx
523 shl $1, %eax
524 addl %eax, %edi
525
526 pm_puts_ploop:
527 lodsb
528
529 cmp $0, %al
530 je pm_puts_ploop_end
531
532 movb $0x0a, %ah /* black background, light green foreground */
533 stosw
534
535 /* Sanity check for the cursor on the last line */
536 inc %bx
537 cmp $2000, %bx
538 jb pm_puts_ploop
539
540 /* Scroll the screen (24 rows) */
541 movl %esi, %edx
542 movl $0xb80a0, %esi
543 movl $0xb8000, %edi
544 movl $960, %ecx
545 rep movsl
546
547 /* Clear the 24th row */
548 xorl %eax, %eax
549 movl $40, %ecx
550 rep stosl
551
552 /* Go to row 24 */
553 movl %edx, %esi
554 movl $0xb8f00, %edi
555 movw $1920, %bx
556
557 jmp pm_puts_ploop
558 pm_puts_ploop_end:
559
560 /* Write bits 8 - 15 of the cursor address */
561 movw $0x3d4, %dx
562 movb $0xe, %al
563 outb %al, %dx
564
565 movw $0x3d5, %dx
566 movb %bh, %al
567 outb %al, %dx
568
569 /* Write bits 0 - 7 of the cursor address */
570 movw $0x3d4, %dx
571 movb $0xf, %al
572 outb %al, %dx
573
574 movw $0x3d5, %dx
575 movb %bl, %al
576 outb %al, %dx
577
578 popl %edi
579 popl %edx
580 popl %ecx
581 popl %ebx
582 popl %eax
583
584 ret
585
586/** Print string to EGA display.
587 *
588 * Should be called from 32 bit protected mode (with paging
589 * enabled and stack established). This function is ABI compliant.
590 *
591 * If CONFIG_EGA is undefined or CONFIG_FB is defined
592 * then this function does nothing.
593 *
594 * @param %ebp+0x08 NULL-terminated string to print.
595 *
596 */
597early_puts:
598
599#if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB)))
600
601 /* Prologue, save preserved registers */
602 pushl %ebp
603 movl %esp, %ebp
604 pushl %ebx
605 pushl %esi
606 pushl %edi
607
608 movl 0x08(%ebp), %esi
609 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */
610 xorl %eax, %eax
611
612 /* Read bits 8 - 15 of the cursor address */
613 movw $0x3d4, %dx
614 movb $0xe, %al
615 outb %al, %dx
616
617 movw $0x3d5, %dx
618 inb %dx, %al
619 shl $8, %ax
620
621 /* Read bits 0 - 7 of the cursor address */
622 movw $0x3d4, %dx
623 movb $0xf, %al
624 outb %al, %dx
625
626 movw $0x3d5, %dx
627 inb %dx, %al
628
629 /* Sanity check for the cursor on screen */
630 cmp $2000, %ax
631 jb early_puts_cursor_ok
632
633 movw $1998, %ax
634
635 early_puts_cursor_ok:
636
637 movw %ax, %bx
638 shl $1, %eax
639 addl %eax, %edi
640
641 early_puts_ploop:
642 lodsb
643
644 cmp $0, %al
645 je early_puts_ploop_end
646
647 movb $0x0e, %ah /* black background, yellow foreground */
648 stosw
649
650 /* Sanity check for the cursor on the last line */
651 inc %bx
652 cmp $2000, %bx
653 jb early_puts_ploop
654
655 /* Scroll the screen (24 rows) */
656 movl %esi, %edx
657 movl $(PA2KA(0xb80a0)), %esi
658 movl $(PA2KA(0xb8000)), %edi
659 movl $960, %ecx
660 rep movsl
661
662 /* Clear the 24th row */
663 xorl %eax, %eax
664 movl $40, %ecx
665 rep stosl
666
667 /* Go to row 24 */
668 movl %edx, %esi
669 movl $(PA2KA(0xb8f00)), %edi
670 movw $1920, %bx
671
672 jmp early_puts_ploop
673 early_puts_ploop_end:
674
675 /* Write bits 8 - 15 of the cursor address */
676 movw $0x3d4, %dx
677 movb $0xe, %al
678 outb %al, %dx
679
680 movw $0x3d5, %dx
681 movb %bh, %al
682 outb %al, %dx
683
684 /* Write bits 0 - 7 of the cursor address */
685 movw $0x3d4, %dx
686 movb $0xf, %al
687 outb %al, %dx
688
689 movw $0x3d5, %dx
690 movb %bl, %al
691 outb %al, %dx
692
693 /* Epilogue, restore preserved registers */
694 popl %edi
695 popl %esi
696 popl %ebx
697 leave
698
699#endif
700
701 ret
702
703#include "vesa_real.inc"
704
705.section K_DATA_START, "aw", @progbits
706
707.align 4096
708page_directory:
709 .space 4096, 0
710
711SYMBOL(bootstrap_idtr)
712 .word 0
713 .long 0
714
715SYMBOL(bootstrap_gdtr)
716 .word GDT_SELECTOR(GDT_ITEMS)
717 .long KA2PA(gdt)
718
719SYMBOL(multiboot_eax)
720 .long 0
721
722SYMBOL(multiboot_ebx)
723 .long 0
724
725pt_loc:
726 .long 0
727kernel_end:
728 .long 0
729free_area:
730 .long 0
731
732status_prot:
733 .asciz "[prot] "
734status_pse:
735 .asciz "[pse] "
736status_non_pse:
737 .asciz "[non_pse] "
738status_vesa_copy:
739 .asciz "[vesa_copy] "
740status_multiboot_cmdline:
741 .asciz "[multiboot_cmdline] "
742status_vesa_real:
743 .asciz "[vesa_real] "
744status_prot2:
745 .asciz "[prot2] "
746status_prot3:
747 .asciz "[prot3] "
748status_main:
749 .asciz "[main] "
Note: See TracBrowser for help on using the repository browser.