Use bootloader provided initrd instead of copying it

This commit is contained in:
pjht 2024-08-17 16:26:34 -05:00
parent 3ef75dcfbc
commit 9b7e36056a
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
2 changed files with 63 additions and 11 deletions

View File

@ -204,22 +204,28 @@ fn get_buffer(id: u64) -> Option<Box<[u8], &'static ASpaceMutex>> {
static REGISTERD_PIDS: Lazy<RwLock<HashMap<u64, u64>>> = 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::<u8>(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
});

View File

@ -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<UnmapError> for PagingError {
}
}
impl From<FlagUpdateError> 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<Page, PagingError> {
if num_pages == 0 {