From a6c141dda43a89791fcf97e3fde0e2c4a4b76e66 Mon Sep 17 00:00:00 2001 From: shibedrill Date: Wed, 28 May 2025 23:07:33 -0400 Subject: [PATCH] I DONT KNOW WHAT IM DOING AND IM SCARED --- src/kernel/arch/x86_64/mod.rs | 1 + src/kernel/arch/x86_64/paging.rs | 266 +++++++++++++++++++++++++++++++ src/kernel/constants.rs | 1 + src/kernel/main.rs | 44 +++-- src/kernel/memory.rs | 9 +- 5 files changed, 293 insertions(+), 28 deletions(-) create mode 100644 src/kernel/arch/x86_64/paging.rs diff --git a/src/kernel/arch/x86_64/mod.rs b/src/kernel/arch/x86_64/mod.rs index ed81a84..3b846b7 100644 --- a/src/kernel/arch/x86_64/mod.rs +++ b/src/kernel/arch/x86_64/mod.rs @@ -4,4 +4,5 @@ pub mod asm; pub mod gdt; pub mod interrupts; +pub mod paging; pub mod serial; diff --git a/src/kernel/arch/x86_64/paging.rs b/src/kernel/arch/x86_64/paging.rs new file mode 100644 index 0000000..4f15a67 --- /dev/null +++ b/src/kernel/arch/x86_64/paging.rs @@ -0,0 +1,266 @@ +#![allow(dead_code)] + +use intbits::Bits; + +#[repr(packed)] +pub struct PageMapLevel5 { + entries: [PageMapLevel5Entry; 512], +} + +pub struct PageMapLevel5Entry { + value: u64, +} + +impl PageMapLevel5Entry { + pub fn execute_disable(&self) -> bool { + self.value.bit(63) + } + pub fn present(&self) -> bool { + self.value.bit(0) + } + pub fn set_present(&mut self, present: bool) { + self.value.set_bit(0, present); + } + pub fn writable(&self) -> bool { + self.value.bit(1) + } + pub fn set_writable(&mut self, writable: bool) { + self.value.set_bit(1, writable); + } + pub fn user_accessible(&self) -> bool { + self.value.bit(2) + } + pub fn set_user_accessible(&mut self, accessible: bool) { + self.value.set_bit(2, accessible); + } + pub fn write_through(&self) -> bool { + self.value.bit(3) + } + pub fn set_write_through(&mut self, write_through: bool) { + self.value.set_bit(3, write_through); + } + pub fn cache_disable(&self) -> bool { + self.value.bit(4) + } + pub fn set_cache_disable(&mut self, cache_disable: bool) { + self.value.set_bit(4, cache_disable); + } + pub fn accessed(&self) -> bool { + self.value.bit(5) + } + pub fn set_accessed(&mut self, accessed: bool) { + self.value.set_bit(5, accessed); + } + pub fn physical_address(&self) -> usize { + self.value.bits(12..=51) as usize + } + pub fn set_physical_address(&mut self, address: u64) { + self.value &= 0xFFF0000000000FFF; + self.value |= (address & 0xFFFFFFFFFF) << 12; + } + pub fn available(&self) -> usize { + (self.value.bits(52..=62) << 4 & self.value.bits(8..=11) << 1 & self.value.bits(6..=6)) + as usize + } +} + +#[repr(packed)] +pub struct PageMapLevel4 { + entries: [PageMapLevel4Entry; 512], +} + +pub struct PageMapLevel4Entry { + value: u64, +} + +impl PageMapLevel4Entry { + pub fn execute_disable(&self) -> bool { + self.value.bit(63) + } + pub fn present(&self) -> bool { + self.value.bit(0) + } + pub fn set_present(&mut self, present: bool) { + self.value.set_bit(0, present); + } + pub fn writable(&self) -> bool { + self.value.bit(1) + } + pub fn set_writable(&mut self, writable: bool) { + self.value.set_bit(1, writable); + } + pub fn user_accessible(&self) -> bool { + self.value.bit(2) + } + pub fn set_user_accessible(&mut self, accessible: bool) { + self.value.set_bit(2, accessible); + } + pub fn write_through(&self) -> bool { + self.value.bit(3) + } + pub fn set_write_through(&mut self, write_through: bool) { + self.value.set_bit(3, write_through); + } + pub fn cache_disable(&self) -> bool { + self.value.bit(4) + } + pub fn set_cache_disable(&mut self, cache_disable: bool) { + self.value.set_bit(4, cache_disable); + } + pub fn accessed(&self) -> bool { + self.value.bit(5) + } + pub fn set_accessed(&mut self, accessed: bool) { + self.value.set_bit(5, accessed); + } + pub fn physical_address(&self) -> usize { + self.value.bits(12..=51) as usize + } + pub fn set_physical_address(&mut self, address: u64) { + self.value &= 0xFFF0000000000FFF; + self.value |= (address & 0xFFFFFFFFFF) << 12; + } + pub fn set_pointer_table(&mut self, table: &PageDirectoryPointerTable) { + self.set_physical_address(&raw const table as u64); + } + pub fn available(&self) -> usize { + (self.value.bits(52..=62) << 4 & self.value.bits(8..=11) << 1 & self.value.bits(6..=6)) + as usize + } +} + +#[repr(packed)] +pub struct PageDirectoryPointerTable { + entries: [*mut PageDirectory; 4], +} + +pub struct PageDirectoryPointer { + value: u64 +} + +impl PageDirectoryPointer { + pub fn execute_disable(&self) -> bool { + self.value.bit(63) + } + pub fn present(&self) -> bool { + self.value.bit(0) + } + pub fn set_present(&mut self, present: bool) { + self.value.set_bit(0, present); + } + pub fn writable(&self) -> bool { + self.value.bit(1) + } + pub fn set_writable(&mut self, writable: bool) { + self.value.set_bit(1, writable); + } + pub fn user_accessible(&self) -> bool { + self.value.bit(2) + } + pub fn set_user_accessible(&mut self, accessible: bool) { + self.value.set_bit(2, accessible); + } + pub fn write_through(&self) -> bool { + self.value.bit(3) + } + pub fn set_write_through(&mut self, write_through: bool) { + self.value.set_bit(3, write_through); + } + pub fn cache_disable(&self) -> bool { + self.value.bit(4) + } + pub fn set_cache_disable(&mut self, cache_disable: bool) { + self.value.set_bit(4, cache_disable); + } + pub fn accessed(&self) -> bool { + self.value.bit(5) + } + pub fn set_accessed(&mut self, accessed: bool) { + self.value.set_bit(5, accessed); + } + pub fn physical_address(&self) -> *mut PageDirectory { + self.value.bits(12..=51) as *mut PageDirectory + } + pub fn set_physical_address(&mut self, address: u64) { + self.value &= 0xFFF0000000000FFF; + self.value |= (address & 0xFFFFFFFFFF) << 12; + } + pub fn set_page_directory(&mut self, dir: &PageDirectory) { + self.set_physical_address(&raw const dir as u64); + } + pub fn available(&self) -> usize { + (self.value.bits(52..=62) << 4 & self.value.bits(8..=11) << 1 & self.value.bits(6..=6)) + as usize + } +} + +pub struct PageDirectory { + entries: [PageDirectoryEntry; 512], +} + +pub struct PageDirectoryEntry { + value: u64, +} + +impl PageDirectoryEntry { + pub fn execute_disable(&self) -> bool { + self.value.bit(63) + } + pub fn present(&self) -> bool { + self.value.bit(0) + } + pub fn set_present(&mut self, present: bool) { + self.value.set_bit(0, present); + } + pub fn writable(&self) -> bool { + self.value.bit(1) + } + pub fn set_writable(&mut self, writable: bool) { + self.value.set_bit(1, writable); + } + pub fn user_accessible(&self) -> bool { + self.value.bit(2) + } + pub fn set_user_accessible(&mut self, accessible: bool) { + self.value.set_bit(2, accessible); + } + pub fn write_through(&self) -> bool { + self.value.bit(3) + } + pub fn set_write_through(&mut self, write_through: bool) { + self.value.set_bit(3, write_through); + } + pub fn cache_disable(&self) -> bool { + self.value.bit(4) + } + pub fn set_cache_disable(&mut self, cache_disable: bool) { + self.value.set_bit(4, cache_disable); + } + pub fn accessed(&self) -> bool { + self.value.bit(5) + } + pub fn set_accessed(&mut self, accessed: bool) { + self.value.set_bit(5, accessed); + } + pub fn physical_address(&self) -> usize { + self.value.bits(12..=51) as usize + } + pub fn set_physical_address(&mut self, address: u64) { + self.value &= 0xFFF0000000000FFF; + self.value |= (address & 0xFFFFFFFFFF) << 12; + } + pub fn available(&self) -> usize { + (self.value.bits(52..=62) << 4 & self.value.bits(8..=11) << 1 & self.value.bits(6..=6)) + as usize + } +} + +#[repr(align(4096))] +pub struct PageTable { + entries: [PageTableEntry; 512], +} + +#[repr(packed)] +pub struct PageTableEntry { + value: u64, +} diff --git a/src/kernel/constants.rs b/src/kernel/constants.rs index aa3dffb..edd0eea 100644 --- a/src/kernel/constants.rs +++ b/src/kernel/constants.rs @@ -5,6 +5,7 @@ use crate::format; use crate::log::LogLevel; use crate::memory::alloc::string::String; +#[allow(dead_code)] pub static INITRAMFS_DEFAULT_PATH: &str = "/boot/initramfs.tar.lzma"; pub static LOG_DEFAULT_LEVEL: LogLevel = LogLevel::Info; diff --git a/src/kernel/main.rs b/src/kernel/main.rs index 910c709..23e3c7c 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -22,6 +22,7 @@ mod util; use core::arch::asm; use arch::x86_64::gdt::gdt; +use arch::x86_64::paging::{self, PageDirectory, PageMapLevel4Entry, PageMapLevel5, PageMapLevel5Entry}; #[cfg(target_arch = "x86_64")] use arch::x86_64::serial::Serialport; @@ -29,12 +30,11 @@ use arch::asm::*; use boot::{modules::*, params, *}; use constants::*; use log::*; -use memory::{MEMMAP_REQUEST, HHDM_RESPONSE}; use memory::alloc::{format, string::*, vec}; +use memory::{HHDM_RESPONSE, MEMMAP_REQUEST}; use params::*; use intbits::{self, Bits}; -use limine::file::File; use limine::memory_map::EntryType; #[allow(unused_imports)] use lzma_rs::lzma_decompress; @@ -113,27 +113,6 @@ unsafe extern "C" fn main() -> ! { log_trace!("{log_msg}") } - let irfs_path = { - if let Some(key) = PARAMS.get("-initramfs") { - key - } else { - INITRAMFS_DEFAULT_PATH - } - }; - - log_trace!("Boot: initramfs path requested: {irfs_path}"); - let _initramfs = { - let mut result: Option<&File> = None; - for file in MODULE_RESPONSE.modules() { - if file.path().to_string_lossy() == irfs_path { - result = Some(file); - log_info!("Boot: initramfs found"); - } - } - result - } - .expect("initramfs not found in modules list"); - // Panic if this is absent. It's needed to set up the GDT and paging let mmap_response = MEMMAP_REQUEST .get_response() @@ -223,9 +202,22 @@ unsafe extern "C" fn main() -> ! { cr3.bits(12..=31) }; log_trace!("Boot: Physical address of page directory: 0x{:x}", pd_addr); - log_trace!("Boot: Virtual address of page directory: 0x{:x}", pd_addr + HHDM_RESPONSE.offset()); - log_trace!("Boot: GDT: 0x{:x} bytes @ 0x{:x}", unsafe { gdt().0 }, unsafe { gdt().1} ); - log_trace!("Boot: GDT: 0x{:x}", unsafe { *((gdt().1 + 0x0) as *const u64) }) + log_trace!( + "Boot: Virtual address of page directory: 0x{:x}", + pd_addr + HHDM_RESPONSE.offset() + ); + log_trace!( + "Boot: GDT: 0x{:x} bytes @ 0x{:x}", + unsafe { gdt().0 }, + unsafe { gdt().1 } + ); + log_trace!("Boot: GDT: 0x{:x}", unsafe { + *((gdt().1 + 0x0) as *const u64) + }); + log_trace!( + "Size of page directory: {}", + size_of::() + ); } panic!("Bailing"); diff --git a/src/kernel/memory.rs b/src/kernel/memory.rs index c32df88..30e77c0 100644 --- a/src/kernel/memory.rs +++ b/src/kernel/memory.rs @@ -5,7 +5,10 @@ use enumflags2::*; use lazy_static::lazy_static; -use limine::{request::{ExecutableAddressRequest, HhdmRequest, MemoryMapRequest}, response::HhdmResponse}; +use limine::{ + request::{ExecutableAddressRequest, HhdmRequest, MemoryMapRequest}, + response::HhdmResponse, +}; use core::alloc::{Allocator, Layout}; use talc::*; @@ -26,7 +29,9 @@ pub static MEMMAP_REQUEST: MemoryMapRequest = limine::request::MemoryMapRequest: pub static HHDM_REQUEST: HhdmRequest = limine::request::HhdmRequest::new(); lazy_static! { - pub static ref HHDM_RESPONSE: &'static HhdmResponse = HHDM_REQUEST.get_response().expect("Did not get HHDM response from bootloader"); + pub static ref HHDM_RESPONSE: &'static HhdmResponse = HHDM_REQUEST + .get_response() + .expect("Did not get HHDM response from bootloader"); } static mut ARENA: [u8; 10000] = [0; 10000];