diff --git a/src/interrupts.rs b/src/interrupts.rs index be066b2..8044903 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -204,22 +204,28 @@ fn get_buffer(id: u64) -> Option> { static REGISTERD_PIDS: Lazy>> = Lazy::new(|| RwLock::new(HashMap::new())); static INITRD_BUF: Lazy<&'static [u8]> = Lazy::new(|| { + #[warn(clippy::expect_used, reason = "FIXME")] + let ramdisk_start = BOOTINFO.ramdisk_addr.into_option().expect("initrd not present"); + let ramdisk_len = BOOTINFO.ramdisk_len; let initrd = unsafe { - #[warn(clippy::expect_used, reason = "FIXME")] - let ramdisk_start = BOOTINFO.ramdisk_addr.into_option().expect("initrd not present"); - let ramdisk_len = BOOTINFO.ramdisk_len; slice::from_raw_parts( ptr::with_exposed_provenance::(usize(ramdisk_start)), usize(ramdisk_len), ) }; - KERNEL_SPACE.lock().alloc_force_user = true; - let initrd = Box::leak( - Vec::with_capacity_in(initrd.len(), &*KERNEL_SPACE) - .tap_mut(|v| v.extend_from_slice(initrd)) - .into_boxed_slice(), - ); - KERNEL_SPACE.lock().alloc_force_user = false; + let initrd_start_page = Page::containing_address(VirtAddr::new(ramdisk_start)); + let initrd_num_pages = usize(ramdisk_len.div_ceil(4096)); + unsafe { + KERNEL_SPACE + .lock() + .update_flags( + initrd_start_page, + initrd_num_pages, + PageTableFlags::USER_ACCESSIBLE, + PageTableFlags::empty(), + ) + .unwrap(); + } initrd }); diff --git a/src/virtual_memory.rs b/src/virtual_memory.rs index a477b8e..72d05c2 100644 --- a/src/virtual_memory.rs +++ b/src/virtual_memory.rs @@ -17,7 +17,7 @@ use x86_64::{ registers::control::Cr3, structures::paging::{ frame::PhysFrameRange, - mapper::{MapToError, MappedFrame, TranslateResult, UnmapError}, + mapper::{FlagUpdateError, MapToError, MappedFrame, TranslateResult, UnmapError}, page::PageRange, FrameAllocator, FrameDeallocator, Mapper, OffsetPageTable, Page, PageTable, PageTableFlags, PhysFrame, Size4KiB, Translate, @@ -79,6 +79,15 @@ impl From for PagingError { } } +impl From for PagingError { + fn from(err: FlagUpdateError) -> Self { + match err { + FlagUpdateError::PageNotMapped => Self::PageNotMapped, + FlagUpdateError::ParentEntryHugePage => Self::ParentEntryHugePage, + } + } +} + // SAFETY: from_start_address_unchecked requires that the given address is page (4 KiB) aligned, // which means that the lower 12 bits are zero. We shift the page number left 12 bits, so the lower // 12 bits will always be zero. @@ -696,6 +705,43 @@ impl AddressSpace { Ok(dest_range_start) } + pub unsafe fn update_flags( + &mut self, + page: Page, + num_pages: usize, + set_flags: PageTableFlags, + clear_flags: PageTableFlags, + ) -> Result<(), PagingError> { + self.check_request_valid(page, num_pages)?; + #[expect( + clippy::arithmetic_side_effects, + reason = "check_request_valid guarentees this won't overflow" + )] + for page in (PageRange { start: page, end: page + u64(num_pages) }) { + let TranslateResult::Mapped { frame: _, offset: 0, flags } = + self.mapper.translate(page.start_address()) + else { + return Err(PagingError::PageNotMapped); + }; + unsafe { + self.mapper.update_flags(page, (flags | set_flags) & !(clear_flags))?.flush(); + self.mapper.set_flags_p3_entry( + page, + PageTableFlags::PRESENT + | PageTableFlags::WRITABLE + | PageTableFlags::USER_ACCESSIBLE, + )?.flush_all(); + self.mapper.set_flags_p2_entry( + page, + PageTableFlags::PRESENT + | PageTableFlags::WRITABLE + | PageTableFlags::USER_ACCESSIBLE, + )?.flush_all(); + } + } + Ok(()) + } + /// Finds a range of free pages and returns the starting page fn find_free_pages(&self, num_pages: usize) -> Result { if num_pages == 0 {