Compare commits

..

No commits in common. "b069ee78a8611887659e499e9ac01f32e86343c6" and "c9481b05c34dc6e886e1014ce3ff26a3c89b70ce" have entirely different histories.

7 changed files with 564 additions and 266 deletions

View file

@ -6,4 +6,4 @@ mod raw_node;
extern crate alloc; extern crate alloc;
pub use raw_node::{Color, RBTree, Side, TreeIter, TreeNodeIter, UnsafeNode}; pub use raw_node::{RBTree, TreeIter, TreeNodeIter};

View file

@ -709,7 +709,6 @@ impl<N: UnsafeNode> RBTree<N> {
} }
} }
#[must_use]
pub fn insert_node(&mut self, new_node: NonNull<N>) -> Option<NonNull<N>> { pub fn insert_node(&mut self, new_node: NonNull<N>) -> Option<NonNull<N>> {
let node_ref = unsafe { new_node.as_ref() }; let node_ref = unsafe { new_node.as_ref() };
@ -825,7 +824,6 @@ impl<N: UnsafeNode> RBTree<N> {
None None
} }
#[must_use]
pub fn remove<Q>(&mut self, key: &Q) -> Option<NonNull<N>> pub fn remove<Q>(&mut self, key: &Q) -> Option<NonNull<N>>
where where
N::Key: core::borrow::Borrow<Q>, N::Key: core::borrow::Borrow<Q>,
@ -995,17 +993,11 @@ impl<N: UnsafeNode> RBTree<N> {
z.node() z.node()
} }
pub fn iter_nodes(&self) -> TreeNodeIter<'_, N> { pub fn iter(&self) -> TreeNodeIter<'_, N> {
TreeNodeIter { TreeNodeIter {
range: TreeRange::full_range(self.root_handle()), range: TreeRange::full_range(self.root_handle()),
} }
} }
pub fn iter(&self) -> TreeIter<'_, N> {
TreeIter {
range: TreeRange::full_range(self.root_handle()),
}
}
} }
impl<N: UnsafeNode> Default for RBTree<N> { impl<N: UnsafeNode> Default for RBTree<N> {
@ -1235,7 +1227,7 @@ mod tests {
#[test] #[test]
fn next_of() { fn next_of() {
let mut tree = RBTree::<TestNode>::new(); let mut tree = RBTree::<TestNode>::new();
_ = tree.insert_node(Box::into_non_null(Box::new(TestNode::new(1)))); tree.insert_node(Box::into_non_null(Box::new(TestNode::new(1))));
assert_eq!(tree.root_handle().next_of(), None); assert_eq!(tree.root_handle().next_of(), None);
assert_eq!(tree.root_handle().next_back_of(), None); assert_eq!(tree.root_handle().next_back_of(), None);
@ -1253,11 +1245,11 @@ mod tests {
impl DummyTree { impl DummyTree {
fn new() -> Self { fn new() -> Self {
let a = Box::into_non_null(Box::new(TestNode::new(1))); let mut a = Box::into_non_null(Box::new(TestNode::new(1)));
let x = Box::into_non_null(Box::new(TestNode::new(2))); let mut x = Box::into_non_null(Box::new(TestNode::new(2)));
let b = Box::into_non_null(Box::new(TestNode::new(3))); let mut b = Box::into_non_null(Box::new(TestNode::new(3)));
let y = Box::into_non_null(Box::new(TestNode::new(4))); let mut y = Box::into_non_null(Box::new(TestNode::new(4)));
let c = Box::into_non_null(Box::new(TestNode::new(5))); let mut c = Box::into_non_null(Box::new(TestNode::new(5)));
unsafe { unsafe {
x.as_ref().set_left(Some(a)); x.as_ref().set_left(Some(a));
@ -1353,10 +1345,10 @@ mod tests {
for &node in &nodes { for &node in &nodes {
eprintln!("Inserting node with key: {}", unsafe { (*node).key }); eprintln!("Inserting node with key: {}", unsafe { (*node).key });
_ = tree.insert_node(unsafe { NonNull::new_unchecked(node) }); tree.insert_node(unsafe { NonNull::new_unchecked(node) });
eprintln!("Tree after insertion:"); eprintln!("Tree after insertion:");
for n in tree.iter_nodes() { for n in tree.iter() {
eprintln!( eprintln!(
"\tNode: {:?} => {:?}", "\tNode: {:?} => {:?}",
unsafe { n.node().map(|n| n.as_ref().key) }, unsafe { n.node().map(|n| n.as_ref().key) },
@ -1381,7 +1373,7 @@ mod tests {
.collect(); .collect();
for &node in &nodes { for &node in &nodes {
_ = tree.insert_node(unsafe { NonNull::new_unchecked(node) }); tree.insert_node(unsafe { NonNull::new_unchecked(node) });
} }
for i in 0..10 { for i in 0..10 {
@ -1397,7 +1389,7 @@ mod tests {
)); ));
eprintln!("Tree after removal:"); eprintln!("Tree after removal:");
for n in tree.iter_nodes() { for n in tree.iter() {
eprintln!( eprintln!(
"\tNode: {:?} => {:?}", "\tNode: {:?} => {:?}",
unsafe { n.node().map(|n| n.as_ref().key) }, unsafe { n.node().map(|n| n.as_ref().key) },

View file

@ -7,7 +7,6 @@
allocator_api, allocator_api,
ptr_cast_slice, ptr_cast_slice,
likely_unlikely, likely_unlikely,
int_roundings,
never_type never_type
)] )]
#![cfg_attr(test, feature(custom_test_frameworks))] #![cfg_attr(test, feature(custom_test_frameworks))]

View file

@ -72,7 +72,7 @@ extern "C" fn _start() -> ! {
let leaf = kernel::x86_64::cpuid::Leaf8000008::get(); let leaf = kernel::x86_64::cpuid::Leaf8000008::get();
serial_println!("max phy: {:#?}", leaf); serial_println!("max phy: {:#?}", leaf);
kernel::serial_println!("PMM: {pmm:#?}"); // kernel::serial_println!("PMM: {pmm:#?}");
let fb = limine_requests::FRAMEBUFFER_REQUEST let fb = limine_requests::FRAMEBUFFER_REQUEST
.framebuffers() .framebuffers()

View file

@ -1,9 +1,6 @@
use core::{alloc::Allocator, cell::Cell, fmt::Debug, num::NonZeroUsize, ptr::NonNull}; use core::{alloc::Allocator, fmt::Debug};
use bit_field::BitField; use crate::{memory::page_tree::PageTree, serial_println, sync::OnceLock, x86_64::PAGE_SIZE};
use rbtree::RBTree;
use crate::{serial_println, sync::OnceLock, x86_64::PAGE_SIZE};
pub static HHDM_BASE: OnceLock<u64> = OnceLock::new(); pub static HHDM_BASE: OnceLock<u64> = OnceLock::new();
@ -15,12 +12,6 @@ pub trait VirtAddrTranslationExt {
pub struct PhyAddr(pub u64); pub struct PhyAddr(pub u64);
impl PhyAddr { impl PhyAddr {
pub fn from_hhdm_virt(virt: impl Into<VirtAddr>) -> Option<Self> {
let hhdm_base = unsafe { *HHDM_BASE.get_unchecked() };
virt.into().0.checked_sub(hhdm_base).map(PhyAddr)
}
pub fn into_hhdm_virt(&self) -> VirtAddr { pub fn into_hhdm_virt(&self) -> VirtAddr {
VirtAddr(self.0 + unsafe { crate::memory::HHDM_BASE.get().unwrap_unchecked() }) VirtAddr(self.0 + unsafe { crate::memory::HHDM_BASE.get().unwrap_unchecked() })
} }
@ -30,10 +21,6 @@ impl PhyAddr {
pub fn byte_add(&self, offset: usize) -> PhyAddr { pub fn byte_add(&self, offset: usize) -> PhyAddr {
PhyAddr(self.0 + offset as u64) PhyAddr(self.0 + offset as u64)
} }
pub fn page_index(&self) -> u64 {
self.0.div_floor(PAGE_SIZE as u64)
}
} }
impl Debug for PhyAddr { impl Debug for PhyAddr {
@ -42,36 +29,6 @@ impl Debug for PhyAddr {
} }
} }
impl<T> From<&T> for VirtAddr {
fn from(ptr: &T) -> Self {
VirtAddr(ptr as *const T as u64)
}
}
impl<T> From<&mut T> for VirtAddr {
fn from(ptr: &mut T) -> Self {
VirtAddr(ptr as *mut T as u64)
}
}
impl<T> From<*const T> for VirtAddr {
fn from(ptr: *const T) -> Self {
VirtAddr(ptr as u64)
}
}
impl<T> From<*mut T> for VirtAddr {
fn from(ptr: *mut T) -> Self {
VirtAddr(ptr as u64)
}
}
impl<T> From<NonNull<T>> for VirtAddr {
fn from(ptr: NonNull<T>) -> Self {
VirtAddr(ptr.as_ptr() as u64)
}
}
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, PartialEq, Eq)]
pub struct VirtAddr(pub u64); pub struct VirtAddr(pub u64);
@ -112,35 +69,7 @@ pub struct PhysicalMemoryManager {
} }
pub struct PhysicalMemoryAllocator { pub struct PhysicalMemoryAllocator {
tree: RBTree<PhysicalPageNode>, tree: PageTree,
}
#[repr(C)]
#[derive(Debug)]
struct PageHeader {
node: PhysicalPageNode,
count: u64,
}
impl PageHeader {
fn phy(&self) -> Option<PhyAddr> {
PhyAddr::from_hhdm_virt(self)
}
fn new_from_page_idx_and_count(page_idx: usize, count: usize) -> NonNull<Self> {
let phy = PhyAddr(page_idx as u64 * PAGE_SIZE as u64);
let virt = phy.into_hhdm_virt();
let ptr = virt.as_mut::<Self>();
unsafe {
ptr.write(PageHeader {
node: PhysicalPageNode::new_red(),
count: count as u64,
});
}
NonNull::new(ptr).unwrap()
}
} }
impl Debug for PhysicalMemoryAllocator { impl Debug for PhysicalMemoryAllocator {
@ -149,17 +78,8 @@ impl Debug for PhysicalMemoryAllocator {
.field_with("tree", |f| { .field_with("tree", |f| {
let iter = self.tree.iter(); let iter = self.tree.iter();
write!(f, "[")?; write!(f, "[")?;
for key in iter { for info in iter {
let header = unsafe { (&raw const *key).cast::<PageHeader>().read_volatile() }; writeln!(f, "({:?}..{:?}), ", info.phy, info.end())?;
if let Some(phy) = header.phy() {
writeln!(
f,
"({:?}..{:?}), ",
phy,
phy.page_add(header.count as usize)
)?;
}
} }
write!(f, "]") write!(f, "]")
}) })
@ -174,7 +94,7 @@ impl PhysicalMemoryAllocator {
.filter(|region| region.region_type.is_usable()); .filter(|region| region.region_type.is_usable());
let mut pmm = PhysicalMemoryAllocator { let mut pmm = PhysicalMemoryAllocator {
tree: RBTree::new(), tree: PageTree::from_root(usize::MAX),
}; };
usable_regions.for_each(|region| { usable_regions.for_each(|region| {
@ -193,16 +113,7 @@ impl PhysicalMemoryAllocator {
page_index, page_index,
count count
); );
self.tree.free_region(page_index, count);
let node_ptr =
PageHeader::new_from_page_idx_and_count(page_index, count).cast::<PhysicalPageNode>();
let None = self.tree.insert_node(node_ptr) else {
panic!(
"Failed to insert node for page_index = {}, count = {}",
page_index, count
);
};
} }
} }
@ -218,14 +129,17 @@ unsafe impl Allocator for PanicingAllocator {
fn allocate( fn allocate(
&self, &self,
layout: core::alloc::Layout, layout: core::alloc::Layout,
) -> Result<NonNull<[u8]>, core::alloc::AllocError> { ) -> Result<core::ptr::NonNull<[u8]>, core::alloc::AllocError> {
match layout.size() { match layout.size() {
0 => Ok(NonNull::slice_from_raw_parts(NonNull::dangling(), 0)), 0 => Ok(core::ptr::NonNull::slice_from_raw_parts(
core::ptr::NonNull::dangling(),
0,
)),
_ => panic!("PanicingAllocator cannot allocate memory"), _ => panic!("PanicingAllocator cannot allocate memory"),
} }
} }
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: core::alloc::Layout) {} unsafe fn deallocate(&self, _ptr: core::ptr::NonNull<u8>, _layout: core::alloc::Layout) {}
} }
pub mod bump { pub mod bump {
@ -645,7 +559,7 @@ pub mod bump {
} }
} }
fn _asdf(bump: &mut Bump<super::PanicingAllocator>) { fn asdf(bump: &mut Bump<super::PanicingAllocator>) {
let mut bump = bump.as_scope(); let mut bump = bump.as_scope();
let x = bump.alloc_with(|| 3u64); let x = bump.alloc_with(|| 3u64);
bump.scope(|bump| { bump.scope(|bump| {
@ -657,165 +571,558 @@ pub mod bump {
} }
} }
/// A node for a red-black tree of free physical page chunks. mod page_tree {
/// use bit_field::BitField;
/// On amd64 platforms, the maximum physical address is 52 bits, the lower
/// 12 of which are zero for page aligned addresses.
/// Our Tree Node entry needs to store 3 page indices (parent, left, right) and a color bit.
struct PhysicalPageNode(Cell<u128>);
impl Debug for PhysicalPageNode { use crate::{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { memory::{PAGE_SIZE, PhyAddr},
use rbtree::UnsafeNode; serial_println,
};
f.debug_struct("PhysicalPageNode") use core::ops::{Index, IndexMut};
.field("parent", &self.parent())
.field("left", &self.left())
.field("right", &self.right())
.field("color", &self.color())
.finish()
}
}
impl PhysicalPageNode { pub enum SearchResult<T> {
fn new_red() -> Self { Found(T),
PhysicalPageNode(Cell::new(1 << 120)) NotFound(T),
} }
fn bits(&self) -> u128 { /// On amd64 platforms, the maximum physical address is 52 bits, the lower
self.0.get() /// 12 of which are zero for page aligned addresses.
/// Our Tree Node entry needs to store 3 page indices (left, right, parent) and a color bit.
struct CompactPage(u128);
impl CompactPage {
fn parent(&self) -> usize {
self.0.get_bits(0..40) as usize
}
fn set_parent(&mut self, parent: usize) {
self.0.set_bits(0..40, parent as u128);
} }
fn parent_bits(&self) -> u64 { fn left_child(&self) -> usize {
self.bits().get_bits(0..40) as u64 self.0.get_bits(40..80) as usize
}
fn set_left_child(&mut self, left: usize) {
self.0.set_bits(40..80, left as u128);
} }
fn set_parent_bits(&self, parent: u64) { fn right_child(&self) -> usize {
self.0.update(|mut bits| { self.0.get_bits(80..120) as usize
bits.set_bits(0..40, parent as u128); }
bits fn set_right_child(&mut self, right: usize) {
}); self.0.set_bits(80..120, right as u128);
} }
fn left_bits(&self) -> u64 { fn color(&self) -> bool {
self.bits().get_bits(40..80) as u64 self.0.get_bit(120)
}
fn set_color(&mut self, color: bool) {
self.0.set_bit(120, color);
} }
fn set_left_bits(&self, left: u64) { fn data(&self) -> u8 {
self.0.update(|mut bits| { self.0.get_bits(121..128) as u8
bits.set_bits(40..80, left as u128); }
bits fn set_data(&mut self, data: u8) {
}); self.0.set_bits(121..128, data as u128);
}
} }
fn right_bits(&self) -> u64 { struct Page {
self.bits().get_bits(80..120) as u64 left_idx: usize,
right_idx: usize,
parent: usize,
count: isize,
} }
fn set_right_bits(&self, right: u64) { impl Page {
self.0.update(|mut bits| { fn new_red(_idx: usize, count: usize) -> Self {
bits.set_bits(80..120, right as u128); Self {
bits left_idx: usize::MAX,
}); right_idx: usize::MAX,
parent: usize::MAX,
count: -(count as isize),
}
}
fn child(&self, left: bool) -> usize {
if left { self.left_idx } else { self.right_idx }
}
fn red(&self) -> bool {
self.count.is_negative()
}
fn set_color(&mut self, red: bool) {
if red {
self.count = -(self.count.unsigned_abs() as isize);
} else {
self.count = self.count.unsigned_abs() as isize;
}
}
fn count(&self) -> usize {
self.count.unsigned_abs()
}
fn set_count(&mut self, count: usize) {
let red = self.red();
self.count = if red {
-(count as isize)
} else {
count as isize
};
}
} }
fn color_bit(&self) -> bool { #[repr(transparent)]
self.bits().get_bit(120) pub struct PageTree {
root: usize,
pages: Pages,
} }
fn set_color_bit(&self, color: bool) { struct Pages;
self.0.update(|mut bits| {
bits.set_bit(120, color);
bits
});
}
}
/// A key for a red-black tree of free physical page chunks. impl Pages {
/// The key uses the address of the node as the key, which is unique and means fn get_disjoint_mut<const N: usize>(&mut self, indices: [usize; N]) -> [&mut Page; N] {
/// the key does not require any additional bits. indices.map(|idx| unsafe {
struct PhysicalPageNodeKey; PhyAddr(idx as u64 * PAGE_SIZE as u64)
.into_hhdm_virt()
impl Eq for PhysicalPageNodeKey {} .as_mut::<Page>()
.as_mut_unchecked()
impl PartialEq for PhysicalPageNodeKey { })
fn eq(&self, _other: &Self) -> bool {
core::ptr::eq(self, _other)
}
}
impl PartialOrd for PhysicalPageNodeKey {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for PhysicalPageNodeKey {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
(&raw const *self).cmp(&(&raw const *other))
}
}
unsafe impl rbtree::UnsafeNode for PhysicalPageNode {
type Key = PhysicalPageNodeKey;
fn left(&self) -> Option<NonNull<Self>> {
NonZeroUsize::new((self.left_bits() << 12) as usize).map(NonNull::with_exposed_provenance)
} }
fn right(&self) -> Option<NonNull<Self>> { fn get_ptr(&self, idx: usize) -> *const Page {
NonZeroUsize::new((self.right_bits() << 12) as usize).map(NonNull::with_exposed_provenance) PhyAddr(idx as u64 * PAGE_SIZE as u64)
.into_hhdm_virt()
.as_ptr::<Page>()
} }
fn parent(&self) -> Option<NonNull<Self>> { fn get_mut(&mut self, idx: usize) -> &mut Page {
NonZeroUsize::new((self.parent_bits() << 12) as usize).map(NonNull::with_exposed_provenance) unsafe {
PhyAddr(idx as u64 * PAGE_SIZE as u64)
.into_hhdm_virt()
.as_mut::<Page>()
.as_mut_unchecked()
}
}
} }
fn key(&self) -> &Self::Key { impl Index<usize> for Pages {
assert_eq!( type Output = Page;
core::mem::size_of::<Self::Key>(), fn index(&self, idx: usize) -> &Self::Output {
0, unsafe {
"PhysicalPageNodeKey must be zero-sized" PhyAddr(idx as u64 * PAGE_SIZE as u64)
.into_hhdm_virt()
.as_ptr::<Page>()
.as_ref_unchecked()
}
}
}
impl IndexMut<usize> for Pages {
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
unsafe {
PhyAddr(idx as u64 * PAGE_SIZE as u64)
.into_hhdm_virt()
.as_mut::<Page>()
.as_mut_unchecked()
}
}
}
impl PageTree {
pub fn from_root(root: usize) -> Self {
Self { root, pages: Pages }
}
pub fn free_region(&mut self, page_index: usize, count: usize) {
let pre = match self.find(page_index) {
SearchResult::Found(_) => panic!("Page index already exists in free list"),
SearchResult::NotFound(Self::INVALID_IDX) => Self::INVALID_IDX,
SearchResult::NotFound(idx) => {
if idx > page_index {
self.next_back_of(idx)
} else {
idx
}
}
};
match pre {
Self::INVALID_IDX => {
self.insert(page_index, count);
}
_ => {
if self.pages[pre].count() + pre == page_index {
serial_println!(
"Found previous page: pre = {}, pre_count = {}",
pre,
self.pages[pre].count()
); );
// SAFETY: The key is a zero-sized type, so we can transmute the let new_count = self.pages[pre].count() + count;
// reference to the node to a reference to the key. self.pages[pre].set_count(new_count);
unsafe { core::mem::transmute_copy::<&PhysicalPageNode, &PhysicalPageNodeKey>(&self) }
}
fn color(&self) -> rbtree::Color {
if self.color_bit() {
rbtree::Color::Red
} else { } else {
rbtree::Color::Black self.insert(page_index, count);
}
}
} }
} }
fn set_left(&self, left: Option<NonNull<Self>>) { // rb-tree impl
self.set_left_bits(left.map_or(0, |ptr| {
PhyAddr::from_hhdm_virt(VirtAddr::from(ptr)) const INVALID_IDX: usize = usize::MAX;
.expect("PhysicalPageNode left pointer is not in HHDM") fn rotate(&mut self, x: usize, left: bool) {
.page_index() let (y, b, x_hole, y_hole) = if left {
})); let y = self.pages[x].right_idx;
let b = self.pages[y].left_idx;
let [x_page, y_page] = self.pages.get_disjoint_mut([x, y]);
let x_hole = &mut x_page.right_idx;
let y_hole = &mut y_page.left_idx;
(y, b, x_hole, y_hole)
} else {
let y = self.pages[x].left_idx;
let b = self.pages[y].right_idx;
let [x_page, y_page] = self.pages.get_disjoint_mut([x, y]);
let x_hole = &mut x_page.left_idx;
let y_hole = &mut y_page.right_idx;
(y, b, x_hole, y_hole)
};
*x_hole = b;
*y_hole = x;
if b != usize::MAX {
self.pages[b].parent = x;
} }
fn set_right(&self, right: Option<NonNull<Self>>) { let x_parent = self.pages[x].parent;
self.set_right_bits(right.map_or(0, |ptr| { self.pages[y].parent = x_parent;
PhyAddr::from_hhdm_virt(VirtAddr::from(ptr)) if self.pages[x].parent == usize::MAX {
.expect("PhysicalPageNode right pointer is not in HHDM") self.root = y;
.page_index() } else if x == self.pages[x_parent].left_idx {
})); self.pages[x_parent].left_idx = y;
} else {
self.pages[x_parent].right_idx = y;
} }
fn set_parent(&self, parent: Option<NonNull<Self>>) { self.pages[x].parent = y;
self.set_parent_bits(parent.map_or(0, |ptr| {
PhyAddr::from_hhdm_virt(VirtAddr::from(ptr))
.expect("PhysicalPageNode parentpointer is not in HHDM")
.page_index()
}));
} }
fn set_color(&self, color: rbtree::Color) { pub fn find(&self, idx: usize) -> SearchResult<usize> {
self.set_color_bit(color == rbtree::Color::Red); let mut node = self.root;
let mut parent = usize::MAX;
while node != usize::MAX {
parent = node;
if idx < node {
node = self.pages[node].left_idx;
} else if idx > node {
node = self.pages[node].right_idx;
} else {
return SearchResult::Found(node);
}
}
SearchResult::NotFound(parent)
}
pub fn insert(&mut self, idx: usize, count: usize) {
let SearchResult::NotFound(parent) = self.find(idx) else {
panic!("Page index already exists in free list");
};
let page = &mut self.pages[idx];
*page = Page::new_red(idx, count);
page.parent = parent;
if parent == usize::MAX {
self.root = idx;
} else if idx < parent {
self.set_left_child_of(parent, idx);
} else {
self.set_right_child_of(parent, idx);
}
self.fixup_insert(idx);
}
fn fixup_insert(&mut self, mut idx: usize) {
// idx is red; fixup the tree while the parent is red
loop {
let parent = self.parent_of(idx);
if parent == usize::MAX || !self.color_of(parent) {
break;
}
// gp is guaranteed to exist because the parent is red and the root is black
let gp = self.pages[parent].parent;
let (uncle, uncle_left) = if parent == self.pages[gp].left_idx {
(self.pages[gp].right_idx, false)
} else {
(self.pages[gp].left_idx, true)
};
if self.color_of(uncle) {
self.pages[parent].set_color(false);
self.pages[uncle].set_color(false);
self.pages[gp].set_color(true);
idx = gp;
} else {
// uncle is black
if idx == self.pages[parent].child(uncle_left) {
// idx is on the same side as uncle
self.rotate(parent, !uncle_left);
idx = parent;
}
self.pages[parent].set_color(false);
self.pages[gp].set_color(true);
self.rotate(gp, uncle_left);
}
}
self.pages[self.root].set_color(false);
}
/// replaces the node at `at_idx` with the node at `with_idx`.
fn replace(&mut self, at_idx: usize, with_idx: usize) {
let at_parent = self.parent_of(at_idx);
match at_parent {
Self::INVALID_IDX => {}
_ if at_idx == self.left_child_of(at_parent) => {
self.set_left_child_of(at_parent, with_idx);
}
_ => {
self.set_right_child_of(at_parent, with_idx);
}
}
if let Self::INVALID_IDX = with_idx {
} else {
self.set_parent_of(with_idx, at_parent);
}
}
/// returns the next node in the tree after `idx`, or usize::MAX if there is no next node.
fn minimum_of(&self, mut idx: usize) -> usize {
loop {
let next = self.left_child_of(idx);
if next == usize::MAX {
break;
}
idx = next;
}
idx
}
fn maximum_of(&self, mut idx: usize) -> usize {
loop {
let next = self.right_child_of(idx);
if next == usize::MAX {
break;
}
idx = next;
}
idx
}
fn next_back_of(&self, mut idx: usize) -> usize {
match self.left_child_of(idx) {
Self::INVALID_IDX => {
let mut p = self.parent_of(idx);
while p != Self::INVALID_IDX && idx == self.left_child_of(p) {
idx = p;
p = self.parent_of(idx);
}
p
}
left => self.maximum_of(left),
}
}
fn next_of(&self, mut idx: usize) -> usize {
match self.right_child_of(idx) {
Self::INVALID_IDX => {
let mut p = self.parent_of(idx);
while p != Self::INVALID_IDX && idx == self.right_child_of(p) {
idx = p;
p = self.parent_of(idx);
}
p
}
right => self.minimum_of(right),
}
}
fn left_child_of(&self, idx: usize) -> usize {
self.pages[idx].left_idx
}
fn right_child_of(&self, idx: usize) -> usize {
self.pages[idx].right_idx
}
fn child_of(&self, idx: usize, left: bool) -> usize {
if left {
self.pages[idx].left_idx
} else {
self.pages[idx].right_idx
}
}
fn children_of(&self, idx: usize) -> (usize, usize) {
(self.pages[idx].left_idx, self.pages[idx].right_idx)
}
fn parent_of(&self, idx: usize) -> usize {
self.pages[idx].parent
}
fn set_parent_of(&mut self, idx: usize, parent: usize) {
if idx != Self::INVALID_IDX {
self.pages[idx].parent = parent;
}
}
fn set_color_of(&mut self, idx: usize, red: bool) {
self.pages[idx].set_color(red);
}
fn color_of(&self, idx: usize) -> bool {
// leaves are implicitly black
idx != Self::INVALID_IDX && self.pages[idx].red()
}
fn set_left_child_of(&mut self, idx: usize, left: usize) {
self.pages[idx].left_idx = left;
}
fn set_right_child_of(&mut self, idx: usize, right: usize) {
self.pages[idx].right_idx = right;
}
pub fn remove(&mut self, z: usize) {
let y = match self.children_of(z) {
(Self::INVALID_IDX, _) | (_, Self::INVALID_IDX) => z,
_ => self.next_of(z),
};
let x = match self.left_child_of(y) {
Self::INVALID_IDX => self.right_child_of(y),
_ => self.left_child_of(y),
};
let p_y = self.parent_of(y);
self.set_parent_of(x, p_y);
match p_y {
Self::INVALID_IDX => {
self.root = x;
}
_ if y == self.left_child_of(p_y) => {
self.set_left_child_of(p_y, x);
}
_ => {
self.set_right_child_of(p_y, x);
}
}
let color = self.color_of(y);
if y != z {
self.replace(z, y);
}
if !color {
self.fixup_remove(x);
}
}
fn fixup_remove(&mut self, mut x: usize) {
loop {
if x == self.root || self.color_of(x) {
break;
}
let p_x = self.parent_of(x);
let (mut w, w_left) = if x == self.left_child_of(p_x) {
(self.right_child_of(p_x), false)
} else {
(self.left_child_of(p_x), true)
};
if self.color_of(w) {
self.set_color_of(w, false);
self.set_color_of(p_x, true);
self.rotate(p_x, !w_left);
w = self.child_of(p_x, w_left);
}
// w is now black
match (
self.color_of(self.left_child_of(w)),
self.color_of(self.right_child_of(w)),
) {
(false, false) => {
self.set_color_of(w, true);
x = p_x;
continue;
}
(left @ true, false) | (left @ false, true) => {
if left != w_left {
self.set_color_of(self.child_of(w, left), false);
self.set_color_of(w, true);
self.rotate(w, w_left);
}
self.set_color_of(w, self.color_of(p_x));
self.set_color_of(p_x, false);
self.set_color_of(self.child_of(w, w_left), false);
self.rotate(p_x, !w_left);
x = self.root;
}
(true, true) => {
x = self.root;
}
}
}
}
pub fn iter(&self) -> PageTreeIter<'_> {
PageTreeIter {
tree: self,
next: self.minimum_of(self.root),
}
}
}
pub struct PageTreeIter<'a> {
tree: &'a PageTree,
next: usize,
}
pub struct PageInfo {
pub phy: PhyAddr,
pub count: usize,
}
impl PageInfo {
pub fn end(&self) -> PhyAddr {
self.phy.page_add(self.count)
}
}
impl<'a> Iterator for PageTreeIter<'a> {
type Item = PageInfo;
fn next(&mut self) -> Option<Self::Item> {
if self.next == usize::MAX {
return None;
}
let page_info = PageInfo {
phy: PhyAddr(self.next as u64 * PAGE_SIZE as u64),
count: self.tree.pages[self.next].count(),
};
self.next = self.tree.next_of(self.next);
Some(page_info)
}
} }
} }

View file

@ -24,8 +24,8 @@ pub fn cpuid(eax: u32, ecx: u32) -> CpuidResult {
} }
pub struct CpuId { pub struct CpuId {
pub max_eax: u32, max_eax: u32,
pub vendor_id: [u8; 12], vendor_id: [u8; 12],
} }
pub struct Leaf1(CpuidResult); pub struct Leaf1(CpuidResult);

View file

@ -1,4 +1,4 @@
use core::{arch::asm, fmt::Debug}; use core::{arch::asm, fmt::Debug, ops::Index};
use bit_field::BitField; use bit_field::BitField;
use bitflags::bitflags; use bitflags::bitflags;