diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 425d7eb..76a1014 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -11,7 +11,7 @@ use kernel::{ }, print, }; -use x86_drivers::gdt::{DPL, GdtEntry, GdtPointer, GdtSelector}; +use x86_drivers::{gdt::{DPL, GdtEntry, GdtPointer, GdtSelector}, paging::PageMapLevel4}; pub use x86_drivers::prelude::*; #[unsafe(no_mangle)] @@ -123,11 +123,39 @@ extern "efiapi" fn efi_main(handle: Handle, table: *mut EfiSystemTable) -> UefiS let res = alloc.request_pages(&RegionRequest::new(2)); print!("Region request returned ({res:?})\r\n"); - let sp = reserve_kernel_pages(image_info.0, image_info.1, 4096, &mut alloc); + let (sp, plm4) = reserve_kernel_pages(image_info.0, image_info.1, 4096, &mut alloc).unwrap(); print!("Potential new stack pointer: {sp:?}\r\n"); + let new_stack_pointer = unsafe { sp.cast::().add(4096) }; + unsafe { specify_kernel(sp, plm4) }; +} - #[allow(clippy::empty_loop)] - loop {} +unsafe fn specify_kernel(sp: *const u8, plm4_phys: *const PageMapLevel4) -> ! { + unsafe { + core::arch::asm!( + "mov rsp, {sp}", + "mov rbp, {sp}", + "mov cr3, {plm4}", + "jmp {main}", + sp = in(reg) sp, + plm4 = in(reg) plm4_phys, + main = sym kernel_main, + options(nostack,preserves_flags,noreturn)) + } +} + +fn kernel_main() -> ! { + let sp:u32; + let bp:u32; + unsafe { + core::arch::asm!( + "mov {sp}, rsp", + "mov {bp}, rbp", + sp = out(reg) sp, + bp = out(reg) bp, + options(nostack,preserves_flags)) + } + print!("Running from main!, with {sp:#X} {bp:#X} \r\n"); + todo!(); } static GDT_TABLE: [GdtEntry; 3] = [ diff --git a/kernel/src/paging/kernel.rs b/kernel/src/paging/kernel.rs index 7c656de..6a8b05a 100644 --- a/kernel/src/paging/kernel.rs +++ b/kernel/src/paging/kernel.rs @@ -1,7 +1,4 @@ -use core::{ - char::MAX, - sync::atomic::{AtomicBool, AtomicU8}, -}; +use core::sync::atomic::AtomicU8; use x86_drivers::paging::{ BanExecution, Cache, CacheWriteThrough, KernelMode, Page, PageAttributeTable, PageDirectory, @@ -40,72 +37,58 @@ pub fn reserve_kernel_pages( app_size: u64, stack_size: usize, allocator: &mut RegionAllocator, -) -> Result<*const super::Page, super::Error> { +) -> Result<(*const u8, *const PageMapLevel4), super::Error> { // TODO: This is going to bite me, need to track the addresses in some in memory abstraction. + const M2_PAGE_SIZE: u64 = (2 * 1024 * 1024); - let page_ptr = (app_ptr as u64 % PAGE_SIZE as u64) as *const [u8; PAGE_SIZE]; - let pages = app_size as usize / PAGE_SIZE; - for page in 0..pages { - unsafe { - KERNEL_PAGE_TABLE - .register( - page as usize, - Page::new( - page_ptr.add(page) as *const _, - x86_drivers::paging::Mutable::Yes, - // Think this is a good idea, we should keep memory in sync? - CacheWriteThrough::On, - // Generally we do not - Cache::On, - PageAttributeTable::On, - get_max_addr().into(), - BanExecution::No, - ), - ) - .unwrap(); - } + let page_ptr = + (app_ptr as u64 & (!(M2_PAGE_SIZE - 1))) as *const [u8; { M2_PAGE_SIZE as usize }]; + let page_2m_idx = (page_ptr as u64 / M2_PAGE_SIZE); + let app_pages = (app_size / M2_PAGE_SIZE) + 1; + + unsafe { + KERNEL_PHYSMAP_PAGE_DIRECTORY + .register_page( + page_2m_idx as usize, + Page::new( + page_ptr as *const _, + x86_drivers::paging::Mutable::Yes, + // Think this is a good idea, we should keep memory in sync? + CacheWriteThrough::Off, + // Generally we do not + Cache::On, + PageAttributeTable::Off, + get_max_addr().into(), + BanExecution::No, + ), + ) + .unwrap(); } + let stack_pages = stack_size / PAGE_SIZE; // TODO: Make some better upper bound here :( let result = allocator.request_pages(&super::RegionRequest::new_with_address_filter( stack_pages, - unsafe { page_ptr.add(pages) as u64 }, + unsafe { page_ptr.add(app_pages as usize + 1) as u64 }, u64::MAX / 2, ))?; - for page in 0..stack_pages { - let offset_in_table = pages + page; - print!("IDX {offset_in_table}"); - - unsafe { - KERNEL_PAGE_TABLE - .register( - offset_in_table, - Page::new( - result.start.add(page) as *const _, - x86_drivers::paging::Mutable::Yes, - // Not sure if we should have write through on here? a bunch of invalidation - CacheWriteThrough::On, - Cache::On, - PageAttributeTable::On, - get_max_addr().into(), - BanExecution::Yes, - ), - ) - .unwrap(); - } - } + let page_2m_idx = (result.start as u64 / M2_PAGE_SIZE); unsafe { KERNEL_PHYSMAP_PAGE_DIRECTORY - .register_nested( - 0, - PdEntry::new( - core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(), + .register_page( + page_2m_idx as usize, + Page::new( + result.start as *const _, + x86_drivers::paging::Mutable::Yes, + // Not sure if we should have write through on here? a bunch of invalidation CacheWriteThrough::Off, Cache::On, + PageAttributeTable::Off, get_max_addr().into(), + BanExecution::Yes, ), ) .unwrap(); @@ -116,7 +99,7 @@ pub fn reserve_kernel_pages( .register_nested( 0, PdptEntry::new( - core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(), + core::ptr::addr_of!(KERNEL_PHYSMAP_PAGE_DIRECTORY), CacheWriteThrough::Off, Cache::On, get_max_addr().into(), @@ -127,9 +110,9 @@ pub fn reserve_kernel_pages( unsafe { PML4.register( - 511, - Pml4Entry::::new( - core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(), + 0, + Pml4Entry::new( + core::ptr::addr_of!(KERNEL_PHYSMAP_PDPT), CacheWriteThrough::Off, Cache::On, get_max_addr().into(), @@ -137,5 +120,5 @@ pub fn reserve_kernel_pages( ) .unwrap(); } - Ok(result.start) + unsafe { Ok((result.start.cast(), core::ptr::addr_of!(PML4))) } } diff --git a/x86_drivers/src/paging.rs b/x86_drivers/src/paging.rs index 20d5a2d..1653a34 100644 --- a/x86_drivers/src/paging.rs +++ b/x86_drivers/src/paging.rs @@ -320,8 +320,8 @@ impl PageMapLevel4 { return Err(RegisterError::IndexOutOfBounds); }; match (M::MODE, offset) { - (UserOrSupervisor::Supervisor, 256..) => (), - (UserOrSupervisor::User, ..256) => (), + (UserOrSupervisor::User, 256..) => (), + (UserOrSupervisor::Supervisor, ..256) => (), _ => return Err(RegisterError::InvalidIndexForPrivilegeLevel), } *val = page.0;