From 4b6b440d42e640224047bfb727e2e77952cceadc Mon Sep 17 00:00:00 2001 From: corigan01 Date: Tue, 21 Jan 2025 09:15:26 -0600 Subject: [PATCH] Mem: Continue work on vm manager for processes --- crates/elf/src/lib.rs | 9 + crates/mem/src/page.rs | 15 ++ crates/mem/src/paging.rs | 37 +++- crates/mem/src/vm.rs | 107 ++++++----- kernel/src/int.rs | 5 +- kernel/src/main.rs | 64 ++----- kernel/src/scheduler.rs | 341 +++++++++++++++++---------------- meta/src/cmdline.rs | 10 +- user/x86_64-unknown-quantum.ld | 3 - 9 files changed, 324 insertions(+), 267 deletions(-) diff --git a/crates/elf/src/lib.rs b/crates/elf/src/lib.rs index 822c9194..945c8d1b 100644 --- a/crates/elf/src/lib.rs +++ b/crates/elf/src/lib.rs @@ -25,6 +25,8 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA #![no_std] +use core::fmt::Display; + #[cfg(feature = "alloc")] pub mod elf_owned; pub mod tables; @@ -37,6 +39,13 @@ pub enum ElfErrorKind { Invalid, } +impl core::error::Error for ElfErrorKind {} +impl Display for ElfErrorKind { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + writeln!(f, "Elf failed : {:?}", self) + } +} + pub type Result = core::result::Result; // TODO: Add 'loader' trait for calling code when a section needs to be loaded diff --git a/crates/mem/src/page.rs b/crates/mem/src/page.rs index cd756b3d..be8924ee 100644 --- a/crates/mem/src/page.rs +++ b/crates/mem/src/page.rs @@ -156,6 +156,11 @@ impl PhysPage { pub const fn page(&self) -> usize { self.id } + + /// Check if this address is contained within this page + pub fn is_addr_contained_in_page(&self, addr: PhysAddr) -> bool { + self.addr() <= addr && self.addr().offset(S::N_BYTES) >= addr + } } /// A structure representing a well aligned Virtual page @@ -233,6 +238,11 @@ impl VirtPage { (lhs.id - self.id) * S::N_BYTES } + /// Offset this page by an offset of pages + pub const fn offset_by(self, offset: usize) -> Self { + Self::new(self.id + offset) + } + /// Get the distance (in pages) from `self` to `lhs`. /// /// # Note @@ -246,6 +256,11 @@ impl VirtPage { pub const fn page(&self) -> usize { self.id } + + /// Check if this address is contained within this page + pub fn is_addr_contained_in_page(&self, addr: VirtAddr) -> bool { + self.addr() <= addr && self.addr().offset(S::N_BYTES) >= addr + } } macro_rules! impl_traits_for { diff --git a/crates/mem/src/paging.rs b/crates/mem/src/paging.rs index 3c55dd25..8aa3f491 100644 --- a/crates/mem/src/paging.rs +++ b/crates/mem/src/paging.rs @@ -24,7 +24,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA */ extern crate alloc; -use core::ops::{BitOr, BitOrAssign}; +use core::ops::{Add, AddAssign, BitOr, BitOrAssign}; use crate::{ addr::{PhysAddr, VirtAddr}, @@ -869,6 +869,20 @@ impl VmOptions { } } +impl Add for VmPermissions { + type Output = VmPermissions; + + fn add(self, rhs: Self) -> Self::Output { + Self(self.0 | rhs.0) + } +} + +impl AddAssign for VmPermissions { + fn add_assign(&mut self, rhs: Self) { + self.0 |= rhs.0; + } +} + impl core::fmt::Debug for VmPermissions { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("VmPermissions") @@ -1032,8 +1046,13 @@ impl SafePageMapLvl4 { index < 512, "Table index ({index}) was out of range for a PageTable (max=512)!" ); + let is_zero = self.lower[index].is_none(); let table_mut = self.lower[index].get_or_insert_with(|| Box::new(SafePageMapLvl3::empty())); - let mut entry_mut = self.table.get(index); + let mut entry_mut = if is_zero { + PageEntryLvl4::zero() + } else { + self.table.get(index) + }; let reponse = f(&mut entry_mut, table_mut); @@ -1081,8 +1100,13 @@ impl SafePageMapLvl3 { index < 512, "Table index ({index}) was out of range for a PageTable (max=512)!" ); + let is_zero = self.lower[index].is_none(); let table_mut = self.lower[index].get_or_insert_with(|| Box::new(SafePageMapLvl2::empty())); - let mut entry_mut = self.table.get(index); + let mut entry_mut = if is_zero { + PageEntryLvl3::zero() + } else { + self.table.get(index) + }; let reponse = f(&mut entry_mut, table_mut); @@ -1130,8 +1154,13 @@ impl SafePageMapLvl2 { index < 512, "Table index ({index}) was out of range for a PageTable (max=512)!" ); + let is_zero = self.lower[index].is_none(); let table_mut = self.lower[index].get_or_insert_with(|| Box::new(SafePageMapLvl1::empty())); - let mut entry_mut = self.table.get(index); + let mut entry_mut = if is_zero { + PageEntryLvl2::zero() + } else { + self.table.get(index) + }; let reponse = f(&mut entry_mut, table_mut); diff --git a/crates/mem/src/vm.rs b/crates/mem/src/vm.rs index ee025ffa..d9e24838 100644 --- a/crates/mem/src/vm.rs +++ b/crates/mem/src/vm.rs @@ -29,7 +29,7 @@ use core::{error::Error, fmt::Display}; use crate::{ MemoryError, addr::{AlignedTo, VirtAddr}, - page::{Page4K, PhysPage, VirtPage}, + page::{PhysPage, VirtPage}, paging::{PageCorrelationError, Virt2PhysMapping, VmOptions, VmPermissions}, pmm::SharedPhysPage, }; @@ -41,8 +41,8 @@ use util::consts::PAGE_4K; /// A region of virtual memory 'virtual in pages' #[derive(Debug, Clone, Copy)] pub struct VmRegion { - start: VirtPage, - end: VirtPage, + pub start: VirtPage, + pub end: VirtPage, } impl VmRegion { @@ -101,6 +101,8 @@ pub enum PopulationReponse { Okay, /// There was a problem mapping this page MappingError(PageCorrelationError), + /// There was a problem mapping this page in the Inject action + InjectError(Box), } pub trait VmInjectFillAction: core::fmt::Debug { @@ -149,7 +151,7 @@ pub trait VmInjectFillAction: core::fmt::Debug { } /// What to do with this VmObject's memory. How should it be filled? -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum VmFillAction { /// Don't do anything after allocating a physical page Nothing, @@ -159,6 +161,13 @@ pub enum VmFillAction { InjectWith(Arc>), } +impl VmFillAction { + /// Convert a VmInjectFillAction into a VmFillAction + pub fn convert(thing: impl VmInjectFillAction + 'static) -> Self { + Self::InjectWith(Arc::new(RwLock::new(thing))) + } +} + /// Scrub the vpage's memory with the given pattern. /// /// The vpage must be kernel accessable before calling this function. @@ -267,6 +276,8 @@ pub enum NewVmObjectError { /// The type of error given when trying to map a page with a VmObject #[derive(Debug)] pub enum VmObjectMappingError { + /// We cannot populate a page if this table is not loaded + PageTableNotLoaded, /// Cannot map this page MappingError(PageCorrelationError), /// Failed to get a physical page @@ -276,6 +287,8 @@ pub enum VmObjectMappingError { region: VmRegion, requested_vpage: VirtPage, }, + /// There was a problem populating this entry + InjectError(Box), } impl Error for VmObjectMappingError {} @@ -347,6 +360,11 @@ impl VmObject { }); } + // We cannot populate page table while the table isnt loaded + if !vm_process.page_tables.is_loaded() { + return Err(VmObjectMappingError::PageTableNotLoaded); + } + // Get a new backing page for this vpage let backing_page = SharedPhysPage::allocate_anywhere() .map_err(|err| VmObjectMappingError::CannotGetPhysicalPage(err))?; @@ -372,6 +390,9 @@ impl VmObject { PopulationReponse::MappingError(page_correlation_error) => { return Err(VmObjectMappingError::MappingError(page_correlation_error)); } + PopulationReponse::InjectError(inject) => { + return Err(VmObjectMappingError::InjectError(inject)); + } } // Finally map the page back to the user when done @@ -639,42 +660,42 @@ pub fn remove_page_fault_handler() { *MAIN_PAGE_FAULT_HANDLER.write() = None; } -// TODO: REMOVE THIS FUNCTION, its just for testing :) -pub fn test() { - let proc = VmProcess::new(); - - proc.inplace_new_vmobject( - VmRegion::new(VirtPage::new(10), VirtPage::new(20)), - VmPermissions::none() - .set_read_flag(true) - .set_write_flag(true) - .set_user_flag(true), - VmFillAction::Nothing, - ) - .unwrap(); - - logln!( - "{:#?}", - proc.page_fault_handler(PageFaultInfo { - is_present: false, - write_read_access: false, - execute_fault: false, - user_fault: false, - vaddr: VirtPage::::new(15).addr(), - }) - ); - logln!( - "{:#?}", - proc.page_fault_handler(PageFaultInfo { - is_present: false, - write_read_access: false, - execute_fault: false, - user_fault: false, - vaddr: VirtPage::::new(16).addr(), - }) - ); - - logln!("{}", proc.page_tables); - - todo!("Test Done!"); -} +// // TODO: REMOVE THIS FUNCTION, its just for testing :) +// pub fn test() { +// let proc = VmProcess::new(); + +// proc.inplace_new_vmobject( +// VmRegion::new(VirtPage::new(10), VirtPage::new(20)), +// VmPermissions::none() +// .set_read_flag(true) +// .set_write_flag(true) +// .set_user_flag(true), +// VmFillAction::Nothing, +// ) +// .unwrap(); + +// logln!( +// "{:#?}", +// proc.page_fault_handler(PageFaultInfo { +// is_present: false, +// write_read_access: false, +// execute_fault: false, +// user_fault: false, +// vaddr: VirtPage::::new(15).addr(), +// }) +// ); +// logln!( +// "{:#?}", +// proc.page_fault_handler(PageFaultInfo { +// is_present: false, +// write_read_access: false, +// execute_fault: false, +// user_fault: false, +// vaddr: VirtPage::::new(16).addr(), +// }) +// ); + +// logln!("{}", proc.page_tables); + +// todo!("Test Done!"); +// } diff --git a/kernel/src/int.rs b/kernel/src/int.rs index a562d3ca..bc36e2ff 100644 --- a/kernel/src/int.rs +++ b/kernel/src/int.rs @@ -92,7 +92,10 @@ fn exception_handler(args: InterruptInfo) { } // panic mem::vm::PageFaultReponse::NotAttachedHandler => { - panic!("PageFault without attached handler!"); + panic!( + "PageFault without attached handler!\n{:#016x?}\n{:#016x?}", + info, args + ); } } } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 56b66864..097ebcf8 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -38,15 +38,17 @@ extern crate alloc; use arch::CpuPrivilege::Ring0; use bootloader::KernelBootHeader; +use elf::elf_owned::ElfOwned; use lldebug::{debug_ready, logln, make_debug}; use mem::{ + addr::VirtAddr, alloc::{KernelAllocator, provide_init_region}, paging::{Virt2PhysMapping, init_virt2phys_provider}, pmm::Pmm, - vmm::{VirtPage, VmPermissions, VmProcess, VmRegion, backing::KernelVmObject}, }; -use scheduler::Scheduler; +use scheduler::Process; use serial::{Serial, baud::SerialBaud}; +use tar::Tar; use timer::kernel_ticks; use util::{bytes::HumanBytes, consts::PAGE_4K}; @@ -103,52 +105,24 @@ fn main(kbh: &KernelBootHeader) { logln!("Attached virt2phys provider!"); init_virt2phys_provider(); - mem::vm::test(); - logln!("Init VirtMemoryManager"); - let kernel_process = unsafe { VmProcess::new_from_bootloader() }; - - kernel_process.add_vm_object(KernelVmObject::new_boxed( - VmRegion { - start: VirtPage::containing_page(kbh.kernel_elf.0), - end: VirtPage::containing_page(kbh.kernel_elf.0 + kbh.kernel_elf.1 as u64), - }, - VmPermissions::READ, - true, - )); - kernel_process.add_vm_object(KernelVmObject::new_boxed( - VmRegion { - start: VirtPage::containing_page(kbh.kernel_exe.0), - end: VirtPage::containing_page(kbh.kernel_exe.0 + kbh.kernel_exe.1 as u64), - }, - VmPermissions::READ | VmPermissions::EXEC, - true, - )); - kernel_process.add_vm_object(KernelVmObject::new_boxed( - VmRegion { - start: VirtPage::containing_page(kbh.kernel_stack.0), - end: VirtPage::containing_page(kbh.kernel_stack.0 + kbh.kernel_stack.1 as u64), - }, - VmPermissions::READ | VmPermissions::WRITE, - true, - )); - kernel_process.add_vm_object(KernelVmObject::new_boxed( - VmRegion { - start: VirtPage::containing_page(kbh.kernel_init_heap.0), - end: VirtPage::containing_page(kbh.kernel_init_heap.0 + kbh.kernel_init_heap.1 as u64), - }, - VmPermissions::READ | VmPermissions::WRITE, - true, - )); - - let mut scheduler = Scheduler::new(kernel_process); - - scheduler - .add_initfs(unsafe { - core::slice::from_raw_parts(kbh.initfs_ptr.0 as *const u8, kbh.initfs_ptr.1) - }) + + let initfs_slice = + unsafe { core::slice::from_raw_parts(kbh.initfs_ptr.0 as *const u8, kbh.initfs_ptr.1) }; + let dummy_elf = Tar::new(initfs_slice) + .iter() + .find(|h| h.is_file("dummy")) + .unwrap() + .file() .unwrap(); + let elf = ElfOwned::new_from_slice(dummy_elf); + let idk = unsafe { Virt2PhysMapping::inhearit_bootloader() }.unwrap(); + unsafe { idk.clone().load() }; + + let process = Process::new(0, &idk); + process.add_elf(elf).unwrap(); + logln!("Attempting to jump to userspace!"); unsafe { core::arch::asm!("int 0x31") }; logln!("Finished in {}ms", kernel_ticks()); diff --git a/kernel/src/scheduler.rs b/kernel/src/scheduler.rs index cc2814b8..bb7d6cdc 100644 --- a/kernel/src/scheduler.rs +++ b/kernel/src/scheduler.rs @@ -23,184 +23,219 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -use alloc::{boxed::Box, vec::Vec}; -use elf::{elf_owned::ElfOwned, tables::SegmentKind}; +use alloc::{ + boxed::Box, + collections::btree_map::BTreeMap, + vec::{self, Vec}, +}; +use elf::{ElfErrorKind, elf_owned::ElfOwned, tables::SegmentKind}; use lldebug::{hexdump::HexPrint, logln}; use mem::{ - MemoryError, - page::PhysPage, - vmm::{ - VirtPage, VmPermissions, VmProcess, VmRegion, - backing::{KernelVmObject, VmRegionObject}, + addr::VirtAddr, + page::VirtPage, + paging::{Virt2PhysMapping, VmPermissions}, + vm::{ + InsertVmObjectError, PopulationReponse, VmFillAction, VmInjectFillAction, VmProcess, + VmRegion, }, }; -use tar::Tar; -use util::consts::{PAGE_2M, PAGE_4K}; +use util::consts::PAGE_4K; +/// A structure repr a running process on the system +#[derive(Debug)] pub struct Process { - id: usize, vm: VmProcess, + id: usize, } -pub struct Scheduler { - kernel: Process, - process_list: Vec, +/// A structure repr the errors that could happen with a process +#[derive(Debug)] +pub enum ProcessError { + /// There was a problem loading the elf file + ElfLoadingError(ElfErrorKind), + /// There was a problem mapping the VmObject + InsertVmObjectErr(InsertVmObjectError), } -const EXPECTED_START_ADDR: usize = 0x00400000; -const EXPECTED_STACK_ADDR: usize = 0x10000000; -const EXPECTED_STACK_LEN: usize = 4096; - -const KERNEL_HANDLER_RSP: usize = 0x200000000000; - -impl Scheduler { - pub fn new(kernel_process: VmProcess) -> Self { +impl Process { + /// Create a new empty process + pub fn new(id: usize, table: &Virt2PhysMapping) -> Self { Self { - kernel: Process { - id: 0, - vm: kernel_process, - }, - process_list: Vec::new(), + vm: VmProcess::inhearit_page_tables(table), + id, } } - pub fn add_initfs(&mut self, initfs: &[u8]) -> Result<(), MemoryError> { - let tar_file = Tar::new(initfs); + /// Add an elf to process's memory map + pub fn add_elf(&self, elf: ElfOwned) -> Result<(), ProcessError> { + elf.elf() + .program_headers() + .unwrap() + .iter() + .for_each(|header| logln!("{header:#?}")); + unsafe { self.vm.page_tables.clone().load() }.unwrap(); + let elf_object = VmElfInject::new(elf); + let elf_sections = elf_object.load_segments()?; - for header in tar_file.iter() { - logln!("Found file: {:?}", header.filename()); - } + let inject_el = VmFillAction::convert(elf_object); - logln!("Done!"); - - let elf_owned = ElfOwned::new_from_slice( - tar_file - .iter() - .find(|t| t.is_file("dummy")) - .map(|t| t.file().unwrap()) - .unwrap(), - ); - - // Kernel Process Stack - self.kernel.vm.add_vm_object(KernelVmObject::new_boxed( - VmRegion { - start: VirtPage::containing_page((KERNEL_HANDLER_RSP - PAGE_2M) as u64), - end: VirtPage::containing_page((KERNEL_HANDLER_RSP + PAGE_4K) as u64), - }, - VmPermissions::READ | VmPermissions::WRITE | VmPermissions::USER | VmPermissions::EXEC, - false, - )); - self.kernel.vm.map_all_now(); - - let (vaddr_low, vaddr_hi) = elf_owned - .elf() - .vaddr_range() - .map_err(|_| MemoryError::NotSupported)?; - - let process = VmProcess::new_from(&self.kernel.vm); - - process.add_vm_object(ElfBacked::new_boxed( - VmRegion::from_vaddr(vaddr_low as u64, vaddr_hi - vaddr_low), - VmPermissions::WRITE | VmPermissions::READ | VmPermissions::USER | VmPermissions::EXEC, - elf_owned, - )); - process.add_vm_object(NothingBacked::new_boxed( - VmRegion { - start: VirtPage(1), - end: VirtPage(11), - }, - VmPermissions::WRITE | VmPermissions::READ | VmPermissions::USER, - )); - - process.map_all_now()?; - logln!("{:#?}", process); - logln!( - "Initfs loading to : V{:#016x} -> V{:#016x} [{} - {}] \n{}", - vaddr_low, - vaddr_hi, - vaddr_low / PAGE_4K, - vaddr_hi / PAGE_4K, - unsafe { - core::slice::from_raw_parts( - vaddr_low as *const u8, - 128, // Elf::new(initfs).exe_size().unwrap_or(0), - ) - } - .hexdump() - ); + for (region, perms) in elf_sections { + self.vm + .inplace_new_vmobject(region, perms, inject_el.clone()) + .map_err(|err| ProcessError::InsertVmObjectErr(err))?; + } + logln!("{self:#?}"); - Ok(()) + // let elf_object = + // self.vm.inplace_new_vmobject(region, permissions, fill_action) + todo!() } } +/// An elf backing object for a process's memory map #[derive(Debug)] -pub struct ElfBacked { - region: VmRegion, - permissions: VmPermissions, - // TODO: Make this global and ref to it instead of copying it a bunch of times - elf: ElfOwned, -} - -impl ElfBacked { - pub fn new_boxed( - region: VmRegion, - permissions: VmPermissions, - elf: ElfOwned, - ) -> Box { - Box::new(Self { - region, - permissions, - elf, - }) - } +pub struct VmElfInject { + file: ElfOwned, } -impl VmRegionObject for ElfBacked { - fn vm_region(&self) -> VmRegion { - self.region +impl VmElfInject { + /// Create a new VmElfInject + pub fn new(elf: ElfOwned) -> Self { + Self { file: elf } } - fn vm_permissions(&self) -> VmPermissions { - self.permissions - } - - fn init_page(&mut self, vpage: VirtPage, _ppage: PhysPage) -> Result<(), MemoryError> { - let elf_headers = self - .elf + /// Get an iterator over the different regions that this elf file + /// needs to load. + pub fn load_regions( + &self, + ) -> Result + use<'_>, ProcessError> + { + Ok(self + .file .elf() .program_headers() - .map_err(|_| MemoryError::DidNotHandleException)? + .map_err(|elf_err| ProcessError::ElfLoadingError(elf_err))? .iter() - .enumerate() - .filter(|(_, h)| { - let expected_vpage_start = VirtPage::containing_page(h.expected_vaddr()); - let expected_vpage_end = - VirtPage::containing_page(h.expected_vaddr() + h.in_mem_size() as u64); - - h.segment_kind() == SegmentKind::Load - && expected_vpage_start <= vpage - && expected_vpage_end >= vpage + .filter(|h| h.segment_kind() == SegmentKind::Load) + .map(|h| { + let expected_vaddr = VirtAddr::new(h.expected_vaddr() as usize); + let perms = VmPermissions::none() + .set_exec_flag(h.is_executable()) + .set_read_flag(h.is_readable()) + .set_write_flag(h.is_writable()) + .set_user_flag(true); + + ( + expected_vaddr, + expected_vaddr.offset(h.in_mem_size()), + perms, + ) + })) + } + + /// Get the load segments as aligned segments and permissions fixed + /// + /// Since elf exe don't have to have their segments perfectly page aligned + /// it is possible for two segments to overlap (in a page sense) so we + /// take the highest of the two and split them + pub fn load_segments( + &self, + ) -> Result + use<>, ProcessError> { + // FIXME: This is a realy bad impl of this, we should change this before anyone sees :) + let mut pages: BTreeMap = BTreeMap::new(); + + self.load_regions()? + .map(|(start, end, perm)| { + let vm_region = VmRegion::from_containing(start, end); + vm_region.pages_iter().map(move |page| (page, perm)) + }) + .flatten() + .inspect(|(page, perm)| { + logln!("LOAD PAGE [{:?}] - {}", page, perm); + }) + .for_each(|(page, perm)| { + if let Some(already_existing_page) = pages.get_mut(&page) { + *already_existing_page += perm; + } else { + pages.insert(page, perm); + } }); - let vbuffer = - unsafe { core::slice::from_raw_parts_mut((vpage.0 * PAGE_4K) as *mut u8, PAGE_4K) }; + let mut acc: BTreeMap> = BTreeMap::new(); + for (page, perm) in pages.into_iter() { + acc.entry(perm) + .and_modify(|old| old.push(page)) + .or_insert(alloc::vec![page]); + } + + Ok(acc.into_iter().map(|(perm, pages)| { + let mut region = VmRegion::new(pages[0], pages[0]); + + for page in pages { + if page.page() - 1 == region.end.page() { + region.end = VirtPage::new(region.end.page() + 1); + } else if page.page() + 1 == region.start.page() { + region.start = VirtPage::new(region.start.page() - 1); + } + } - for (i, header) in elf_headers { - let elf_memory_buffer = self - .elf - .elf() - .program_header_slice(&header) - .map_err(|_| MemoryError::DidNotHandleException)?; + (region, perm) + })) + } - let buf_start = (vpage.0 * PAGE_4K).saturating_sub(header.expected_vaddr() as usize); + /// Convert this object into a FillAction + pub fn fill_action(self) -> VmFillAction { + VmFillAction::convert(self) + } +} + +impl VmInjectFillAction for VmElfInject { + fn requests_all_pages_filled(&self, _parent_object: &mem::vm::VmObject) -> bool { + true + } + + /// Put data into this page + fn populate_page( + &mut self, + _parent_object: &mem::vm::VmObject, + _process: &VmProcess, + _relative_index: usize, + vpage: mem::page::VirtPage, + _ppage: mem::page::PhysPage, + ) -> mem::vm::PopulationReponse { + let headers = match self.file.elf().program_headers() { + Ok(header) => header, + Err(header_err) => return PopulationReponse::InjectError(Box::new(header_err)), + }; + + let vbuffer = unsafe { core::slice::from_raw_parts_mut(vpage.addr().as_mut_ptr(), 4096) }; + vbuffer.fill(0); + + for header in headers.iter().filter(|header| { + let start_addr = header.expected_vaddr() as usize; + let end_addr = start_addr + header.in_mem_size(); + + (vpage.is_addr_contained_in_page(VirtAddr::new(start_addr)) + || vpage.is_addr_contained_in_page(VirtAddr::new(end_addr))) + && header.segment_kind() == SegmentKind::Load + }) { + let elf_memory_buffer = match self.file.elf().program_header_slice(&header) { + Ok(o) => o, + Err(err) => return mem::vm::PopulationReponse::InjectError(Box::new(err)), + }; + + let buf_start = vpage + .addr() + .addr() + .saturating_sub(header.expected_vaddr() as usize); let vbuffer_offset = (header.expected_vaddr() as usize + buf_start) % PAGE_4K; let this_page_buffer = &elf_memory_buffer [buf_start..(buf_start + (PAGE_4K - vbuffer_offset)).min(elf_memory_buffer.len())]; logln!( - "ELF LOADING... [{}] {vbuffer_offset:>5}..{:<5} <-- {:>5}..{:<5} id={i} [{:>16x} - {:<16x}]", - vpage.0, + "ELF LOADING... [{}] {vbuffer_offset:>5}..{:<5} <-- {:>5}..{:<5} [{:>16x} - {:<16x}]", + vpage.page(), vbuffer_offset + this_page_buffer.len(), buf_start, (buf_start + (PAGE_4K - vbuffer_offset)).min(elf_memory_buffer.len()), @@ -211,32 +246,6 @@ impl VmRegionObject for ElfBacked { vbuffer[vbuffer_offset..vbuffer_offset + this_page_buffer.len()] .copy_from_slice(this_page_buffer); } - - Ok(()) - } -} - -#[derive(Debug)] -pub struct NothingBacked { - region: VmRegion, - permissions: VmPermissions, -} - -impl NothingBacked { - pub fn new_boxed(region: VmRegion, permissions: VmPermissions) -> Box { - Box::new(Self { - region, - permissions, - }) - } -} - -impl VmRegionObject for NothingBacked { - fn vm_region(&self) -> VmRegion { - self.region - } - - fn vm_permissions(&self) -> VmPermissions { - self.permissions + mem::vm::PopulationReponse::Okay } } diff --git a/meta/src/cmdline.rs b/meta/src/cmdline.rs index 1d21a1d7..b0c45bb3 100644 --- a/meta/src/cmdline.rs +++ b/meta/src/cmdline.rs @@ -9,23 +9,23 @@ pub struct CommandLine { pub option: Option, /// Enable Qemu's KVM - #[arg(long, default_value_t = false)] + #[arg(short, long, default_value_t = false)] pub enable_kvm: bool, /// Print all interrupts to std out - #[arg(long = "log-int", default_value_t = false)] + #[arg(short, long = "log-int", default_value_t = false)] pub log_interrupts: bool, /// Print std out to command-line - #[arg(long = "nographic", default_value_t = false)] + #[arg(short, long = "nographic", default_value_t = false)] pub no_graphic: bool, /// Slow down the emulator - #[arg(long = "slow", default_value_t = false)] + #[arg(short, long = "slow", default_value_t = false)] pub slow_emulator: bool, /// Use the bochs emulator - #[arg(long = "bochs", default_value_t = false)] + #[arg(short, long = "bochs", default_value_t = false)] pub use_bochs: bool, } diff --git a/user/x86_64-unknown-quantum.ld b/user/x86_64-unknown-quantum.ld index d0fce3ba..f5e7f739 100644 --- a/user/x86_64-unknown-quantum.ld +++ b/user/x86_64-unknown-quantum.ld @@ -24,7 +24,4 @@ SECTIONS { .eh_frame_hdr : { *(.eh_frame_hdr .eh_frame_hdr.*) } - .font : { - *(.font .font.*) - } }