Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frame allocator changes #1004

Merged
merged 40 commits into from
Jul 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3d4d28e
added frames typestate, just finalizing chunk finding functions
Ramla-I Jul 6, 2023
34c2d8e
runs
Ramla-I Jul 6, 2023
b78dc4e
runs and tests pass
Ramla-I Jul 6, 2023
14fea3e
moved frames to lib.rs
Ramla-I Jul 6, 2023
bd0a7a5
removed frames file
Ramla-I Jul 6, 2023
dbcf462
comments
Ramla-I Jul 6, 2023
52ce8c3
comments
Ramla-I Jul 6, 2023
e5ec8f5
comments and clippy errors
Ramla-I Jul 6, 2023
2c0e482
pr changes
Ramla-I Jul 17, 2023
c57aa16
PR issues
Ramla-I Jul 18, 2023
69943bb
tests
Ramla-I Jul 18, 2023
21f2b38
moved frame state to memory structs
Ramla-I Jul 18, 2023
69d246d
added unmapped frames
Ramla-I Jul 19, 2023
0dfbc98
PR changes
Ramla-I Jul 20, 2023
45e3a30
comments
Ramla-I Jul 21, 2023
4c8d2ed
comments and cleanup
Ramla-I Jul 21, 2023
906a7b3
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
2d4987e
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
6abc6aa
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
a0c471d
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
bc69076
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
c6ce7ce
Update kernel/memory_structs/src/lib.rs
Ramla-I Jul 24, 2023
dc40d1f
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
01fd398
Update kernel/memory_structs/src/lib.rs
Ramla-I Jul 24, 2023
b786c22
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
ea87a4a
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
cc822c6
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
58d25aa
Update kernel/frame_allocator/src/lib.rs
Ramla-I Jul 24, 2023
66c0b26
small changes
Ramla-I Jul 24, 2023
a9ac710
changed UnmappedFramesInfo to UnmappedFrameRange
Ramla-I Jul 24, 2023
8639f12
drop handler log statements
Ramla-I Jul 24, 2023
7a6e458
pr comments
Ramla-I Jul 24, 2023
53a14b3
spacing
Ramla-I Jul 24, 2023
6f75236
improve formatting
kevinaboos Jul 24, 2023
a77b8b9
clarify `Frames` docs
kevinaboos Jul 24, 2023
00cc97f
improve clarity of docs / drop handler
kevinaboos Jul 24, 2023
42f7d84
fix formatting, use proper early return pattern
kevinaboos Jul 25, 2023
43ecf9f
comments
Ramla-I Jul 25, 2023
0d8ede6
make sure two frames objects never have the same range within the Fra…
Ramla-I Jul 27, 2023
cb1ec40
drop handler uses remove rather than replace_with
Ramla-I Jul 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
875 changes: 552 additions & 323 deletions kernel/frame_allocator/src/lib.rs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions kernel/frame_allocator/src/static_array_rb_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ impl <T: Ord> Wrapper<T> {
inner: value,
})
}

/// Returns the inner value, consuming this wrapper.
pub(crate) fn into_inner(self) -> T {
self.inner
}
}


Expand Down
105 changes: 60 additions & 45 deletions kernel/frame_allocator/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
//! Tests for the AllocatedFrames type, mainly the `split` method.
//! Tests for the `Frames` type, mainly the `split` method.

extern crate std;

use self::std::dbg;

use super::*;

impl PartialEq for AllocatedFrames {
fn eq(&self, other: &Self) -> bool {
self.frames == other.frames
}
}

