source: mainline/kernel/arch/amd64/src/boot/boot.S@ 76fca31

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

Fortify ia32 and amd64 kernels against mallicious uspace applications that set
DF prior to entering the kernel. For AMD64 syscalls, we don't use the CLD
instruction, but make use of the SFMASK MSR instead. Simics works fine with
it, but QEMU seems to have a problem.

  • 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/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.align 4
45.global multiboot_image_start
46multiboot_header:
47 .long MULTIBOOT_HEADER_MAGIC
48 .long MULTIBOOT_HEADER_FLAGS
49 .long -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) # checksum
50 .long multiboot_header
51 .long unmapped_ktext_start
52 .long 0
53 .long 0
54 .long multiboot_image_start
55
56multiboot_image_start:
57 cld
58 movl $START_STACK, %esp # initialize stack pointer
59 lgdtl bootstrap_gdtr # initialize Global Descriptor Table register
60
61 movw $gdtselector(KDATA_DES), %cx
62 movw %cx, %es
63 movw %cx, %ds # kernel data + stack
64 movw %cx, %ss
65 # Simics seems to remove hidden part of GS on entering user mode
66 # when _visible_ part of GS does not point to user-mode segment
67 movw $gdtselector(UDATA_DES), %cx
68 movw %cx, %fs
69 movw %cx, %gs
70
71 jmpl $gdtselector(KTEXT32_DES), $multiboot_meeting_point
72 multiboot_meeting_point:
73
74 movl %eax, grub_eax # save parameters from GRUB
75 movl %ebx, grub_ebx
76
77 # Protected 32-bit. We want to reuse the code-seg descriptor,
78 # the Default operand size must not be 1 when entering long mode
79
80 movl $(INTEL_CPUID_EXTENDED), %eax
81 cpuid
82 cmp $(INTEL_CPUID_EXTENDED), %eax
83 ja extended_cpuid_supported
84
85 movl $extended_cpuid_msg, %esi
86 jmp error_halt
87
88 extended_cpuid_supported:
89
90 movl $(AMD_CPUID_EXTENDED), %eax
91 cpuid
92 bt $(AMD_EXT_LONG_MODE), %edx
93 jc long_mode_supported
94
95 movl $long_mode_msg, %esi
96 jmp error_halt
97
98 long_mode_supported:
99
100 bt $(AMD_EXT_NOEXECUTE), %edx
101 jc noexecute_supported
102
103 movl $noexecute_msg, %esi
104 jmp error_halt
105
106 noexecute_supported:
107
108 movl $(INTEL_CPUID_STANDARD), %eax
109 cpuid
110 bt $(INTEL_FXSAVE), %edx
111 jc fx_supported
112
113 movl $fx_msg, %esi
114 jmp error_halt
115
116 fx_supported:
117
118 bt $(INTEL_SSE2), %edx
119 jc sse2_supported
120
121 movl $sse2_msg, %esi
122 jmp error_halt
123
124 sse2_supported:
125
126#ifdef CONFIG_FB
127 mov $vesa_init, %esi
128 mov $VESA_INIT_SEGMENT << 4, %edi
129 mov $e_vesa_init - vesa_init, %ecx
130 rep movsb
131
132 mov $VESA_INIT_SEGMENT << 4, %edi
133 jmpl *%edi
134
135 vesa_meeting_point:
136
137 mov %esi, KA2PA(vesa_ph_addr)
138 mov %di, KA2PA(vesa_height)
139 shr $16, %edi
140 mov %di, KA2PA(vesa_width)
141 mov %bx, KA2PA(vesa_scanline)
142 shr $16, %ebx
143 mov %bx, KA2PA(vesa_bpp)
144#endif
145
146 # Enable 64-bit page translation entries - CR4.PAE = 1.
147 # Paging is not enabled until after long mode is enabled
148
149 movl %cr4, %eax
150 btsl $5, %eax
151 movl %eax, %cr4
152
153 # Set up paging tables
154
155 leal ptl_0, %eax
156 movl %eax, %cr3
157
158 # Enable long mode
159
160 movl $EFER_MSR_NUM, %ecx # EFER MSR number
161 rdmsr # Read EFER
162 btsl $AMD_LME_FLAG, %eax # Set LME = 1
163 wrmsr # Write EFER
164
165 # Enable paging to activate long mode (set CR0.PG = 1)
166
167 movl %cr0, %eax
168 btsl $31, %eax
169 movl %eax, %cr0
170
171 # At this point we are in compatibility mode
172
173 jmpl $gdtselector(KTEXT_DES), $start64
174
175.code64
176start64:
177 movq $(PA2KA(START_STACK)), %rsp
178 movl grub_eax, %eax
179 movl grub_ebx, %ebx
180
181 cmpl $MULTIBOOT_LOADER_MAGIC, %eax # compare GRUB signature
182 je valid_boot
183
184 xorl %ecx, %ecx # no memory size or map available
185 movl %ecx, e820counter
186
187 jmp invalid_boot
188
189 valid_boot:
190
191 movl (%ebx), %eax # ebx = physical address of struct multiboot_info
192
193 bt $3, %eax # mbi->flags[3] (mods_count, mods_addr valid)
194 jc mods_valid
195
196 xorq %rcx, %rcx
197 movq %rcx, init
198 jmp mods_end
199
200 mods_valid:
201
202 xorq %rcx, %rcx
203 movl 20(%ebx), %ecx # mbi->mods_count
204 movq %rcx, init
205
206 cmpl $0, %ecx
207 je mods_end
208
209 movl 24(%ebx), %esi # mbi->mods_addr
210 movq $init, %rdi
211
212 mods_loop:
213
214 xorq %rdx, %rdx
215 movl 0(%esi), %edx # mods->mod_start
216 movq $0xffff800000000000, %r10
217 addq %r10, %rdx
218 movq %rdx, 8(%rdi)
219
220 xorq %rdx, %rdx
221 movl 4(%esi), %edx
222 subl 0(%esi), %edx # mods->mod_end - mods->mod_start
223 movq %rdx, 16(%rdi)
224
225 addl $16, %esi
226 addq $16, %rdi
227
228 loop mods_loop
229
230 mods_end:
231
232 bt $6, %eax # mbi->flags[6] (mmap_length, mmap_addr valid)
233 jc mmap_valid
234
235 xorl %edx, %edx
236 jmp mmap_invalid
237
238 mmap_valid:
239 movl 44(%ebx), %ecx # mbi->mmap_length
240 movl 48(%ebx), %esi # mbi->mmap_addr
241 movq $e820table, %rdi
242 xorl %edx, %edx
243
244 mmap_loop:
245 cmpl $0, %ecx
246 jle mmap_end
247
248 movl 4(%esi), %eax # mmap->base_addr_low
249 movl %eax, (%rdi)
250
251 movl 8(%esi), %eax # mmap->base_addr_high
252 movl %eax, 4(%rdi)
253
254 movl 12(%esi), %eax # mmap->length_low
255 movl %eax, 8(%rdi)
256
257 movl 16(%esi), %eax # mmap->length_high
258 movl %eax, 12(%rdi)
259
260 movl 20(%esi), %eax # mmap->type
261 movl %eax, 16(%rdi)
262
263 movl (%esi), %eax # mmap->size
264 addl $0x4, %eax
265 addl %eax, %esi
266 subl %eax, %ecx
267 addq $MEMMAP_E820_RECORD_SIZE, %rdi
268 incl %edx
269 jmp mmap_loop
270
271 mmap_end:
272
273 mmap_invalid:
274 movl %edx, e820counter
275
276 invalid_boot:
277
278#ifdef CONFIG_SMP
279
280 # copy AP bootstrap routines below 1 MB
281
282 movq $BOOT_OFFSET, %rsi
283 movq $AP_BOOT_OFFSET, %rdi
284 movq $_hardcoded_unmapped_size, %rcx
285 rep movsb
286
287#endif
288
289 call main_bsp # never returns
290
291 cli
292 hlt
293
294#ifdef CONFIG_FB
295.code32
296vesa_init:
297 jmp $gdtselector(VESA_INIT_DES), $vesa_init_real - vesa_init
298
299.code16
300vesa_init_real:
301
302 mov %cr0, %eax
303 and $~1, %eax
304 mov %eax, %cr0
305
306 jmp $VESA_INIT_SEGMENT, $vesa_init_real2 - vesa_init
307
308vesa_init_real2:
309
310 mov $VESA_INIT_SEGMENT, %bx
311
312 mov %bx, %es
313 mov %bx, %fs
314 mov %bx, %gs
315 mov %bx, %ds
316 mov %bx, %ss
317
318 movl $0x0000fffc, %esp
319 movl $0x0000fffc, %ebp
320
321#define VESA_INFO_SIZE 1024
322
323#define VESA_MODE_ATTRIBUTES_OFFSET 0
324#define VESA_MODE_LIST_PTR_OFFSET 14
325#define VESA_MODE_SCANLINE_OFFSET 16
326#define VESA_MODE_WIDTH_OFFSET 18
327#define VESA_MODE_HEIGHT_OFFSET 20
328#define VESA_MODE_BPP_OFFSET 25
329#define VESA_MODE_PHADDR_OFFSET 40
330
331#define VESA_END_OF_MODES 0xffff
332
333#define VESA_OK 0x4f
334
335#define VESA_GET_INFO 0x4f00
336#define VESA_GET_MODE_INFO 0x4f01
337#define VESA_SET_MODE 0x4f02
338#define VESA_SET_PALETTE 0x4f09
339
340#define CONFIG_VESA_BPP_a 255
341
342#if CONFIG_VESA_BPP == 24
343#define CONFIG_VESA_BPP_VARIANT 32
344#endif
345
346 mov $VESA_GET_INFO, %ax
347 mov $e_vesa_init - vesa_init, %di
348 push %di
349 int $0x10
350
351 pop %di
352 cmp $VESA_OK, %al
353 jnz 0f
354
355 mov 2 + VESA_MODE_LIST_PTR_OFFSET(%di), %si
356 mov %si, %gs
357 mov VESA_MODE_LIST_PTR_OFFSET(%di), %si
358
359 add $VESA_INFO_SIZE, %di
360
3611:# Try next mode
362 mov %gs:(%si), %cx
363 cmp $VESA_END_OF_MODES, %cx
364 jz 0f
365
366 inc %si
367 inc %si
368 push %cx
369 push %di
370 push %si
371 mov $VESA_GET_MODE_INFO, %ax
372 int $0x10
373
374 pop %si
375 pop %di
376 pop %cx
377 cmp $VESA_OK, %al
378 jnz 0f
379
380 mov $CONFIG_VESA_WIDTH, %ax
381 cmp VESA_MODE_WIDTH_OFFSET(%di), %ax
382 jnz 1b
383
384 mov $CONFIG_VESA_HEIGHT, %ax
385 cmp VESA_MODE_HEIGHT_OFFSET(%di), %ax
386 jnz 1b
387
388 mov $CONFIG_VESA_BPP, %al
389 cmp VESA_MODE_BPP_OFFSET(%di), %al
390
391#ifdef CONFIG_VESA_BPP_VARIANT
392 jz 2f
393
394 mov $CONFIG_VESA_BPP_VARIANT, %al
395 cmp VESA_MODE_BPP_OFFSET(%di), %al
396#endif
397 jnz 1b
398
3992:
400
401 mov %cx, %bx
402 or $0xc000, %bx
403 push %di
404 mov $VESA_SET_MODE, %ax
405 int $0x10
406
407 pop %di
408 cmp $VESA_OK, %al
409 jnz 0f
410
411#if CONFIG_VESA_BPP == 8
412
413 # Set 3:2:3 VGA palette
414
415 mov VESA_MODE_ATTRIBUTES_OFFSET(%di), %ax
416 push %di
417 mov $vga323 - vesa_init, %di
418 mov $0x100, %ecx
419
420 bt $5, %ax # Test if VGA compatible registers are present
421 jnc vga_compat
422
423 # Try VESA routine to set palette
424
425 mov $VESA_SET_PALETTE, %ax
426 xor %bl, %bl
427 xor %dx, %dx
428 int $0x10
429
430 jmp vga_not_compat
431
432 vga_compat:
433
434 # Try VGA registers to set palette
435
436 movw $0x3c6, %dx # Set palette mask
437 movb $0xff, %al
438 outb %al, %dx
439
440 movw $0x3c8, %dx # First index to set
441 xor %al, %al
442 outb %al, %dx
443
444 movw $0x3c9, %dx # Data port
445 vga_loop:
446 movb %es:2(%di), %al
447 outb %al, %dx
448
449 movb %es:1(%di), %al
450 outb %al, %dx
451
452 movb %es:(%di), %al
453 outb %al, %dx
454
455 addw $4, %di
456 loop vga_loop
457
458 vga_not_compat:
459
460 pop %di
461
462#endif
463
464 mov VESA_MODE_PHADDR_OFFSET(%di), %esi
465 mov VESA_MODE_WIDTH_OFFSET(%di), %ax
466 shl $16, %eax
467 mov VESA_MODE_HEIGHT_OFFSET(%di), %ax
468 mov VESA_MODE_BPP_OFFSET(%di), %bl
469 xor %bh, %bh
470 shl $16, %ebx
471 mov VESA_MODE_SCANLINE_OFFSET(%di), %bx
472 mov %eax, %edi
473
4748:
475
476 mov %cr0, %eax
477 or $1, %eax
478 mov %eax, %cr0
479
480 jmp 9f
4819:
482
483 ljmpl $gdtselector(KTEXT32_DES), $(vesa_init_protect - vesa_init + VESA_INIT_SEGMENT << 4)
484
4850:# No prefered mode found
486 mov $0x111, %cx
487 push %di
488 push %cx
489 mov $VESA_GET_MODE_INFO, %ax
490 int $0x10
491
492 pop %cx
493 pop %di
494 cmp $VESA_OK, %al
495 jnz 1f
496 jz 2b # Force relative jump
497
4981:
499 mov $0x0003, %ax
500 int $0x10
501 mov $0xffffffff, %edi # EGA text mode used, because of problems with VESA
502 xor %ax, %ax
503 jz 8b # Force relative jump
504
505vga323:
506#include "vga323.pal"
507
508.code32
509vesa_init_protect:
510 movw $gdtselector(KDATA_DES), %cx
511 movw %cx, %es
512 movw %cx, %ds # kernel data + stack
513 movw %cx, %ss
514 # Simics seems to remove hidden part of GS on entering user mode
515 # when _visible_ part of GS does not point to user-mode segment
516 movw $gdtselector(UDATA_DES), %cx
517 movw %cx, %fs
518 movw %cx, %gs
519
520 movl $START_STACK, %esp # initialize stack pointer
521
522 jmpl $gdtselector(KTEXT32_DES), $vesa_meeting_point
523
524.align 4
525e_vesa_init:
526#endif
527
528# Print string from %esi to EGA display (in red) and halt
529error_halt:
530 movl $0xb8000, %edi # base of EGA text mode memory
531 xorl %eax, %eax
532
533 movw $0x3d4, %dx # read bits 8 - 15 of the cursor address
534 movb $0xe, %al
535 outb %al, %dx
536
537 movw $0x3d5, %dx
538 inb %dx, %al
539 shl $8, %ax
540
541 movw $0x3d4, %dx # read bits 0 - 7 of the cursor address
542 movb $0xf, %al
543 outb %al, %dx
544
545 movw $0x3d5, %dx
546 inb %dx, %al
547
548 cmp $1920, %ax
549 jbe cursor_ok
550 movw $1920, %ax # sanity check for the cursor on the last line
551 cursor_ok:
552
553 movw %ax, %bx
554 shl $1, %eax
555 addl %eax, %edi
556
557 movw $0x0c00, %ax # black background, light red foreground
558
559 ploop:
560 lodsb
561 cmp $0, %al
562 je ploop_end
563 stosw
564 inc %bx
565 jmp ploop
566 ploop_end:
567
568 movw $0x3d4, %dx # write bits 8 - 15 of the cursor address
569 movb $0xe, %al
570 outb %al, %dx
571
572 movw $0x3d5, %dx
573 movb %bh, %al
574 outb %al, %dx
575
576 movw $0x3d4, %dx # write bits 0 - 7 of the cursor address
577 movb $0xf, %al
578 outb %al, %dx
579
580 movw $0x3d5, %dx
581 movb %bl, %al
582 outb %al, %dx
583
584 cli
585 hlt
586
587
588.section K_INI_PTLS, "aw", @progbits
589
590#
591# Macro for generating initial page table contents.
592# @param cnt Number of entries to generat. Must be multiple of 8.
593# @param g Number of GB that will be added to the mapping.
594#
595.macro ptl2gen cnt g
596.if \cnt
597 ptl2gen "\cnt - 8" \g
598 .quad ((\cnt - 8) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
599 .quad ((\cnt - 7) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
600 .quad ((\cnt - 6) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
601 .quad ((\cnt - 5) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
602 .quad ((\cnt - 4) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
603 .quad ((\cnt - 3) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
604 .quad ((\cnt - 2) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
605 .quad ((\cnt - 1) * 0x200000) + (\g * 1024 * 1024 * 1024) | (PTL_WRITABLE | PTL_PRESENT | PTL_2MB_PAGE)
606.endif
607.endm
608
609# Page table for pages in the first gigabyte.
610.align 4096
611.global ptl_2_0g
612ptl_2_0g:
613 ptl2gen 512 0
614
615# Page table for pages in the second gigabyte.
616.align 4096
617.global ptl_2_1g
618ptl_2_1g:
619 ptl2gen 512 1
620
621# Page table for pages in the third gigabyte.
622.align 4096
623.global ptl_2_2g
624ptl_2_2g:
625 ptl2gen 512 2
626
627# Page table for pages in the fourth gigabyte.
628.align 4096
629.global ptl_2_3g
630ptl_2_3g:
631 ptl2gen 512 3
632
633.align 4096
634.global ptl_1
635ptl_1:
636 # Identity mapping for [0; 4G)
637 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
638 .quad ptl_2_1g + (PTL_WRITABLE | PTL_PRESENT)
639 .quad ptl_2_2g + (PTL_WRITABLE | PTL_PRESENT)
640 .quad ptl_2_3g + (PTL_WRITABLE | PTL_PRESENT)
641 .fill 506, 8, 0
642 # Mapping of [0; 1G) at -2G
643 .quad ptl_2_0g + (PTL_WRITABLE | PTL_PRESENT)
644 .fill 1, 8, 0
645
646.align 4096
647.global ptl_0
648ptl_0:
649 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
650 .fill 255,8,0
651 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
652 .fill 254,8,0
653 .quad ptl_1 + (PTL_WRITABLE | PTL_PRESENT)
654
655.section K_DATA_START, "aw", @progbits
656
657.global bootstrap_gdtr
658bootstrap_gdtr:
659 .word gdtselector(GDT_ITEMS)
660 .long KA2PA(gdt)
661
662grub_eax:
663 .long 0
664
665grub_ebx:
666 .long 0
667
668extended_cpuid_msg:
669 .asciz "Extended CPUID not supported. System halted."
670long_mode_msg:
671 .asciz "64 bit long mode not supported. System halted."
672noexecute_msg:
673 .asciz "No-execute pages not supported. System halted."
674fx_msg:
675 .asciz "FXSAVE/FXRESTORE instructions not supported. System halted."
676sse2_msg:
677 .asciz "SSE2 instructions not supported. System halted."
Note: See TracBrowser for help on using the repository browser.