Skip to content

Instantly share code, notes, and snippets.

@hawkw
Last active January 25, 2017 22:01
Show Gist options
  • Save hawkw/72f8eafa05cb30ebe34e3a93e7ac0a7e to your computer and use it in GitHub Desktop.
Save hawkw/72f8eafa05cb30ebe34e3a93e7ac0a7e to your computer and use it in GitHub Desktop.
boot.rs
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
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