fn from_addr(start_addr: usize, end_addr: usize) -> AllocatedFrames {
AllocatedFrames {
frames: FrameRange::new(
fn from_addr(start_addr: usize, end_addr: usize) -> FreeFrames {
FreeFrames::new(
MemoryRegionType::Free,
FrameRange::new(
Frame::containing_address(PhysicalAddress::new_canonical(start_addr)),
Frame::containing_address(PhysicalAddress::new_canonical(end_addr)),
)
}
)
}

fn frame_addr(addr: usize) -> Frame {
Expand All @@ -30,7 +25,7 @@ fn split_before_beginning() {
let original = from_addr( 0x4275000, 0x4285000);
let split_at = frame_addr(0x4274000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
assert!(result.is_err());
}
Expand All @@ -42,11 +37,13 @@ fn split_at_beginning() {
let first = AllocatedFrames::empty();
let second = from_addr( 0x4275000, 0x4285000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}


Expand All @@ -57,11 +54,13 @@ fn split_at_middle() {
let first = from_addr( 0x4275000, 0x427C000);
let second = from_addr( 0x427D000, 0x4285000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}

#[test]
Expand All @@ -71,11 +70,13 @@ fn split_at_end() {
let first = from_addr( 0x4275000, 0x4284000);
let second = from_addr( 0x4285000, 0x4285000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}


Expand All @@ -86,11 +87,13 @@ fn split_after_end() {
let first = from_addr( 0x4275000, 0x4285000);
let second = AllocatedFrames::empty();

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}


Expand All @@ -99,7 +102,7 @@ fn split_empty_at_zero() {
let original = AllocatedFrames::empty();
let split_at = frame_addr(0x0000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
assert!(result.is_err());
}
Expand All @@ -109,7 +112,7 @@ fn split_empty_at_one() {
let original = AllocatedFrames::empty();
let split_at = frame_addr(0x1000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
assert!(result.is_err());
}
Expand All @@ -119,7 +122,7 @@ fn split_empty_at_two() {
let original = AllocatedFrames::empty();
let split_at = frame_addr(0x2000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
assert!(result.is_err());
}
Expand All @@ -133,11 +136,13 @@ fn split_at_beginning_zero() {
let first = AllocatedFrames::empty();
let second = from_addr(0x0, 0x5000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}

#[test]
Expand All @@ -147,11 +152,13 @@ fn split_at_beginning_one() {
let first = from_addr( 0x0000, 0x0000);
let second = from_addr( 0x1000, 0x5000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}

#[test]
Expand All @@ -161,11 +168,13 @@ fn split_at_beginning_max_length_one() {
let first = AllocatedFrames::empty();
let second = from_addr(0xFFFF_FFFF_FFFF_F000, 0xFFFF_FFFF_FFFF_F000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}

#[test]
Expand All @@ -175,11 +184,13 @@ fn split_at_end_max_length_two() {
let first = from_addr( 0xFFFF_FFFF_FFFF_E000, 0xFFFF_FFFF_FFFF_E000);
let second = from_addr( 0xFFFF_FFFF_FFFF_F000, 0xFFFF_FFFF_FFFF_F000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}


Expand All @@ -190,11 +201,13 @@ fn split_after_end_max() {
let first = from_addr( 0xFFFF_FFFF_FFFF_E000, 0xFFFF_FFFF_FFFF_E000);
let second = AllocatedFrames::empty();

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}

#[test]
Expand All @@ -204,9 +217,11 @@ fn split_at_beginning_max() {
let first = AllocatedFrames::empty();
let second = from_addr(0xFFFF_FFFF_FFFF_E000, 0xFFFF_FFFF_FFFF_E000);

let result = original.split(split_at);
let result = original.split_at(split_at);
dbg!(&result);
let (result1, result2) = result.unwrap();
assert_eq!(result1, first);
assert_eq!(result2, second);
assert_eq!(result1.start(), first.start());
assert_eq!(result1.end(), first.end());
assert_eq!(result2.start(), second.start());
assert_eq!(result2.end(), second.end());
}
1 change: 1 addition & 0 deletions kernel/memory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub use page_allocator::{
};
pub use frame_allocator::{
AllocatedFrames,
UnmappedFrames,
allocate_frames,
allocate_frames_at,
allocate_frames_by_bytes,
Expand Down
23 changes: 12 additions & 11 deletions kernel/memory/src/paging/mapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use core::{
slice,
};
use log::{error, warn, debug, trace};
use crate::{BROADCAST_TLB_SHOOTDOWN_FUNC, VirtualAddress, PhysicalAddress, Page, Frame, FrameRange, AllocatedPages, AllocatedFrames};
use crate::{BROADCAST_TLB_SHOOTDOWN_FUNC, VirtualAddress, PhysicalAddress, Page, Frame, FrameRange, AllocatedPages, AllocatedFrames, UnmappedFrames};
use crate::paging::{
get_current_p4,
table::{P4, UPCOMING_P4, Table, Level4},
Expand All @@ -34,23 +34,23 @@ use owned_borrowed_trait::{OwnedOrBorrowed, Owned, Borrowed};
#[cfg(target_arch = "x86_64")]
use kernel_config::memory::ENTRIES_PER_PAGE_TABLE;

/// This is a private callback used to convert `UnmappedFrames` into `AllocatedFrames`.
/// This is a private callback used to convert `UnmappedFrameRange` into `UnmappedFrames`.
///
/// This exists to break the cyclic dependency cycle between `page_table_entry` and
/// `frame_allocator`, which depend on each other as such:
/// * `frame_allocator` needs to `impl Into<AllocatedPages> for UnmappedFrames`
/// * `frame_allocator` needs to `impl Into<Frames> for UnmappedFrameRange`
/// in order to allow unmapped exclusive frames to be safely deallocated
/// * `page_table_entry` needs to use the `AllocatedFrames` type in order to allow
/// page table entry values to be set safely to a real physical frame that is owned and exists.
///
/// To get around that, the `frame_allocator::init()` function returns a callback
/// to its function that allows converting a range of unmapped frames back into `AllocatedFrames`,
/// to its function that allows converting a range of unmapped frames back into `UnmappedFrames`,
/// which then allows them to be dropped and thus deallocated.
///
/// This is safe because the frame allocator can only be initialized once, and also because
/// only this crate has access to that function callback and can thus guarantee
/// that it is only invoked for `UnmappedFrames`.
pub(super) static INTO_ALLOCATED_FRAMES_FUNC: Once<fn(FrameRange) -> AllocatedFrames> = Once::new();
/// that it is only invoked for `UnmappedFrameRange`.
pub(super) static INTO_UNMAPPED_FRAMES_FUNC: Once<fn(FrameRange) -> UnmappedFrames> = Once::new();

/// A convenience function to translate the given virtual address into a
/// physical address using the currently-active page table.
Expand Down Expand Up @@ -609,8 +609,8 @@ impl MappedPages {
);
}

let mut first_frame_range: Option<AllocatedFrames> = None; // this is what we'll return
let mut current_frame_range: Option<AllocatedFrames> = None;
let mut first_frame_range: Option<UnmappedFrames> = None; // this is what we'll return
let mut current_frame_range: Option<UnmappedFrames> = None;

for page in self.pages.range().clone() {
let p1 = active_table_mapper.p4_mut()
Expand All @@ -630,8 +630,8 @@ impl MappedPages {
// freed from the newly-unmapped P1 PTE entry above.
match unmapped_frames {
UnmapResult::Exclusive(newly_unmapped_frames) => {
let newly_unmapped_frames = INTO_ALLOCATED_FRAMES_FUNC.get()
.ok_or("BUG: Mapper::unmap(): the `INTO_ALLOCATED_FRAMES_FUNC` callback was not initialized")
let newly_unmapped_frames = INTO_UNMAPPED_FRAMES_FUNC.get()
.ok_or("BUG: Mapper::unmap(): the `INTO_UNMAPPED_FRAMES_FUNC` callback was not initialized")
.map(|into_func| into_func(newly_unmapped_frames.deref().clone()))?;

if let Some(mut curr_frames) = current_frame_range.take() {
Expand Down Expand Up @@ -680,7 +680,8 @@ impl MappedPages {
}

// Ensure that we return at least some frame range, even if we broke out of the above loop early.
Ok(first_frame_range.or(current_frame_range))
Ok(first_frame_range.map(|f| f.into_allocated_frames())
.or(current_frame_range.map(|f| f.into_allocated_frames())))
}


Expand Down
8 changes: 4 additions & 4 deletions kernel/memory/src/paging/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use core::{
use log::debug;
use super::{
Frame, FrameRange, PageRange, VirtualAddress, PhysicalAddress,
AllocatedPages, allocate_pages, AllocatedFrames, PteFlags,
AllocatedPages, allocate_pages, AllocatedFrames, UnmappedFrames, PteFlags,
InitialMemoryMappings, tlb_flush_all, tlb_flush_virt_addr,
get_p4, find_section_memory_bounds,
};
Expand Down Expand Up @@ -223,11 +223,11 @@ pub fn get_current_p4() -> Frame {
pub fn init(
boot_info: &impl BootInformation,
stack_start_virt: VirtualAddress,
into_alloc_frames_fn: fn(FrameRange) -> AllocatedFrames,
into_unmapped_frames_fn: fn(FrameRange) -> UnmappedFrames,
) -> Result<InitialMemoryMappings, &'static str> {
// Store the callback from `frame_allocator::init()` that allows the `Mapper` to convert
// `page_table_entry::UnmappedFrames` back into `AllocatedFrames`.
mapper::INTO_ALLOCATED_FRAMES_FUNC.call_once(|| into_alloc_frames_fn);
// `page_table_entry::UnmappedFrameRange` back into `UnmappedFrames`.
mapper::INTO_UNMAPPED_FRAMES_FUNC.call_once(|| into_unmapped_frames_fn);

// bootstrap a PageTable from the currently-loaded page table
let mut page_table = PageTable::from_current()
Expand Down
25 changes: 24 additions & 1 deletion kernel/memory_structs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,35 @@

#![no_std]
#![feature(step_trait)]
#![allow(incomplete_features)]
kevinaboos marked this conversation as resolved.
Show resolved Hide resolved
#![feature(adt_const_params)]

use core::{
cmp::{min, max},
fmt,
iter::Step,
ops::{Add, AddAssign, Deref, DerefMut, Sub, SubAssign}
marker::ConstParamTy,
ops::{Add, AddAssign, Deref, DerefMut, Sub, SubAssign},
};
use kernel_config::memory::{MAX_PAGE_NUMBER, PAGE_SIZE};
use zerocopy::FromBytes;
use paste::paste;
use derive_more::*;
use range_inclusive::{RangeInclusive, RangeInclusiveIterator};

/// The possible states that a range of exclusively-owned pages or frames can be in.
#[derive(PartialEq, Eq, ConstParamTy)]
pub enum MemoryState {
/// Memory is free and owned by the allocator
Free,
/// Memory is allocated and can be used for a mapping
Allocated,
/// Memory is mapped (PTE has been set)
Mapped,
/// Memory has been unmapped (PTE has been cleared)
Unmapped
}

/// A macro for defining `VirtualAddress` and `PhysicalAddress` structs
/// and implementing their common traits, which are generally identical.
macro_rules! implement_address {
Expand Down Expand Up @@ -470,6 +486,13 @@ macro_rules! implement_page_frame_range {
None
}
}

#[doc = "Returns `true` if the `other` `" $TypeName "` is fully contained within this `" $TypeName "`."]
pub fn contains_range(&self, other: &$TypeName) -> bool {
!other.is_empty()
&& (other.start() >= self.start())
&& (other.end() <= self.end())
}
}
impl fmt::Debug for $TypeName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Expand Down
Loading