Switch to a bump allocator for user virtual memory allocations
This commit is contained in:
parent
07393d8c71
commit
d4df5b53ff
@ -32,6 +32,7 @@ pub struct AddressSpace {
|
||||
pub alloc_force_user: bool,
|
||||
pub mapper: OffsetPageTable<'static>,
|
||||
bytes_allocated: AtomicUsize,
|
||||
bump_base: Page,
|
||||
}
|
||||
|
||||
impl fmt::Debug for AddressSpace {
|
||||
@ -196,6 +197,7 @@ pub static KERNEL_SPACE: Lazy<ASpaceMutex> = Lazy::new(|| {
|
||||
}
|
||||
let mut kernel_space = AddressSpace::new_with_addr(table);
|
||||
kernel_space.is_kernel = true;
|
||||
kernel_space.bump_base = KERNEL_PAGE_RANGE.start;
|
||||
let l4_virt = VirtAddr::from_ptr(ptr::from_ref(kernel_space.mapper.level_4_table()));
|
||||
#[expect(
|
||||
clippy::unwrap_used,
|
||||
@ -251,6 +253,7 @@ impl AddressSpace {
|
||||
alloc_force_user: false,
|
||||
is_kernel: false,
|
||||
bytes_allocated: AtomicUsize::new(0),
|
||||
bump_base: USER_PAGE_RANGE.start,
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,6 +382,9 @@ impl AddressSpace {
|
||||
PhysFrame::from_start_address_unchecked(PhysAddr::new(0x000F_FFFF_FFFF_F000))
|
||||
};
|
||||
self.check_request_valid(page, num_pages)?;
|
||||
if self.bump_base < page + u64(num_pages) {
|
||||
self.bump_base = page + u64(num_pages);
|
||||
}
|
||||
#[expect(
|
||||
clippy::arithmetic_side_effects,
|
||||
reason = "This is the maximum physical frame, so there is no way the subtraction can underflow"
|
||||
@ -455,6 +461,9 @@ impl AddressSpace {
|
||||
flags: PageTableFlags,
|
||||
) -> Result<*mut u8, PagingError> {
|
||||
self.check_request_valid(page, num_pages)?;
|
||||
if self.bump_base < page + u64(num_pages) {
|
||||
self.bump_base = page + u64(num_pages);
|
||||
}
|
||||
#[expect(
|
||||
clippy::arithmetic_side_effects,
|
||||
reason = "check_request_valid guarentees this won't overflow"
|
||||
@ -544,7 +553,8 @@ impl AddressSpace {
|
||||
num_pages: usize,
|
||||
flags: PageTableFlags,
|
||||
) -> Result<*mut u8, PagingError> {
|
||||
unsafe { self.map_to(self.find_free_pages(num_pages)?, phys_frame, num_pages, flags) }
|
||||
let start_page = self.find_free_pages(num_pages)?;
|
||||
unsafe { self.map_to(start_page, phys_frame, num_pages, flags) }
|
||||
}
|
||||
|
||||
/// Maps new virtual pages to new physical memory and returns the starting address.
|
||||
@ -555,9 +565,10 @@ impl AddressSpace {
|
||||
num_pages: usize,
|
||||
flags: PageTableFlags,
|
||||
) -> Result<*mut u8, PagingError> {
|
||||
let start_page = self.find_free_pages(num_pages)?;
|
||||
// SAFETY: &mut aliasing is prevented by using free physical frames, and uninitialized
|
||||
// values are prevented by using free virtual pages.
|
||||
let ptr = unsafe { self.map(self.find_free_pages(num_pages)?, num_pages, flags)? };
|
||||
let ptr = unsafe { self.map(start_page, num_pages, flags)? };
|
||||
self.record_alloc(num_pages * 4096);
|
||||
Ok(ptr)
|
||||
}
|
||||
@ -571,10 +582,10 @@ impl AddressSpace {
|
||||
num_pages: usize,
|
||||
flags: PageTableFlags,
|
||||
) -> Result<(*mut u8, u64), PagingError> {
|
||||
let start_page = self.find_free_pages(num_pages)?;
|
||||
// SAFETY: &mut aliasing is prevented by using free physical frames, and uninitialized
|
||||
// values are prevented by using free virtual pages.
|
||||
let ptr =
|
||||
unsafe { self.map_cont_phys(self.find_free_pages(num_pages)?, num_pages, flags)? };
|
||||
let ptr = unsafe { self.map_cont_phys(start_page, num_pages, flags)? };
|
||||
self.record_alloc(num_pages * 4096);
|
||||
Ok(ptr)
|
||||
}
|
||||
@ -602,6 +613,9 @@ impl AddressSpace {
|
||||
flags: PageTableFlags,
|
||||
) -> Result<*mut u8, PagingError> {
|
||||
self.check_request_valid(page, num_pages)?;
|
||||
if self.bump_base < page + u64(num_pages) {
|
||||
self.bump_base = page + u64(num_pages);
|
||||
}
|
||||
assert!(!self.alloc_force_user);
|
||||
#[expect(
|
||||
clippy::arithmetic_side_effects,
|
||||
@ -733,33 +747,41 @@ impl AddressSpace {
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
return Err(PagingError::PageAllocationFailed);
|
||||
}
|
||||
let mut remaining_pages = num_pages;
|
||||
let range = if self.is_kernel { KERNEL_PAGE_RANGE } else { USER_PAGE_RANGE };
|
||||
for page in range {
|
||||
if self.translate_addr(page.start_address()).is_none() {
|
||||
#[expect(
|
||||
clippy::arithmetic_side_effects,
|
||||
reason = "remaining_pages can never be 0 here, thus this can't underflow"
|
||||
)]
|
||||
{
|
||||
remaining_pages -= 1;
|
||||
}
|
||||
if remaining_pages == 0 {
|
||||
fn find_free_pages(&mut self, num_pages: usize) -> Result<Page, PagingError> {
|
||||
if self.is_kernel {
|
||||
if num_pages == 0 {
|
||||
return Err(PagingError::PageAllocationFailed);
|
||||
}
|
||||
let mut remaining_pages = num_pages;
|
||||
let range = if self.is_kernel { KERNEL_PAGE_RANGE } else { USER_PAGE_RANGE };
|
||||
for page in range {
|
||||
if self.translate_addr(page.start_address()).is_none() {
|
||||
#[expect(
|
||||
clippy::arithmetic_side_effects,
|
||||
reason = "page is at minimum num_pages - 1, thus this can't underflow"
|
||||
reason = "remaining_pages can never be 0 here, thus this can't underflow"
|
||||
)]
|
||||
return Ok(page + 1 - u64(num_pages));
|
||||
}
|
||||
} else {
|
||||
remaining_pages = num_pages;
|
||||
};
|
||||
{
|
||||
remaining_pages -= 1;
|
||||
}
|
||||
if remaining_pages == 0 {
|
||||
#[expect(
|
||||
clippy::arithmetic_side_effects,
|
||||
reason = "page is at minimum num_pages - 1, thus this can't underflow"
|
||||
)]
|
||||
return Ok(page + 1 - u64(num_pages));
|
||||
}
|
||||
} else {
|
||||
remaining_pages = num_pages;
|
||||
};
|
||||
}
|
||||
Err(PagingError::PageAllocationFailed)
|
||||
} else if USER_PAGE_RANGE.end - self.bump_base < u64(num_pages) {
|
||||
Err(PagingError::PageAllocationFailed)
|
||||
} else {
|
||||
let old_base = self.bump_base;
|
||||
self.bump_base += u64(num_pages);
|
||||
Ok(old_base)
|
||||
}
|
||||
Err(PagingError::PageAllocationFailed)
|
||||
}
|
||||
|
||||
pub fn record_alloc(&self, size: usize) {
|
||||
|
Loading…
Reference in New Issue
Block a user