From d6354aeb5644bc2ecefa295a8690bc10b4a21144 Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 13 Jun 2017 20:42:04 -0600 Subject: [PATCH] Refactor kernel mapping so that symbol table is mapped --- linkers/x86_64.ld | 11 ++---- src/interrupt/mod.rs | 37 ++---------------- src/interrupt/trace.rs | 33 ++++++++++++++++ src/lib.rs | 1 + src/paging/mod.rs | 87 ++++++++++++++++++++++++++---------------- src/start.rs | 35 ++++------------- 6 files changed, 104 insertions(+), 100 deletions(-) create mode 100644 src/interrupt/trace.rs diff --git a/linkers/x86_64.ld b/linkers/x86_64.ld index 546adaa..55640ec 100644 --- a/linkers/x86_64.ld +++ b/linkers/x86_64.ld @@ -29,6 +29,10 @@ SECTIONS { *(.data*) . = ALIGN(4096); __data_end = .; + __bss_start = .; + *(.bss*) + . = ALIGN(4096); + __bss_end = .; } .tdata : AT(ADDR(.tdata) - KERNEL_OFFSET) { @@ -43,13 +47,6 @@ SECTIONS { __tbss_end = .; } - .bss : AT(ADDR(.bss) - KERNEL_OFFSET) { - __bss_start = .; - *(.bss*) - . = ALIGN(4096); - __bss_end = .; - } - __end = .; /DISCARD/ : { diff --git a/src/interrupt/mod.rs b/src/interrupt/mod.rs index 3cc5caa..85686d9 100644 --- a/src/interrupt/mod.rs +++ b/src/interrupt/mod.rs @@ -1,13 +1,12 @@ //! Interrupt instructions -use core::mem; - -use paging::{ActivePageTable, VirtualAddress}; - pub mod exception; pub mod ipi; pub mod irq; pub mod syscall; +pub mod trace; + +pub use self::trace::stack_trace; /// Clear interrupts #[inline(always)] @@ -53,33 +52,3 @@ pub unsafe fn halt() { pub fn pause() { unsafe { asm!("pause" : : : : "intel", "volatile"); } } - -/// Get a stack trace -//TODO: Check for stack being mapped before dereferencing -#[inline(never)] -pub unsafe fn stack_trace() { - let mut rbp: usize; - asm!("" : "={rbp}"(rbp) : : : "intel", "volatile"); - - println!("TRACE: {:>016X}", rbp); - //Maximum 64 frames - let active_table = ActivePageTable::new(); - for _frame in 0..64 { - if let Some(rip_rbp) = rbp.checked_add(mem::size_of::()) { - if active_table.translate(VirtualAddress::new(rbp)).is_some() && active_table.translate(VirtualAddress::new(rip_rbp)).is_some() { - let rip = *(rip_rbp as *const usize); - if rip == 0 { - println!(" {:>016X}: EMPTY RETURN", rbp); - break; - } - println!(" {:>016X}: {:>016X}", rbp, rip); - rbp = *(rbp as *const usize); - } else { - println!(" {:>016X}: GUARD PAGE", rbp); - break; - } - } else { - println!(" {:>016X}: RBP OVERFLOW", rbp); - } - } -} diff --git a/src/interrupt/trace.rs b/src/interrupt/trace.rs new file mode 100644 index 0000000..0778ac0 --- /dev/null +++ b/src/interrupt/trace.rs @@ -0,0 +1,33 @@ +use core::mem; + +use paging::{ActivePageTable, VirtualAddress}; + +/// Get a stack trace +//TODO: Check for stack being mapped before dereferencing +#[inline(never)] +pub unsafe fn stack_trace() { + let mut rbp: usize; + asm!("" : "={rbp}"(rbp) : : : "intel", "volatile"); + + println!("TRACE: {:>016X}", rbp); + //Maximum 64 frames + let active_table = ActivePageTable::new(); + for _frame in 0..64 { + if let Some(rip_rbp) = rbp.checked_add(mem::size_of::()) { + if active_table.translate(VirtualAddress::new(rbp)).is_some() && active_table.translate(VirtualAddress::new(rip_rbp)).is_some() { + let rip = *(rip_rbp as *const usize); + if rip == 0 { + println!(" {:>016X}: EMPTY RETURN", rbp); + break; + } + println!(" {:>016X}: {:>016X}", rbp, rip); + rbp = *(rbp as *const usize); + } else { + println!(" {:>016X}: GUARD PAGE", rbp); + break; + } + } else { + println!(" {:>016X}: RBP OVERFLOW", rbp); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index f200492..4e1c17b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ #![feature(alloc)] #![feature(asm)] #![feature(collections)] +#![feature(concat_idents)] #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(drop_types_in_const)] diff --git a/src/paging/mod.rs b/src/paging/mod.rs index 2462fb9..319bcb1 100644 --- a/src/paging/mod.rs +++ b/src/paging/mod.rs @@ -78,7 +78,7 @@ unsafe fn init_tcb(cpu_id: usize) -> usize { /// Initialize paging /// /// Returns page table and thread control block offset -pub unsafe fn init(cpu_id: usize, stack_start: usize, stack_end: usize) -> (ActivePageTable, usize) { +pub unsafe fn init(cpu_id: usize, kernel_start: usize, kernel_end: usize, stack_start: usize, stack_end: usize) -> (ActivePageTable, usize) { extern { /// The starting byte of the text (code) data segment. static mut __text_start: u8; @@ -118,6 +118,60 @@ pub unsafe fn init(cpu_id: usize, stack_start: usize, stack_end: usize) -> (Acti }; active_table.with(&mut new_table, &mut temporary_page, |mapper| { + // Remap stack writable, no execute + { + let start_frame = Frame::containing_address(PhysicalAddress::new(stack_start - ::KERNEL_OFFSET)); + let end_frame = Frame::containing_address(PhysicalAddress::new(stack_end - ::KERNEL_OFFSET - 1)); + for frame in Frame::range_inclusive(start_frame, end_frame) { + let page = Page::containing_address(VirtualAddress::new(frame.start_address().get() + ::KERNEL_OFFSET)); + let result = mapper.map_to(page, frame, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); + // The flush can be ignored as this is not the active table. See later active_table.switch + unsafe { result.ignore(); } + } + } + + // Map all frames in kernel + { + let start_frame = Frame::containing_address(PhysicalAddress::new(kernel_start)); + let end_frame = Frame::containing_address(PhysicalAddress::new(kernel_end - 1)); + for frame in Frame::range_inclusive(start_frame, end_frame) { + let phys_addr = frame.start_address().get(); + let virt_addr = phys_addr + ::KERNEL_OFFSET; + + macro_rules! in_section { + ($n: ident) => ( + virt_addr >= & concat_idents!(__, $n, _start) as *const u8 as usize && + virt_addr < & concat_idents!(__, $n, _end) as *const u8 as usize + ); + } + + let flags = if in_section!(text) { + // Remap text read-only + PRESENT | GLOBAL + } else if in_section!(rodata) { + // Remap rodata read-only, no execute + PRESENT | GLOBAL | NO_EXECUTE + } else if in_section!(data) { + // Remap data writable, no execute + PRESENT | GLOBAL | NO_EXECUTE | WRITABLE + } else if in_section!(tdata) { + // Remap tdata master read-only, no execute + PRESENT | GLOBAL | NO_EXECUTE + } else if in_section!(bss) { + // Remap bss writable, no execute + PRESENT | GLOBAL | NO_EXECUTE | WRITABLE + } else { + // Remap anything else read-only, no execute + PRESENT | GLOBAL | NO_EXECUTE + }; + + let page = Page::containing_address(VirtualAddress::new(virt_addr)); + let result = mapper.map_to(page, frame, flags); + // The flush can be ignored as this is not the active table. See later active_table.switch + unsafe { result.ignore(); } + } + } + // Map tdata and tbss { let size = & __tbss_end as *const _ as usize - & __tdata_start as *const _ as usize; @@ -133,37 +187,6 @@ pub unsafe fn init(cpu_id: usize, stack_start: usize, stack_end: usize) -> (Acti unsafe { result.ignore(); } } } - - let mut remap = |start: usize, end: usize, flags: EntryFlags| { - if end > start { - let start_frame = Frame::containing_address(PhysicalAddress::new(start)); - let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1)); - for frame in Frame::range_inclusive(start_frame, end_frame) { - let page = Page::containing_address(VirtualAddress::new(frame.start_address().get() + ::KERNEL_OFFSET)); - let result = mapper.map_to(page, frame, flags); - // The flush can be ignored as this is not the active table. See later active_table.switch - unsafe { result.ignore(); } - } - } - }; - - // Remap stack writable, no execute - remap(stack_start - ::KERNEL_OFFSET, stack_end - ::KERNEL_OFFSET, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - - // Remap a section with `flags` - let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| { - remap(start as *const _ as usize - ::KERNEL_OFFSET, end as *const _ as usize - ::KERNEL_OFFSET, flags); - }; - // Remap text read-only - remap_section(& __text_start, & __text_end, PRESENT | GLOBAL); - // Remap rodata read-only, no execute - remap_section(& __rodata_start, & __rodata_end, PRESENT | GLOBAL | NO_EXECUTE); - // Remap data writable, no execute - remap_section(& __data_start, & __data_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); - // Remap tdata master writable, no execute - remap_section(& __tdata_start, & __tdata_end, PRESENT | GLOBAL | NO_EXECUTE); - // Remap bss writable, no execute - remap_section(& __bss_start, & __bss_end, PRESENT | GLOBAL | NO_EXECUTE | WRITABLE); }); // This switches the active table, which is setup by the bootloader, to a correct table diff --git a/src/start.rs b/src/start.rs index 2bf9f59..f95a1c3 100644 --- a/src/start.rs +++ b/src/start.rs @@ -3,7 +3,6 @@ /// It must create the IDT with the correct entries, those entries are /// defined in other files inside of the `arch` module -use core::ptr; use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use acpi; @@ -40,43 +39,25 @@ extern { /// The entry to Rust, all things must be initialized #[no_mangle] -pub unsafe extern fn kstart() -> ! { +pub unsafe extern fn kstart(kernel_base: usize, kernel_size: usize, stack_base: usize, stack_size: usize) -> ! { { - extern { - /// The starting byte of the _.bss_ (uninitialized data) segment. - static mut __bss_start: u8; - /// The ending byte of the _.bss_ (uninitialized data) segment. - static mut __bss_end: u8; - /// The end of the kernel - static mut __end: u8; - } - - // Zero BSS, this initializes statics that are set to 0 + // BSS should already be zero { - let start_ptr = &mut __bss_start as *mut u8; - let end_ptr = & __bss_end as *const u8 as usize; - - if start_ptr as usize <= end_ptr { - let size = end_ptr - start_ptr as usize; - ptr::write_bytes(start_ptr, 0, size); - } - assert_eq!(BSS_TEST_ZERO, 0); assert_eq!(DATA_TEST_NONZERO, 0xFFFFFFFFFFFFFFFF); } - // Initialize memory management - memory::init(0, &__end as *const u8 as usize - ::KERNEL_OFFSET); + println!("Kernel: {:X}:{:X}", kernel_base, kernel_base + kernel_size); + println!("Stack: {:X}:{:X}", stack_base, stack_base + stack_size); - // TODO: allocate a stack - let stack_start = 0x00080000 + ::KERNEL_OFFSET; - let stack_end = 0x0009F000 + ::KERNEL_OFFSET; + // Initialize memory management + memory::init(0, kernel_base + ((kernel_size + 4095)/4096) * 4096); // Initialize paging - let (mut active_table, tcb_offset) = paging::init(0, stack_start, stack_end); + let (mut active_table, tcb_offset) = paging::init(0, kernel_base, kernel_base + kernel_size, stack_base, stack_base + stack_size); // Set up GDT - gdt::init(tcb_offset, stack_end); + gdt::init(tcb_offset, stack_base + stack_size); // Set up IDT idt::init();