From 0aae87eda3cb44f8da042b17a5523c92e003918f Mon Sep 17 00:00:00 2001 From: Jack Halford Date: Thu, 3 May 2018 20:27:52 +0200 Subject: [PATCH] i'm just trying to figure out this mess.. fml --- kernel-rs/src/allocator/mod.rs | 13 ++-- kernel-rs/src/arch/x86/consts.rs | 31 +++++++++ kernel-rs/src/arch/x86/gdt.rs | 67 ++++++++----------- kernel-rs/src/arch/x86/interrupt/exception.rs | 6 +- kernel-rs/src/arch/x86/mod.rs | 38 ++++++++++- kernel-rs/src/arch/x86/start.asm | 3 +- kernel-rs/src/console.rs | 16 +++++ kernel-rs/src/lib.rs | 4 +- kernel-rs/src/memory/mod.rs | 2 +- kernel-rs/src/vga/mod.rs | 36 +++++----- kernel-rs/x86 | 2 +- 11 files changed, 144 insertions(+), 74 deletions(-) create mode 100644 kernel-rs/src/arch/x86/consts.rs diff --git a/kernel-rs/src/allocator/mod.rs b/kernel-rs/src/allocator/mod.rs index 9707bd8a..5837c638 100644 --- a/kernel-rs/src/allocator/mod.rs +++ b/kernel-rs/src/allocator/mod.rs @@ -5,21 +5,22 @@ use x86::*; use x86::structures::paging::*; use arch::x86::paging::*; -fn map_heap(active_table: &mut ActivePageTable, offset: usize, size: usize) { - let heap_start_page = Page::containing_address(VirtAddr::new(offset as u32)); - let heap_end_page = Page::containing_address(VirtAddr::new(offset as u32 + size as u32 - 1)); +fn map_heap(active_table: &mut ActivePageTable, offset: u32, size: u32) { + let heap_start_page = Page::containing_address(VirtAddr::new(offset)); + let heap_end_page = Page::containing_address(VirtAddr::new(offset + size - 1)); for page in heap_start_page..heap_end_page + 1 { + //we really should only map 1 huge page instead of 1024 small pages active_table.map(page, PageTableFlags::WRITABLE); } } /// should be called only once pub unsafe fn init(active_table: &mut ActivePageTable) { - let offset = ::HEAP_START; - let size = ::HEAP_SIZE; + let offset = ::KERNEL_HEAP_OFFSET; + let size = ::KERNEL_HEAP_SIZE; map_heap(active_table, offset, size); - Allocator::init(offset, size); + Allocator::init(offset as usize, size as usize); } diff --git a/kernel-rs/src/arch/x86/consts.rs b/kernel-rs/src/arch/x86/consts.rs new file mode 100644 index 00000000..9d41c545 --- /dev/null +++ b/kernel-rs/src/arch/x86/consts.rs @@ -0,0 +1,31 @@ +//layout looks like this: +// [kernel 0->4MiB] +// [kernel 4->8MiB] +// [user stack] +// [start of userheap] +// . +// . +// . +// [end of userheap] +// [kernel heap] +// [recursive map] points to first entry +// +// which makes userheap = 4GiB - 4*4MiB (~= 4GiB) +macro_rules! p2 { ($i:expr) => {($i & P2_MASK) / P1_SIZE}} +pub const P2_MASK: u32 = 0xFFC0_0000; //top 10 bits +pub const P1_SIZE: u32 = 0x0040_0000; //4MiB (2**22) + +pub const RECURSIVE_PAGE_OFFSET: u32 = (-(P1_SIZE as isize)) as u32; +///1023 +pub const RECURSIVE_PAGE_P2: u32 = p2!(RECURSIVE_PAGE_OFFSET); + +pub const KERNEL_HEAP_OFFSET: u32 = RECURSIVE_PAGE_OFFSET - P1_SIZE; +///1022 +pub const KERNEL_HEAP_P2: u32 = p2!(KERNEL_HEAP_OFFSET); +pub const KERNEL_HEAP_SIZE: u32 = 4 * 1024 * 1024; //4MiB (1 huge page) + +pub const USER_OFFSET: u32 = 0x00a0_0000; //3rd page (kernel takes 2 first pages) +pub const USER_P2: u32 = p2!(USER_OFFSET); + +pub const USER_STACK_OFFSET: u32 = USER_OFFSET + P1_SIZE; +pub const USER_STACK_2: u32 = p2!(USER_STACK_OFFSET); diff --git a/kernel-rs/src/arch/x86/gdt.rs b/kernel-rs/src/arch/x86/gdt.rs index 65873b55..3744733f 100644 --- a/kernel-rs/src/arch/x86/gdt.rs +++ b/kernel-rs/src/arch/x86/gdt.rs @@ -1,49 +1,38 @@ use x86::structures::gdt; use x86::structures::tss; -use x86::instructions::segmentation::set_cs; +use x86::instructions::segmentation::*; use x86::instructions::tables::load_tss; -use x86::registers::control; -use arch::x86::paging::ActivePageTable; +use x86::*; use spin::Once; -static GDT: Once = Once::new(); -static TSS_MAIN: Once = Once::new(); -static TSS_INT: Once = Once::new(); +pub static mut GDT: gdt::Gdt = gdt::Gdt::new(); +pub static mut TSS: tss::TaskStateSegment = tss::TaskStateSegment::new(); -pub fn init(mut active_table: &mut ActivePageTable) { - let tss_main = TSS_MAIN.call_once(|| { - let mut tss = tss::TaskStateSegment::new(); - // tss.esp0 = stack.top; - // tss.ss = 0x8; - tss.cr3 = control::Cr3::read_u32(); - tss.reserved_iopb = 1; //T debug bit - tss - }); +pub static GDT_KERNEL_CODE: u16 = 1; +pub static GDT_KERNEL_DATA: u16 = 1; +pub static GDT_USER_CODE: u16 = 2; +pub static GDT_USER_DATA: u16 = 3; - let mut code_selector = gdt::SegmentSelector(0); - let mut tss_main_selector = gdt::SegmentSelector(0); +pub unsafe fn init() { + TSS.ss0 = gdt::SegmentSelector::new(GDT_KERNEL_CODE, PrivilegeLevel::Ring0).0; + asm!("mov %ebp, $0" : "=r" (TSS.esp0)); - let gdt = GDT.call_once(|| { - let mut gdt = gdt::Gdt::new(); - code_selector = gdt.add_entry(gdt::Descriptor::kernel_code_segment()); - tss_main_selector = gdt.add_entry(gdt::Descriptor::tss_segment(&tss_main)); - gdt - }); + // the following order is important + let kcode_selector = GDT.add_entry(gdt::Descriptor::kernel_code_segment()); + let kdata_selector = GDT.add_entry(gdt::Descriptor::kernel_data_segment()); + let tss_selector = GDT.add_entry(gdt::Descriptor::tss_segment(&TSS)); + //I read that the tss should be twice as long + //fuck knows why... + //also this doesnt work if the tss is after 3rd spot + //once again: fuck knows why... + GDT.add_entry(gdt::Descriptor(0)); + let ucode_selector = GDT.add_entry(gdt::Descriptor::user_code_segment()); + let udata_selector = GDT.add_entry(gdt::Descriptor::user_data_segment()); - println!("gdt[0]={:#?}", gdt::Descriptor(gdt.table[0])); - println!("gdt[1]={:#?}", gdt::Descriptor(gdt.table[1])); - println!("gdt[2]={:#?}", gdt::Descriptor(gdt.table[2])); - println!("gdt[3]={:#?}", gdt::Descriptor(gdt.table[3])); - println!("gdt[4]={:#?}", gdt::Descriptor(gdt.table[4])); - flush!(); - - gdt.load(); - unsafe { - // reload code segment register - // println!("set_cs({:#x})", code_selector.0); - set_cs(code_selector); - // load TSS - // println!("loading tss {:?}", tss_main_selector); - load_tss(tss_main_selector); - } + GDT.load(); + set_cs(kcode_selector); + load_ds(kdata_selector); + load_es(kdata_selector); + load_ss(kdata_selector); + load_tss(tss_selector); } diff --git a/kernel-rs/src/arch/x86/interrupt/exception.rs b/kernel-rs/src/arch/x86/interrupt/exception.rs index 2f6a858d..d9b034d2 100644 --- a/kernel-rs/src/arch/x86/interrupt/exception.rs +++ b/kernel-rs/src/arch/x86/interrupt/exception.rs @@ -4,7 +4,7 @@ macro_rules! exception { ($name:ident, $func:block) => { pub extern "x86-interrupt" fn $name(stack_frame: &mut ExceptionStackFrame) { - println!("Exception: {}", stringify!($name)); + println!("#{}", stringify!($name)); println!("{:#?}", stack_frame); flush!(); @@ -20,9 +20,9 @@ macro_rules! exception { macro_rules! exception_err { ($name:ident, $func:block) => { pub extern "x86-interrupt" fn $name( - stack_frame: &mut ExceptionStackFrame, _error_code: u32) + stack_frame: &mut ExceptionStackFrame, error_code: u32) { - println!("Exception: {}", stringify!($name)); + println!("#{}({})", stringify!($name), error_code); println!("{:#?}", stack_frame); flush!(); diff --git a/kernel-rs/src/arch/x86/mod.rs b/kernel-rs/src/arch/x86/mod.rs index fb606873..89080806 100644 --- a/kernel-rs/src/arch/x86/mod.rs +++ b/kernel-rs/src/arch/x86/mod.rs @@ -4,7 +4,7 @@ extern crate x86; pub mod paging; pub mod interrupt; pub mod device; -pub mod pti; +pub mod consts; pub mod gdt; pub mod idt; @@ -40,7 +40,7 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { idt::init(); // fill and load gdt - gdt::init(&mut active_table); + gdt::init(); // set up heap ::allocator::init(&mut active_table); @@ -51,3 +51,37 @@ pub unsafe extern "C" fn x86_rust_start(multiboot_info_addr: usize) { // primary CPU entry point ::kmain(); } + +pub unsafe fn usermode(ip: u32, sp: u32, arg: u32) -> ! { + asm!("push r10 + push r11 + push r12 + push r13 + push r14 + push r15 + " + : //no output + : "{r10}"(gdt::GDT_USER_DATA << 3 | 3), + "{r11}"(sp), + "{r12}"(1 << 9) // interrupt enable flag + "{r13}"(gdt::GDT_USER_CODE << 3 | 3), + "{r14}"(ip), + "{r15}"(arg) + : //no clobbers + : "intel", "volatile" + ); + + asm!("mov ds, r14d + mov es, r14d + mov fs, r15d + mov gs, r14d + fninit + iret" + : //no output (never returns) + : "{r14}"(gdt::GDT_USER_DATA << 3 | 3), + "{r15}"(gdt::GDT_USER_CODE << 3 | 3) + : //no clobbers (never returns) + : "intel", "volatile" + ); + unreachable!(); +} diff --git a/kernel-rs/src/arch/x86/start.asm b/kernel-rs/src/arch/x86/start.asm index ea3fe179..fc0fc608 100644 --- a/kernel-rs/src/arch/x86/start.asm +++ b/kernel-rs/src/arch/x86/start.asm @@ -4,10 +4,11 @@ extern x86_rust_start section .text bits 32 x86_start: - mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds) + mov ax, 0x10 ; 16 bytes (0x10) is where the offset for data section (gdt_ds) mov ds, ax mov ss, ax mov es, ax + mov ax, 0x0 ; fuck fs & gs, fuck them. mov fs, ax mov gs, ax diff --git a/kernel-rs/src/console.rs b/kernel-rs/src/console.rs index ae067a53..e3b45690 100644 --- a/kernel-rs/src/console.rs +++ b/kernel-rs/src/console.rs @@ -186,9 +186,25 @@ pub fn acpi_info() -> Result<(), &'static str> { /// Dump control registers pub fn regs() -> Result<(), &'static str> { use x86::registers::control::*; + use x86::instructions::tables::tr; + use x86::instructions::segmentation::*; + use x86::structures::gdt; println!("cr0 = {:?}", Cr0::read()); println!("cr3 = {:?}", Cr3::read()); println!("cr4 = {:?}", Cr4::read()); + println!("tr = {:?}", tr()); + println!("ss = {:?}", ss()); + println!("cs = {:?}", cs()); + println!("ds = {:?}", ds()); + println!("es = {:?}", es()); + println!("fs = {:?}", fs()); + println!("gs = {:?}", gs()); + unsafe { + println!( + "tss = {:#?}", + gdt::Descriptor(::arch::x86::gdt::GDT.table[tr().index() as usize]) + ); + } flush!(); Ok(()) } diff --git a/kernel-rs/src/lib.rs b/kernel-rs/src/lib.rs index 23b0c5cf..6c65b86f 100644 --- a/kernel-rs/src/lib.rs +++ b/kernel-rs/src/lib.rs @@ -43,6 +43,7 @@ pub mod allocator; pub mod memory; /// arch specific entry points pub mod arch; +pub use arch::x86::consts::*; // use core::mem; // use x86::structures::idt::*; @@ -83,8 +84,5 @@ pub extern "C" fn panic_fmt(fmt: core::fmt::Arguments, file: &'static str, line: loop {} } -pub const HEAP_START: usize = (1 << 22 + 2); //third entry of p2 -pub const HEAP_SIZE: usize = 10 * 4096 * 8; //~ 100 KiB - #[global_allocator] static HEAP_ALLOCATOR: allocator::Allocator = allocator::Allocator; diff --git a/kernel-rs/src/memory/mod.rs b/kernel-rs/src/memory/mod.rs index 017f86e6..3fba610d 100644 --- a/kernel-rs/src/memory/mod.rs +++ b/kernel-rs/src/memory/mod.rs @@ -53,7 +53,7 @@ pub fn init(boot_info: &multiboot2::BootInformation) { let frame_allocator = RecycleAllocator::new(bump_allocator); let heap_end_page = - Page::containing_address(VirtAddr::new(::HEAP_START as u32 + ::HEAP_SIZE as u32 - 1)); + Page::containing_address(VirtAddr::new(::KERNEL_HEAP_OFFSET + ::KERNEL_HEAP_SIZE - 1)); let stack_allocator = { let stack_alloc_start = heap_end_page + 1; diff --git a/kernel-rs/src/vga/mod.rs b/kernel-rs/src/vga/mod.rs index 1a2dedc8..27be530c 100644 --- a/kernel-rs/src/vga/mod.rs +++ b/kernel-rs/src/vga/mod.rs @@ -199,24 +199,24 @@ impl fmt::Write for Writer { } pub fn init() { - set_color!(Yellow, Red); - print!( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - format_args!("{: ^80}", r#" ,--, "#), - format_args!("{: ^80}", r#" ,--.'| ,----, "#), - format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), - format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), - format_args!("{: ^80}", r#"; : | | ; | : . ; "#), - format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), - format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), - format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), - format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), - format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), - format_args!("{: ^80}", r#" ' ; |./__; : "#), - format_args!("{: ^80}", r#" | : ;| : .' "#), - format_args!("{: ^80}", r#" ' ,/ ; | .' "#), - format_args!("{: ^80}", r#" '--' `---' "#) - ); + // set_color!(Yellow, Red); + // print!( + // "{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + // format_args!("{: ^80}", r#" ,--, "#), + // format_args!("{: ^80}", r#" ,--.'| ,----, "#), + // format_args!("{: ^80}", r#" ,--, | : .' .' \ "#), + // format_args!("{: ^80}", r#",---.'| : ' ,----,' | "#), + // format_args!("{: ^80}", r#"; : | | ; | : . ; "#), + // format_args!("{: ^80}", r#"| | : _' | ; |.' / "#), + // format_args!("{: ^80}", r#": : |.' | `----'/ ; "#), + // format_args!("{: ^80}", r#"| ' ' ; : / ; / "#), + // format_args!("{: ^80}", r#"\ \ .'. | ; / /-, "#), + // format_args!("{: ^80}", r#" `---`: | ' / / /.`| "#), + // format_args!("{: ^80}", r#" ' ; |./__; : "#), + // format_args!("{: ^80}", r#" | : ;| : .' "#), + // format_args!("{: ^80}", r#" ' ,/ ; | .' "#), + // format_args!("{: ^80}", r#" '--' `---' "#) + // ); unsafe { VGA.prompt(); } diff --git a/kernel-rs/x86 b/kernel-rs/x86 index 830c0b77..73a83239 160000 --- a/kernel-rs/x86 +++ b/kernel-rs/x86 @@ -1 +1 @@ -Subproject commit 830c0b770873e8f96b0fbdab484579e15cfd8b73 +Subproject commit 73a83239073de4acb5b18bacad049553a086ce3f