-
Notifications
You must be signed in to change notification settings - Fork 0
Long mode #8
base: master
Are you sure you want to change the base?
Long mode #8
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,11 @@ | ||
[package] | ||
authors = ["Jorge Aparicio <[email protected]>"] | ||
build = "build.rs" | ||
name = "kernel" | ||
version = "0.1.0" | ||
|
||
[profile.dev] | ||
panic = "abort" | ||
|
||
[profile.release] | ||
panic = "abort" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
fn main() { | ||
println!("cargo:rerun-if-changed=layout.ld"); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,23 +6,77 @@ | |
use core::ptr; | ||
|
||
#[no_mangle] | ||
pub fn start() { | ||
unsafe { | ||
ptr::write_volatile(0xb8000 as *mut u16, 0x0248); // H | ||
ptr::write_volatile(0xb8002 as *mut u16, 0x0265); // e | ||
ptr::write_volatile(0xb8004 as *mut u16, 0x026c); // l | ||
ptr::write_volatile(0xb8006 as *mut u16, 0x026c); // l | ||
ptr::write_volatile(0xb8008 as *mut u16, 0x026f); // o | ||
ptr::write_volatile(0xb800a as *mut u16, 0x022c); // , | ||
ptr::write_volatile(0xb800c as *mut u16, 0x0220); // | ||
ptr::write_volatile(0xb800e as *mut u16, 0x0277); // w | ||
ptr::write_volatile(0xb8010 as *mut u16, 0x026f); // o | ||
ptr::write_volatile(0xb8012 as *mut u16, 0x0272); // r | ||
ptr::write_volatile(0xb8014 as *mut u16, 0x026c); // l | ||
ptr::write_volatile(0xb8016 as *mut u16, 0x0264); // d | ||
ptr::write_volatile(0xb8018 as *mut u16, 0x0221); // ! | ||
pub unsafe fn start() { | ||
const NENTRIES: usize = 512; | ||
const HUGE_PAGE_SIZE: u64 = 2 * 1024 * 1024; // 2 MiB | ||
|
||
extern "C" { | ||
static mut p2_table: [u64; NENTRIES]; | ||
static mut p3_table: [u64; NENTRIES]; | ||
static mut p4_table: [u64; NENTRIES]; | ||
} | ||
|
||
// Link up page tables | ||
p4_table[0] = &p3_table[0] as *const _ as usize as u64 | 0b11; | ||
p3_table[0] = &p2_table[0] as *const _ as usize as u64 | 0b11; | ||
|
||
for (entry, i) in p2_table.iter_mut().zip(0..) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*entry = i * HUGE_PAGE_SIZE | 0b10000011; | ||
} | ||
|
||
// move page table address to cr3 | ||
asm!("mov eax, p4_table | ||
mov cr3, eax" :::: "intel"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://crates.io/crates/x86 would be neat to use here, but it also only supports 64-bit for now, IIRC. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They added support for 32 bit lately, but I'm not sure if it's already on crates.io… There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 0.8 on crates.io has the bulk of this. |
||
|
||
// enable PAE | ||
asm!("mov eax, cr4 | ||
or eax, 1 << 5 | ||
mov cr4, eax" :::: "intel"); | ||
|
||
// set long mode bit | ||
asm!("mov ecx, 0xC0000080 | ||
rdmsr | ||
or eax, 1 << 8 | ||
wrmsr" :::: "intel"); | ||
|
||
// enable paging | ||
asm!("mov eax, cr0 | ||
or eax, 1 << 31 | ||
or eax, 1 << 16 | ||
mov cr0, eax" :::: "intel"); | ||
|
||
// load the GDT (Global Descriptor Table) | ||
asm!("lgdt [gdt64.pointer]"); | ||
|
||
// update selectors | ||
asm!("mov ax, gdt64.data.offset" :::: "intel"); | ||
|
||
// stack selector | ||
asm!("mov ss, ax" :::: "intel"); | ||
// data selector | ||
asm!("mov ds, ax" :::: "intel"); | ||
// extra selector | ||
asm!("mov es, ax" :::: "intel"); | ||
|
||
// FIXME Is this the right syntax for a far jump? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thought on this part? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think so? Not 100% sure though. |
||
asm!("jmp [long_mode_start]"); | ||
|
||
// Because this is a syntax error | ||
// asm!("jmp gdt64.code:long_mode_start" :::: "intel"); | ||
// ^ | ||
// error: <inline asm>:2:16: error: unexpected token in argument list | ||
} | ||
|
||
#[export_name = "long_mode_start"] | ||
pub unsafe fn main() { | ||
// FIXME we are in 64-bit mode now BUT this whole crate is compiled for a 32-bit target so the | ||
// _compiler_ won't let use 64-bit instructions. | ||
// asm!("mov rax, 0x2f592f412f4b2f4f" :::: "intel"); | ||
// asm!("mov qword [0xb8000], rax" :::: "intel"); | ||
|
||
// Note that writing that ^ as ptr::write_volatile will emit 32-bit instructions. | ||
ptr::write_volatile(0xb8000 as *mut u64, 0x2f592f412f4b2f4f); | ||
|
||
asm::hlt(); | ||
} | ||
|
||
|
@@ -34,8 +88,5 @@ mod asm { | |
} | ||
} | ||
|
||
#[lang = "eh_personality"] | ||
fn eh_personality() {} | ||
|
||
#[lang = "panic_fmt"] | ||
fn panic_fmt() {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"arch": "x86", | ||
"data-layout": "e-m:e-p:32:32-f64:32:64-f80:32-n8:16:32-S128", | ||
"executables": true, | ||
"llvm-target": "i386", | ||
"no-compiler-rt": true, | ||
"os": "none", | ||
"pre-link-args": ["-m32", "-Tlayout.ld", "-Wl,-n", "-nostartfiles"], | ||
"target-endian": "little", | ||
"target-pointer-width": "32" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
{ | ||
"arch": "x86_64", | ||
"cpu": "x86-64", | ||
"cpu": "i386", | ||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", | ||
"executables": true, | ||
"llvm-target": "x86_64", | ||
"no-compiler-rt": true, | ||
"os": "none", | ||
"pre-link-args": ["-Tlayout.ld", "-Wl,-n", "-nostartfiles"], | ||
"pre-link-args": ["-m32", "-Tlayout.ld", "-Wl,-n", "-nostartfiles"], | ||
"target-endian": "little", | ||
"target-pointer-width": "64" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this can be solved by splitting this crate in two: one crates that does the booting process and is compiled for a 32-bit target and the other crate that exposes the
long_mode_start
symbol and is compiled for a 64-bit target. The issue is that I think the compiler won't link together crates compiled for different types (imagine mixing a crate compiled for ARM with a crate compiled for x86). If that's the case we could compiled theboot
crate as a staticlib and link that staticlib into thelong
crate. That should bypass the "same target" check.All this is speculation from my part. I don't know if it will actually work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds about right to me.