Last active
January 25, 2017 22:01
-
-
Save hawkw/72f8eafa05cb30ebe34e3a93e7ac0a7e to your computer and use it in GitHub Desktop.
boot.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
In archive target/x86_64-sos-kernel-gnu/debug/build/sos_kernel-9a7755fc73ed37f1/out/libboot.a: | |
boot.o: file format elf64-x86-64 | |
Disassembly of section .text: | |
0000000000000000 <start>: | |
; == start the kernel ======================================================== | |
; this is the beginning of our boot process called by GRUB. | |
start: | |
; 0. Move the stack pointer to the top of the stack. --------------------- | |
mov esp, stack_top | |
0: bc 00 00 00 00 mov $0x0,%esp | |
; 1. Move Multiboot info pointer to edi ---------------------------------- | |
mov edi, ebx | |
5: 89 df mov %ebx,%edi | |
; 2. Make sure that the system supports SOS. ----------------------------- | |
call is_multiboot ; check that multiboot is supported | |
7: e8 36 00 00 00 callq 42 <is_multiboot> | |
call is_cpuid ; check CPUID is supported (to check for long mode) | |
c: e8 5f 00 00 00 callq 70 <is_cpuid> | |
call is_long_mode ; check if long mode (64-bit) is available. | |
11: e8 38 00 00 00 callq 4e <is_long_mode> | |
; 3. if everything is okay, create the page tables and start long mode | |
call create_page_tables | |
16: e8 7d 00 00 00 callq 98 <create_page_tables> | |
call set_long_mode | |
1b: e8 c1 00 00 00 callq e1 <set_long_mode> | |
; 4. load the 64-bit GDT | |
lgdt [gdt64.ptr] | |
20: 0f 01 15 00 00 00 00 lgdt 0x0(%rip) # 27 <start+0x27> | |
; 5. update selectors | |
mov ax, 16 | |
27: 66 b8 10 00 mov $0x10,%ax | |
mov ss, ax ; stack selector | |
2b: 8e d0 mov %eax,%ss | |
mov ds, ax ; data selector | |
2d: 8e d8 mov %eax,%ds | |
mov es, ax ; extra selector | |
2f: 8e c0 mov %eax,%es | |
; 6. print `OK` to screen and jump to the 64-bit boot subroutine. | |
mov dword [0xb8000], 0x2f4b2f4f | |
31: c7 05 00 80 0b 00 4f movl $0x2f4b2f4f,0xb8000(%rip) # b803b <heap_base+0xb203b> | |
38: 2f 4b 2f | |
jmp gdt64.code:arch_init | |
3b: ea (bad) | |
3c: 00 00 add %al,(%rax) | |
3e: 00 00 add %al,(%rax) | |
40: 08 00 or %al,(%rax) | |
0000000000000042 <is_multiboot>: | |
; == Tests whether or not multiboot is enabled ============================== | |
is_multiboot: | |
cmp eax, 0x36d76289 | |
42: 3d 89 62 d7 36 cmp $0x36d76289,%eax | |
jne .no_multiboot | |
47: 75 01 jne 4a <is_multiboot.no_multiboot> | |
ret | |
49: c3 retq | |
000000000000004a <is_multiboot.no_multiboot>: | |
.no_multiboot: | |
mov al, "0" | |
4a: b0 30 mov $0x30,%al | |
jmp err | |
4c: eb 3a jmp 88 <err> | |
000000000000004e <is_long_mode>: | |
; == Tests whether or not long mode is available ============================== | |
; If long mode is not available, die (we are a long mode OS). | |
is_long_mode: | |
mov eax, 0x80000000 ; Set the A-register to 0x80000000. | |
4e: b8 00 00 00 80 mov $0x80000000,%eax | |
cpuid ; CPU identification. | |
53: 0f a2 cpuid | |
cmp eax, 0x80000001 ; Compare the A-register with 0x80000001. | |
55: 3d 01 00 00 80 cmp $0x80000001,%eax | |
jb .no_long_mode ; It is less, there is no long mode. | |
5a: 72 10 jb 6c <is_long_mode.no_long_mode> | |
mov eax, 0x80000001 ; Set the A-register to 0x80000001. | |
5c: b8 01 00 00 80 mov $0x80000001,%eax | |
cpuid ; Do the CPUID thing once more. | |
61: 0f a2 cpuid | |
test edx, 1 << 29 ; Test if the LM-bit, (bit 29), is set in edx. | |
63: f7 c2 00 00 00 20 test $0x20000000,%edx | |
jz .no_long_mode ; If it isn't, there is no long mode, | |
69: 74 01 je 6c <is_long_mode.no_long_mode> | |
ret ; and we are left with only the void for company. | |
6b: c3 retq | |
000000000000006c <is_long_mode.no_long_mode>: | |
.no_long_mode: | |
mov al, "2" | |
6c: b0 32 mov $0x32,%al | |
jmp err | |
6e: eb 18 jmp 88 <err> | |
0000000000000070 <is_cpuid>: | |
; == Tests wether or not CPUID is available ================================== | |
; If the system does not support CPUID, we cannot boot, since we need to use | |
; CPUID to check if we can switch to 64-bit long mode | |
is_cpuid: | |
pushfd ; Store the FLAGS-register. | |
70: 9c pushfq | |
pop eax ; Restore the A-register. | |
71: 58 pop %rax | |
mov ecx, eax ; Set the C-register to the A-register. | |
72: 89 c1 mov %eax,%ecx | |
xor eax, 1 << 21 ; Flip the ID-bit, which is bit 21. | |
74: 35 00 00 20 00 xor $0x200000,%eax | |
push eax ; Store the A-register. | |
79: 50 push %rax | |
popfd ; Restore the FLAGS-register. | |
7a: 9d popfq | |
pushfd ; Store the FLAGS-register. | |
7b: 9c pushfq | |
pop eax ; Restore the A-register. | |
7c: 58 pop %rax | |
push ecx ; Store the C-register. | |
7d: 51 push %rcx | |
popfd ; Restore the FLAGS-register. | |
7e: 9d popfq | |
xor eax, ecx ; Do a XOR A-register andC-register. | |
7f: 31 c8 xor %ecx,%eax | |
jz .no_cpuid ; The zero flag is set, no CPUID. | |
81: 74 01 je 84 <is_cpuid.no_cpuid> | |
ret ; CPUID is available for use. | |
83: c3 retq | |
0000000000000084 <is_cpuid.no_cpuid>: | |
.no_cpuid: | |
mov al, "1" | |
84: b0 31 mov $0x31,%al | |
jmp err | |
86: eb 00 jmp 88 <err> | |
0000000000000088 <err>: | |
; == Prints a boot error code to the VGA buffer ============================== | |
err: | |
mov dword [0xb8000], 0x4f524f45 | |
88: c7 05 00 80 0b 00 45 movl $0x4f524f45,0xb8000(%rip) # b8092 <heap_base+0xb2092> | |
8f: 4f 52 4f | |
mov byte [0xb8004], al | |
92: a2 04 80 0b 00 f4 b8 movabs %al,0xb8f4000b8004 | |
99: 00 00 | |
0000000000000098 <create_page_tables>: | |
; - the first PML4 entry -> PDP | |
; - the first PDP entry -> PD | |
; - each PD entry to its own 2mB page | |
create_page_tables: | |
; recursive map last entry in PML4 --------------------------------------- | |
mov eax, pml4_table | |
98: b8 00 00 00 00 mov $0x0,%eax | |
or eax, 0b11 | |
9d: 83 c8 03 or $0x3,%eax | |
mov [pml4_table + 511 * 8], eax | |
a0: a3 00 00 00 00 b8 00 movabs %eax,0xb800000000 | |
a7: 00 00 | |
page_map pml4_table, pdp_table ; map first PML4 entry to PDP table | |
a9: 00 83 c8 03 a3 00 add %al,0xa303c8(%rbx) | |
af: 00 00 add %al,(%rax) | |
b1: 00 b8 00 00 00 00 add %bh,0x0(%rax) | |
page_map pdp_table, pd_table ; map first PDP entry to PD table | |
b7: 83 c8 03 or $0x3,%eax | |
ba: a3 00 00 00 00 b9 00 movabs %eax,0xb900000000 | |
c1: 00 00 | |
... | |
00000000000000c4 <create_page_tables.pd_table_map>: | |
; map each PD table entry to its own 2mB page | |
mov ecx, 0 | |
.pd_table_map: ; maps the PD table ----------------------------------------- | |
mov eax, 0x200000 ; 2 mB | |
c4: b8 00 00 20 00 mov $0x200000,%eax | |
mul ecx ; times the start address of the page | |
c9: f7 e1 mul %ecx | |
or eax, 0b10000011 ; check if present + writable + huge | |
cb: 0d 83 00 00 00 or $0x83,%eax | |
mov [pd_table + ecx * 8], eax ; map nth entry from pd -> own page | |
d0: 89 04 cd 00 00 00 00 mov %eax,0x0(,%rcx,8) | |
; increment counter and check if done | |
inc ecx | |
d7: 41 81 f9 00 02 00 00 cmp $0x200,%r9d | |
cmp ecx, 512 | |
jne .pd_table_map | |
de: 75 e4 jne c4 <create_page_tables.pd_table_map> | |
ret | |
e0: c3 retq | |
00000000000000e1 <set_long_mode>: | |
; == Sets long mode and enables paging ======================================= | |
; In order to do this, we must first create the initial page tables. | |
set_long_mode: | |
; load PML4 addr to cr3 register ----------------------------------------- | |
mov eax, pml4_table | |
e1: b8 00 00 00 00 mov $0x0,%eax | |
mov cr3, eax | |
e6: 0f 22 d8 mov %rax,%cr3 | |
; enable PAE-flag in cr4 (Physical Address Extension) -------------------- | |
mov eax, cr4 | |
e9: 0f 20 e0 mov %cr4,%rax | |
or eax, 1 << 5 | |
ec: 83 c8 20 or $0x20,%eax | |
mov cr4, eax | |
ef: 0f 22 e0 mov %rax,%cr4 | |
; set the long mode bit in the EFER MSR (model specific register) -------- | |
mov ecx, 0xC0000080 | |
f2: b9 80 00 00 c0 mov $0xc0000080,%ecx | |
rdmsr | |
f7: 0f 32 rdmsr | |
or eax, 1 << 8 | |
f9: 0d 00 01 00 00 or $0x100,%eax | |
wrmsr | |
fe: 0f 30 wrmsr | |
; enable paging in the cr0 register ------------------------------------- | |
mov eax, cr0 | |
100: 0f 20 c0 mov %cr0,%rax | |
or eax, 1 << 31 | |
103: 0d 00 00 00 80 or $0x80000000,%eax | |
or eax, 1 << 16 | |
108: 0d 00 00 01 00 or $0x10000,%eax | |
mov cr0, eax | |
10d: 0f 22 c0 mov %rax,%cr0 | |
ret | |
110: c3 retq |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
boot/target/boot.o: file format elf64-x86-64 | |
Disassembly of section .text._start: | |
0000000000000000 <_start>: | |
#[cold] | |
#[no_mangle] | |
#[naked] | |
pub unsafe extern "C" fn _start() { | |
// 0. Move the stack pointer to the top of the stack. | |
asm!( "mov esp, stack_top" | |
0: 8b 25 00 00 00 00 mov 0x0(%rip),%esp # 6 <_start+0x6> | |
/// } | |
/// ``` | |
#[inline] | |
#[stable(feature = "volatile", since = "1.9.0")] | |
pub unsafe fn write_volatile<T>(dst: *mut T, src: T) { | |
intrinsics::volatile_store(dst, src); | |
6: 66 c7 05 00 80 0b 00 movw $0x230,0xb8000(%rip) # b800f <_start+0xb800f> | |
d: 30 02 | |
:::: "intel"); | |
boot_write(b"0"); | |
asm!("cli"); | |
f: fa cli | |
10: 66 c7 05 00 80 0b 00 movw $0x231,0xb8000(%rip) # b8019 <_start+0xb8019> | |
17: 31 02 | |
19: 66 c7 05 00 80 0b 00 movw $0x232,0xb8000(%rip) # b8022 <_start+0xb8022> | |
20: 32 02 | |
// 3. if everything is okay, create the page tables and start long mode | |
const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB | |
//-- map the PML4 and PDP tables ----------------------------------------- | |
// recursive map last PML4 entry | |
pml4_table[511] = (&pml4_table[0] as *const _ as u64) | 3; | |
22: b8 00 00 00 00 mov $0x0,%eax | |
27: 83 c8 03 or $0x3,%eax | |
2a: a3 f8 0f 00 00 c7 05 movabs %eax,0xffc05c700000ff8 | |
31: fc 0f | |
33: 00 00 add %al,(%rax) | |
35: 00 00 add %al,(%rax) | |
37: 00 00 add %al,(%rax) | |
// map first PML4 entry to PDP table | |
pml4_table[0] = (&pdp_table[0] as *const _ as u64) | 3; | |
39: b8 00 00 00 00 mov $0x0,%eax | |
3e: 83 c8 03 or $0x3,%eax | |
41: a3 00 00 00 00 c7 05 movabs %eax,0x405c700000000 | |
48: 04 00 | |
4a: 00 00 add %al,(%rax) | |
4c: 00 00 add %al,(%rax) | |
4e: 00 00 add %al,(%rax) | |
// map first PDPT entry to PD table | |
pdp_table[0] = (&pd_table[0] as *const _ as u64) | 3; | |
50: b8 00 00 00 00 mov $0x0,%eax | |
55: 83 c8 03 or $0x3,%eax | |
58: a3 00 00 00 00 c7 05 movabs %eax,0x405c700000000 | |
5f: 04 00 | |
61: 00 00 add %al,(%rax) | |
63: 00 00 add %al,(%rax) | |
65: 00 00 add %al,(%rax) | |
67: 66 c7 05 00 80 0b 00 movw $0x233,0xb8000(%rip) # b8070 <_start+0xb8070> | |
6e: 33 02 | |
70: 66 c7 05 02 80 0b 00 movw $0x22e,0xb8002(%rip) # b807b <_start+0xb807b> | |
77: 2e 02 | |
79: 66 c7 05 04 80 0b 00 movw $0x231,0xb8004(%rip) # b8086 <_start+0xb8086> | |
80: 31 02 | |
82: 31 c9 xor %ecx,%ecx | |
84: b8 00 f0 ff ff mov $0xfffff000,%eax | |
89: 90 nop | |
8a: 90 nop | |
8b: 90 nop | |
8c: 90 nop | |
8d: 90 nop | |
8e: 90 nop | |
8f: 90 nop | |
//-- map the PD table ---------------------------------------------------- | |
for (number, entry) in pd_table.iter_mut().enumerate() { | |
// set each PD entry equal to the start address of the page (the page | |
// number times the page's size) | |
let addr = number as u64 * HUGE_PAGE_SIZE; | |
90: 89 ca mov %ecx,%edx | |
92: c1 ea 0b shr $0xb,%edx | |
#[rustc_inherit_overflow_checks] | |
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> { | |
self.iter.next().map(|a| { | |
let ret = (self.count, a); | |
// Possible undefined overflow. | |
self.count += 1; | |
95: 8d 71 01 lea 0x1(%rcx),%esi | |
98: c1 e1 15 shl $0x15,%ecx | |
// with the appropriate flags (present + writable + huge) | |
// TODO: do we want to do this using bitflags, or is that too | |
// heavyweight for the boot module? | |
// - eliza, 1/23/2017 | |
*entry = addr | 0b10000011; | |
9b: 81 c9 83 00 00 00 or $0x83,%ecx | |
a1: 89 90 04 10 00 00 mov %edx,0x1004(%rax) | |
a7: 89 88 00 10 00 00 mov %ecx,0x1000(%rax) | |
unsafe { | |
if mem::size_of::<T>() != 0 { | |
assume(!self.ptr.is_null()); | |
assume(!self.end.is_null()); | |
} | |
if self.ptr == self.end { | |
ad: 83 c0 08 add $0x8,%eax | |
b0: 89 f1 mov %esi,%ecx | |
b2: 75 dc jne 90 <_start+0x90> | |
#[naked] | |
#[inline(always)] | |
pub unsafe fn set_long_mode() { | |
// load PML4 addr to cr3 | |
asm!( "mov eax, pml4_table | |
b4: a1 00 00 00 00 0f 22 movabs 0xfd8220f00000000,%eax | |
bb: d8 0f | |
mov cr3, eax" | |
:::: "intel"); | |
// boot_write(b"3.2"); | |
// enable PAE flag in cr4 | |
asm!( "mov eax, cr4 | |
bd: 20 e0 and %ah,%al | |
bf: 83 c8 20 or $0x20,%eax | |
c2: 0f 22 e0 mov %rax,%cr4 | |
mov cr4, eax" | |
:::: "intel"); | |
// boot_write(b"3.3"); | |
// set the long mode bit in EFER MSR (model specific register) | |
asm!( "mov ecx, 0xC0000080 | |
c5: b9 80 00 00 c0 mov $0xc0000080,%ecx | |
ca: 0f 32 rdmsr | |
cc: 0d 00 01 00 00 or $0x100,%eax | |
d1: 0f 30 wrmsr | |
d3: 66 c7 05 00 80 0b 00 movw $0x233,0xb8000(%rip) # b80dc <_start+0xb80dc> | |
da: 33 02 | |
dc: 66 c7 05 02 80 0b 00 movw $0x22e,0xb8002(%rip) # b80e7 <_start+0xb80e7> | |
e3: 2e 02 | |
e5: 66 c7 05 04 80 0b 00 movw $0x234,0xb8004(%rip) # b80f2 <_start+0xb80f2> | |
ec: 34 02 | |
wrmsr" | |
:::: "intel"); | |
boot_write(b"3.4"); | |
// enable paging in cr0 | |
asm!( "mov eax, cr0 | |
ee: 0f 20 c0 mov %cr0,%rax | |
f1: 0d 00 00 00 80 or $0x80000000,%eax | |
f6: 0d 00 00 01 00 or $0x10000,%eax | |
fb: 0f 22 c0 mov %rax,%cr0 | |
fe: 66 c7 05 00 80 0b 00 movw $0x233,0xb8000(%rip) # b8107 <_start+0xb8107> | |
105: 33 02 | |
107: 66 c7 05 02 80 0b 00 movw $0x22e,0xb8002(%rip) # b8112 <_start+0xb8112> | |
10e: 2e 02 | |
110: 66 c7 05 04 80 0b 00 movw $0x235,0xb8004(%rip) # b811d <_start+0xb811d> | |
117: 35 02 | |
create_page_tables(); | |
set_long_mode(); | |
// 4. load the 64-bit GDT | |
asm!( "lgdt ($0)" | |
119: b8 1a 00 00 00 mov $0x1a,%eax | |
11e: 0f 01 10 lgdt (%rax) | |
121: 66 c7 05 00 80 0b 00 movw $0x234,0xb8000(%rip) # b812a <_start+0xb812a> | |
128: 34 02 | |
: "memory" | |
); | |
boot_write(b"4"); | |
// 5. update selectors | |
asm!("mov ax, 16" :::: "intel"); | |
12a: 66 b8 10 00 mov $0x10,%ax | |
12e: 66 c7 05 00 80 0b 00 movw $0x235,0xb8000(%rip) # b8137 <_start+0xb8137> | |
135: 35 02 | |
137: 66 c7 05 02 80 0b 00 movw $0x22e,0xb8002(%rip) # b8142 <_start+0xb8142> | |
13e: 2e 02 | |
140: 66 c7 05 04 80 0b 00 movw $0x231,0xb8004(%rip) # b814d <_start+0xb814d> | |
147: 31 02 | |
boot_write(b"5.1"); | |
// stack selector | |
asm!("mov ss, ax" :::: "intel"); | |
149: 66 8e d0 mov %ax,%ss | |
14c: 66 c7 05 00 80 0b 00 movw $0x235,0xb8000(%rip) # b8155 <_start+0xb8155> | |
153: 35 02 | |
155: 66 c7 05 02 80 0b 00 movw $0x22e,0xb8002(%rip) # b8160 <_start+0xb8160> | |
15c: 2e 02 | |
15e: 66 c7 05 04 80 0b 00 movw $0x232,0xb8004(%rip) # b816b <_start+0xb816b> | |
165: 32 02 | |
boot_write(b"5.2"); | |
// data selector | |
asm!("mov ds, ax" :::: "intel"); | |
167: 66 8e d8 mov %ax,%ds | |
16a: 66 c7 05 00 80 0b 00 movw $0x235,0xb8000(%rip) # b8173 <_start+0xb8173> | |
171: 35 02 | |
173: 66 c7 05 02 80 0b 00 movw $0x22e,0xb8002(%rip) # b817e <_start+0xb817e> | |
17a: 2e 02 | |
17c: 66 c7 05 04 80 0b 00 movw $0x233,0xb8004(%rip) # b8189 <_start+0xb8189> | |
183: 33 02 | |
boot_write(b"5.3"); | |
// extra selector | |
asm!("mov es, ax" :::: "intel"); | |
185: 66 8e c0 mov %ax,%es | |
188: 66 c7 05 00 80 0b 00 movw $0x235,0xb8000(%rip) # b8191 <_start+0xb8191> | |
18f: 35 02 | |
191: 66 c7 05 02 80 0b 00 movw $0x22e,0xb8002(%rip) # b819c <_start+0xb819c> | |
198: 2e 02 | |
19a: 66 c7 05 04 80 0b 00 movw $0x234,0xb8004(%rip) # b81a7 <_start+0xb81a7> | |
1a1: 34 02 | |
// asm!("ljmpw $$0x0008, $$arch_init" | |
// :: // "i"(arch_init) | |
// :: "volatile"); | |
asm!( "ljmpl $$8, $$arch_init" | |
1a3: ea (bad) | |
1a4: 00 00 add %al,(%rax) | |
1a6: 00 00 add %al,(%rax) | |
1a8: 08 00 or %al,(%rax) | |
// arch_init(multiboot as u64); | |
// asm!("ljmpl $$0x0008, $$0x106000"); | |
// asm!("ljmpl *(arch_init)"); | |
// asm!("ljmpl [arch_init]" ); | |
} | |
1aa: c3 retq |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment