From f749c89cfc51236c5869b1d4b33f4c5dd77ebc69 Mon Sep 17 00:00:00 2001 From: elfein Date: Mon, 22 Nov 2021 01:51:11 -0800 Subject: [PATCH 1/2] Bruh- modifying the screen buffer without a lock omg --- ableos/Cargo.toml | 2 +- ableos/src/arch/x86_64/memory.rs | 81 ++++++++++++++++++++++ ableos/src/arch/x86_64/mod.rs | 12 ++-- ableos/src/kmain.rs | 111 ++++++++++++++++++------------- 4 files changed, 155 insertions(+), 51 deletions(-) create mode 100644 ableos/src/arch/x86_64/memory.rs diff --git a/ableos/Cargo.toml b/ableos/Cargo.toml index 077645a58..84691a077 100644 --- a/ableos/Cargo.toml +++ b/ableos/Cargo.toml @@ -33,7 +33,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..28f04957f --- /dev/null +++ b/ableos/src/arch/x86_64/memory.rs @@ -0,0 +1,81 @@ +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 + } +} 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 f917606c4..0dd8eebb3 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -1,75 +1,96 @@ #![allow(clippy::empty_loop)] use crate::{ - arch::{drivers::graphics::GraphicsBuffer, init}, - driver_traits::{graphics::Graphics, serial::Serial}, - relib::math::rand::{linearshift::LinearShiftRegister, prand::PRand, RAND_HANDLE, RNG}, - serial_print, serial_println, + arch::{ + drivers::graphics::GraphicsBuffer, + init, + memory::{self, translate_addr}, + sloop, + }, + driver_traits::{graphics::Graphics, serial::Serial}, + 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::{VirtAddr, structures::paging::Page}; #[no_mangle] #[allow(unconditional_recursion)] pub extern "C" fn stack_overflow() -> u8 { - stack_overflow(); - 69 // NOTE: Any specific reason for this number asside from memes? + stack_overflow(); + // meme number + 69 // NOTE: Any specific reason for this number asside from memes? } use crate::keyboard::DecodedKey; lazy_static! { - pub static ref KEY_BUFFER: [DecodedKey; 256] = [DecodedKey::RawKey(123); 256]; - pub static ref KEY_BUFFER_POINTER: u8 = 0; + 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() { - init::init(); +pub fn kernel_main(boot_info: &'static BootInfo) -> ! { + init::init(); - GraphicsBuffer::draw(); - GraphicsBuffer::hide_cursor(); - GraphicsBuffer::show_cursor(); - seed_rng(); + GraphicsBuffer::draw(); + GraphicsBuffer::hide_cursor(); + GraphicsBuffer::show_cursor(); + seed_rng(); - /* If AES is present then AES init rng as well - // Maybe via a cfg - AES::init_rng(); + /* If AES is present then AES init rng as well + // Maybe via a cfg + AES::init_rng(); - */ - #[cfg(not(target_arch = "riscv64"))] - println!("init"); + */ + #[cfg(not(target_arch = "riscv64"))] + println!("init"); - { - use crate::experiments::mail::MailBoxes; - let mut x = MailBoxes::new(); - x.set_flag(1); - x.set_flag(2); - // x.dump_flags(); - } + { + use crate::experiments::mail::MailBoxes; + let mut x = MailBoxes::new(); + x.set_flag(1); + x.set_flag(2); + // x.dump_flags(); + } - // stack_overflow(); - // crate::arch::shutdown(); - loop {} + let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); + + let mut mapper = unsafe { memory::init(phys_mem_offset) }; + let mut frame_allocator = memory::EmptyFrameAllocator; + + let page = Page::containing_address(VirtAddr::new(0)); + 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_f04e) }; + + // stack_overflow(); + // crate::arch::shutdown(); + sloop() } // TODO: reimplement for the random handler pub fn seed_rng() -> PRand { - println!("Seeding PRNG"); - let data = TICK.lock(); - let mut rand = PRand::new(); - let seed = rand.rand(); - println!("{:?}", seed); - rand.seed(*data); - println!("Seeded PRNG"); - rand + println!("Seeding PRNG"); + let data = TICK.lock(); + let mut rand = PRand::new(); + let seed = rand.rand(); + println!("{:?}", seed); + rand.seed(*data); + println!("Seeded PRNG"); + rand } lazy_static! { - // TODO: should have a sin wave influence contribution to entropy - pub static ref TICK: spin::Mutex = spin::Mutex::new(0); + // TODO: should have a sin wave influence contribution to entropy + pub static ref TICK: spin::Mutex = spin::Mutex::new(0); } /// called by arch specific timers to tick up all kernel related functions pub fn tick() { - let mut data = TICK.lock(); - *data += 1; - // serial_println!("{}", *data); - RAND_HANDLE.lock().seed_entropy_timer(*data); + let mut data = TICK.lock(); + *data += 1; + // serial_println!("{}", *data); + RAND_HANDLE.lock().seed_entropy_timer(*data); } pub fn key_entropy(key: u8) { - RAND_HANDLE.lock().seed_entropy_keyboard(key); + RAND_HANDLE.lock().seed_entropy_keyboard(key); } From 218f700b222e8170a85152b4f4b857a87c5dc2b3 Mon Sep 17 00:00:00 2001 From: elfein Date: Mon, 22 Nov 2021 06:58:35 -0800 Subject: [PATCH 2/2] Paging works :3 --- .cargo/config.toml | 2 +- ableos/.cargo/config.toml | 2 +- ableos/src/arch/x86_64/memory.rs | 31 +++++++++++++++++++++++++++++++ ableos/src/kmain.rs | 8 +++++--- ableos/src/lib.rs | 1 + 5 files changed, 39 insertions(+), 5 deletions(-) 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 75f0784c7..58aed6dc1 100644 --- a/ableos/.cargo/config.toml +++ b/ableos/.cargo/config.toml @@ -3,7 +3,7 @@ target = "./json_targets/x86_64-ableos.json" [unstable] build-std-features = ["compiler-builtins-mem"] -build-std = ["core", "compiler_builtins"] +build-std = ["core", "compiler_builtins", "alloc"] [target.'cfg(target_arch = "x86_64")'] diff --git a/ableos/src/arch/x86_64/memory.rs b/ableos/src/arch/x86_64/memory.rs index 28f04957f..9c42a182e 100644 --- a/ableos/src/arch/x86_64/memory.rs +++ b/ableos/src/arch/x86_64/memory.rs @@ -1,3 +1,4 @@ +use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; use x86_64::{ structures::paging::{ FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, @@ -79,3 +80,33 @@ unsafe impl FrameAllocator for EmptyFrameAllocator { 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/kmain.rs b/ableos/src/kmain.rs index 0dd8eebb3..ebe1db6cd 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -57,13 +57,15 @@ pub fn kernel_main(boot_info: &'static BootInfo) -> ! { let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset); let mut mapper = unsafe { memory::init(phys_mem_offset) }; - let mut frame_allocator = memory::EmptyFrameAllocator; + let mut frame_allocator = unsafe { + memory::BootInfoFrameAllocator::init(&boot_info.memory_map) + }; - let page = Page::containing_address(VirtAddr::new(0)); + 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_f04e) }; + unsafe { page_ptr.offset(400).write_volatile(0xf021_f077_f065_804e) }; // stack_overflow(); // crate::arch::shutdown(); diff --git a/ableos/src/lib.rs b/ableos/src/lib.rs index 6ca5156de..2b08f55f4 100644 --- a/ableos/src/lib.rs +++ b/ableos/src/lib.rs @@ -45,3 +45,4 @@ pub const RELEASE_TYPE: &str = "debug"; #[cfg(not(debug_assertions))] /// A constant to check if the kernel is in release mode pub const RELEASE_TYPE: &str = "release"; +extern crate alloc;