diff --git a/.cargo/config.toml b/.cargo/config.toml index 22b6ca6cb..6cea5ca24 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [alias] -repbuild = "run --manifest-path ./repbuild/Cargo.toml --" +repbuild = "run --manifest-path ./repbuild/Cargo.toml --" \ No newline at end of file diff --git a/ableos/.cargo/config.toml b/ableos/.cargo/config.toml index 3120ea561..7c70298eb 100644 --- a/ableos/.cargo/config.toml +++ b/ableos/.cargo/config.toml @@ -3,7 +3,8 @@ target = "./json_targets/x86_64-ableos.json" [unstable] build-std-features = ["compiler-builtins-mem"] -build-std = ["core","alloc", "compiler_builtins"] +build-std = ["core", "compiler_builtins", "alloc"] + [target.'cfg(target_arch = "x86_64")'] diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index d6b12fc91..3c8038a68 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -40,7 +40,7 @@ psp = "0.1.5" [target.'cfg(target_arch = "x86_64")'.dependencies] volatile = "0.2.6" -bootloader = "0.9.8" +bootloader = {version = "0.9.8", features = ["map_physical_memory"]} cpuio = { git = "https://github.com/anyusernameworks/cpuio.git" } x86_64 = "*" uart_16550 = "0.2.0" diff --git a/ableos/src/arch/x86_64/memory.rs b/ableos/src/arch/x86_64/memory.rs new file mode 100644 index 000000000..9c42a182e --- /dev/null +++ b/ableos/src/arch/x86_64/memory.rs @@ -0,0 +1,112 @@ +use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; +use x86_64::{ + structures::paging::{ + FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, + }, + PhysAddr, VirtAddr, +}; + +pub unsafe fn init(physical_memory_offset: VirtAddr) -> OffsetPageTable<'static> { + let level_4_table = active_level_4_table(physical_memory_offset); + OffsetPageTable::new(level_4_table, physical_memory_offset) +} + +unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable { + use x86_64::registers::control::Cr3; + + let (level_4_table_frame, _) = Cr3::read(); + + let phys = level_4_table_frame.start_address(); + let virt = physical_memory_offset + phys.as_u64(); + let page_table_ptr: *mut PageTable = virt.as_mut_ptr(); + + // THIS IS UNSAFE + &mut *page_table_ptr +} + +fn translate_addr_inner(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option { + use x86_64::registers::control::Cr3; + use x86_64::structures::paging::page_table::FrameError; + + let (level_4_table_frame, _) = Cr3::read(); + + let table_indexes = [ + addr.p4_index(), + addr.p3_index(), + addr.p2_index(), + addr.p1_index(), + ]; + let mut frame = level_4_table_frame; + + for &index in &table_indexes { + // convert the frame into a page table reference + let virt = physical_memory_offset + frame.start_address().as_u64(); + let table_ptr: *const PageTable = virt.as_ptr(); + let table = unsafe { &*table_ptr }; + + let entry = &table[index]; + frame = match entry.frame() { + Ok(frame) => frame, + Err(FrameError::FrameNotPresent) => return None, + Err(FrameError::HugeFrame) => panic!["huge pages not supported"], + }; + } + + Some(frame.start_address() + u64::from(addr.page_offset())) +} + +pub unsafe fn translate_addr(addr: VirtAddr, physical_memory_offset: VirtAddr) -> Option { + translate_addr_inner(addr, physical_memory_offset) +} + +pub fn create_example_mapping( + page: Page, + mapper: &mut OffsetPageTable, + frame_allocator: &mut impl FrameAllocator, +) { + use x86_64::structures::paging::PageTableFlags as Flags; + + let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); + let flags = Flags::PRESENT | Flags::WRITABLE; + + let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) }; + map_to_result.expect("map_to failed").flush(); +} + +pub struct EmptyFrameAllocator; + +unsafe impl FrameAllocator for EmptyFrameAllocator { + fn allocate_frame(&mut self) -> Option> { + None + } +} + +pub struct BootInfoFrameAllocator { + memory_map: &'static MemoryMap, + next: usize, +} + +impl BootInfoFrameAllocator { + pub unsafe fn init(memory_map: &'static MemoryMap) -> Self { + Self { + memory_map, + next: 0, + } + } + + fn usable_frames(&self) -> impl Iterator { + let regions = self.memory_map.iter(); + let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); + let addr_range = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); + let frame_address = addr_range.flat_map(|r| r.step_by(4096)); + frame_address.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) + } +} + +unsafe impl FrameAllocator for BootInfoFrameAllocator { + fn allocate_frame(&mut self) -> Option> { + let frame = self.usable_frames().nth(self.next); + self.next += 1; + frame + } +} diff --git a/ableos/src/arch/x86_64/mod.rs b/ableos/src/arch/x86_64/mod.rs index f38307c93..2944251f1 100644 --- a/ableos/src/arch/x86_64/mod.rs +++ b/ableos/src/arch/x86_64/mod.rs @@ -1,13 +1,15 @@ use x86_64::instructions::hlt; +use bootloader::BootInfo; pub mod drivers; pub mod gdt; pub mod init; pub mod interrupts; -#[no_mangle] -pub extern "C" fn _start() -> ! { - crate::kmain::kernel_main(); - sloop(); -} +pub mod memory; +// #[no_mangle] +// pub extern "C" fn _start(boot_info: &'static BootInfo) -> ! { +// crate::kmain::kernel_main(boot_info); +// // sloop(); +// } #[allow(unused)] pub fn shutdown() -> ! { diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs index fb3fb2a04..085e4bbb7 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -1,18 +1,27 @@ #![allow(clippy::empty_loop)] use crate::{ - arch::{drivers::graphics::GraphicsBuffer, init}, + arch::{ + drivers::graphics::GraphicsBuffer, + init, + memory::{self, translate_addr}, + sloop, + }, driver_traits::{graphics::Graphics, serial::Serial}, experiments::systeminfo::{KERNEL_VERSION, RELEASE_TYPE}, keyboard::DecodedKey, relib::math::rand::{linearshift::LinearShiftRegister, prand::PRand, RAND_HANDLE, RNG}, serial_print, serial_println, }; +use bootloader::{entry_point, BootInfo}; use lazy_static::lazy_static; +use x86_64::{structures::paging::Page, VirtAddr}; + #[no_mangle] #[allow(unconditional_recursion)] pub extern "C" fn stack_overflow() -> u8 { stack_overflow(); + // meme number 69 // NOTE: Any specific reason for this number asside from memes? } @@ -20,8 +29,10 @@ lazy_static! { pub static ref KEY_BUFFER: [DecodedKey; 256] = [DecodedKey::RawKey(123); 256]; pub static ref KEY_BUFFER_POINTER: u8 = 0; } +// Defines the entry point +entry_point![kernel_main]; #[no_mangle] -pub extern "C" fn kernel_main() { +pub fn kernel_main(boot_info: &'static BootInfo) -> ! { init::init(); GraphicsBuffer::draw(); @@ -51,9 +62,21 @@ pub extern "C" fn kernel_main() { // x.dump_flags(); } + let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); + + let mut mapper = unsafe { memory::init(phys_mem_offset) }; + let mut frame_allocator = + unsafe { memory::BootInfoFrameAllocator::init(&boot_info.memory_map) }; + + let page = Page::containing_address(VirtAddr::new(0xdeadbeaf000)); + memory::create_example_mapping(page, &mut mapper, &mut frame_allocator); + + let page_ptr: *mut u64 = page.start_address().as_mut_ptr(); + unsafe { page_ptr.offset(400).write_volatile(0xf021_f077_f065_804e) }; + // stack_overflow(); // crate::arch::shutdown(); - loop {} + sloop() } // TODO: reimplement for the random handler pub fn seed_rng() -> PRand {