Compare commits
No commits in common. "549b94d34ce4e9ec0e7450e518bc0989f61a2387" and "238e822751558e1a8eca5d380ee88f326b2c3729" have entirely different histories.
549b94d34c
...
238e822751
|
|
@ -835,13 +835,6 @@ impl<N: UnsafeNode> RBTree<N> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn pop_min(&mut self) -> Option<NonNull<N>> {
|
|
||||||
let min = self.root_handle().minimum_of()?;
|
|
||||||
|
|
||||||
self.remove_node(min)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
#[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
|
||||||
|
|
@ -852,11 +845,6 @@ impl<N: UnsafeNode> RBTree<N> {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
self.remove_node(z)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
fn remove_node(&mut self, z: Handle<N>) -> Option<NonNull<N>> {
|
|
||||||
// Y is either Z, the removed node in the case that Z has at most
|
// Y is either Z, the removed node in the case that Z has at most
|
||||||
// one child, or Y is Z's successor which is guaranteed to have at most one
|
// one child, or Y is Z's successor which is guaranteed to have at most one
|
||||||
// child (the right child).
|
// child (the right child).
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,6 @@ impl MemoryRegionType {
|
||||||
pub fn is_usable(&self) -> bool {
|
pub fn is_usable(&self) -> bool {
|
||||||
matches!(self, Self::Usable | Self::AcpiReclaimable)
|
matches!(self, Self::Usable | Self::AcpiReclaimable)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mapped_non_usable(&self) -> bool {
|
|
||||||
matches!(self, Self::Framebuffer | Self::FirmwareReserved)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
@ -52,15 +48,6 @@ pub struct MemoryRegion {
|
||||||
pub region_type: MemoryRegionType,
|
pub region_type: MemoryRegionType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MemoryRegion {
|
|
||||||
pub fn overlaps(&self, other: &Self) -> bool {
|
|
||||||
let self_end = self.start + self.length;
|
|
||||||
let other_end = other.start + other.length;
|
|
||||||
|
|
||||||
!(self_end <= other.start || other_end <= self.start)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<limine::MemMapEntry> for MemoryRegion {
|
impl From<limine::MemMapEntry> for MemoryRegion {
|
||||||
fn from(entry: limine::MemMapEntry) -> Self {
|
fn from(entry: limine::MemMapEntry) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
||||||
|
|
@ -183,49 +183,6 @@ impl PhysicalMemoryManager {
|
||||||
pmm
|
pmm
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_pages(&mut self, count: usize) -> Option<(PhyAddr, usize)> {
|
|
||||||
let bin = count.next_power_of_two().trailing_zeros() as usize;
|
|
||||||
|
|
||||||
if let Some(chunk) = self.buddies[bin].pop_min() {
|
|
||||||
return unsafe { chunk.as_ref().phy().map(|phy| (phy, 1 << bin)) };
|
|
||||||
}
|
|
||||||
|
|
||||||
// the bin is empty, try to find a larger chunk and split it into two smaller chunks
|
|
||||||
let mut bin_offs = 1;
|
|
||||||
|
|
||||||
let chunk = loop {
|
|
||||||
if bin + bin_offs >= self.buddies.len() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.buddies[bin + bin_offs].pop_min() {
|
|
||||||
Some(chunk) => break chunk,
|
|
||||||
None => bin_offs += 1,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// the chunk is too big; split it into two smaller chunks recursively until we have a chunk of the desired size.
|
|
||||||
for bin_offs in (1..=bin_offs).rev() {
|
|
||||||
// the chunk is size 2^(bin + bin_offs), it can be split into two
|
|
||||||
// chunks of size 2^(bin + bin_offs - 1), where the first chunk
|
|
||||||
// starts at `chunk` and the second chunk starts at `chunk + 2^(bin
|
|
||||||
// + bin_offs - 1)`.
|
|
||||||
let buddy_index = PhysicalPageNode::page_index(chunk) + (1 << (bin + bin_offs - 1));
|
|
||||||
|
|
||||||
let buddy = PhysicalPageNode::new_from_page_index(buddy_index);
|
|
||||||
|
|
||||||
let None = self.buddies[bin + bin_offs - 1].insert_node(buddy) else {
|
|
||||||
panic!(
|
|
||||||
"Attempted to free a region that is already free: page_index = {}, count = {}",
|
|
||||||
buddy_index,
|
|
||||||
1 << (bin + bin_offs - 1)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe { chunk.as_ref().phy().map(|phy| (phy, 1 << bin)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn free_region(&mut self, page_index: usize, mut count: usize) {
|
fn free_region(&mut self, page_index: usize, mut count: usize) {
|
||||||
serial_println!(
|
serial_println!(
|
||||||
"Freeing region: page_index = {:#x}, count = {:#x}",
|
"Freeing region: page_index = {:#x}, count = {:#x}",
|
||||||
|
|
@ -352,13 +309,8 @@ impl Debug for PhysicalMemoryAllocator {
|
||||||
|
|
||||||
impl PhysicalMemoryAllocator {
|
impl PhysicalMemoryAllocator {
|
||||||
pub fn from_memory_map(memory_map: &[crate::boot::MemoryRegion]) -> Self {
|
pub fn from_memory_map(memory_map: &[crate::boot::MemoryRegion]) -> Self {
|
||||||
let mapped_non_usable_regions = memory_map
|
|
||||||
.iter()
|
|
||||||
.filter(|region| region.region_type.mapped_non_usable());
|
|
||||||
|
|
||||||
let usable_regions = memory_map
|
let usable_regions = memory_map
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
|
||||||
.filter(|region| region.region_type.is_usable());
|
.filter(|region| region.region_type.is_usable());
|
||||||
|
|
||||||
let mut pmm = PhysicalMemoryAllocator {
|
let mut pmm = PhysicalMemoryAllocator {
|
||||||
|
|
@ -416,219 +368,6 @@ unsafe impl Allocator for PanicingAllocator {
|
||||||
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: core::alloc::Layout) {}
|
unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: core::alloc::Layout) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A node for a red-black tree of free physical page chunks.
|
|
||||||
///
|
|
||||||
/// 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 {
|
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
||||||
use rbtree::UnsafeNode;
|
|
||||||
|
|
||||||
f.debug_struct("PhysicalPageNode")
|
|
||||||
.field("parent", &self.parent())
|
|
||||||
.field("left", &self.left())
|
|
||||||
.field("right", &self.right())
|
|
||||||
.field("color", &self.color())
|
|
||||||
.finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhysicalPageNode {
|
|
||||||
fn phy(&self) -> Option<PhyAddr> {
|
|
||||||
PhyAddr::from_hhdm_virt(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn page_index(this: NonNull<Self>) -> usize {
|
|
||||||
let phy = PhyAddr::from_hhdm_virt(VirtAddr::from(this));
|
|
||||||
phy.expect("PhysicalPageNode is not in HHDM").page_index() as usize
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_from_page_index(page_index: usize) -> NonNull<Self> {
|
|
||||||
let phy = PhyAddr::from_page_index(page_index);
|
|
||||||
let virt = phy.as_hhdm_virt();
|
|
||||||
let ptr = virt.as_mut::<Self>();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
ptr.write(Self::new_red());
|
|
||||||
}
|
|
||||||
|
|
||||||
NonNull::new(ptr).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_red() -> Self {
|
|
||||||
PhysicalPageNode(Cell::new(1 << 120))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn bits(&self) -> u128 {
|
|
||||||
self.0.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parent_bits(&self) -> u64 {
|
|
||||||
self.bits().get_bits(0..40) as u64
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent_bits(&self, parent: u64) {
|
|
||||||
self.0.update(|mut bits| {
|
|
||||||
bits.set_bits(0..40, parent as u128);
|
|
||||||
bits
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn left_bits(&self) -> u64 {
|
|
||||||
self.bits().get_bits(40..80) as u64
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_left_bits(&self, left: u64) {
|
|
||||||
self.0.update(|mut bits| {
|
|
||||||
bits.set_bits(40..80, left as u128);
|
|
||||||
bits
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn right_bits(&self) -> u64 {
|
|
||||||
self.bits().get_bits(80..120) as u64
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_right_bits(&self, right: u64) {
|
|
||||||
self.0.update(|mut bits| {
|
|
||||||
bits.set_bits(80..120, right as u128);
|
|
||||||
bits
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn color_bit(&self) -> bool {
|
|
||||||
self.bits().get_bit(120)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_color_bit(&self, color: bool) {
|
|
||||||
self.0.update(|mut bits| {
|
|
||||||
bits.set_bit(120, color);
|
|
||||||
bits
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A key for a red-black tree of free physical page chunks.
|
|
||||||
/// The key uses the address of the node as the key, which is unique and means
|
|
||||||
/// the key does not require any additional bits.
|
|
||||||
struct PhysicalPageNodeKey;
|
|
||||||
|
|
||||||
impl Debug for PhysicalPageNodeKey {
|
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
||||||
write!(f, "{:?}", self.phy())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PhysicalPageNodeKey {
|
|
||||||
fn from_page_index(page_index: usize) -> &'static Self {
|
|
||||||
let phy = PhyAddr::from_page_index(page_index);
|
|
||||||
let virt = phy.as_hhdm_virt();
|
|
||||||
let ptr = virt.as_ptr::<Self>();
|
|
||||||
|
|
||||||
unsafe { &*ptr }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn phy(&self) -> Option<PhyAddr> {
|
|
||||||
PhyAddr::from_hhdm_virt(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for PhysicalPageNodeKey {}
|
|
||||||
|
|
||||||
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() as usize)
|
|
||||||
.map(|n| PhyAddr::from_page_index(n.get()))
|
|
||||||
.map(PhyAddr::into_hhdm_virt)
|
|
||||||
.and_then(VirtAddr::into_nonnull)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn right(&self) -> Option<NonNull<Self>> {
|
|
||||||
NonZeroUsize::new(self.right_bits() as usize)
|
|
||||||
.map(|n| PhyAddr::from_page_index(n.get()))
|
|
||||||
.map(PhyAddr::into_hhdm_virt)
|
|
||||||
.and_then(VirtAddr::into_nonnull)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parent(&self) -> Option<NonNull<Self>> {
|
|
||||||
NonZeroUsize::new(self.parent_bits() as usize)
|
|
||||||
.map(|n| PhyAddr::from_page_index(n.get()))
|
|
||||||
.map(PhyAddr::into_hhdm_virt)
|
|
||||||
.and_then(VirtAddr::into_nonnull)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn key(&self) -> &Self::Key {
|
|
||||||
assert_eq!(
|
|
||||||
core::mem::size_of::<Self::Key>(),
|
|
||||||
0,
|
|
||||||
"PhysicalPageNodeKey must be zero-sized"
|
|
||||||
);
|
|
||||||
|
|
||||||
// SAFETY: The key is a zero-sized type, so we can transmute the
|
|
||||||
// reference to the node to a reference to the key.
|
|
||||||
unsafe { core::mem::transmute_copy::<&PhysicalPageNode, &PhysicalPageNodeKey>(&self) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn color(&self) -> rbtree::Color {
|
|
||||||
if self.color_bit() {
|
|
||||||
rbtree::Color::Red
|
|
||||||
} else {
|
|
||||||
rbtree::Color::Black
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_left(&self, left: Option<NonNull<Self>>) {
|
|
||||||
self.set_left_bits(left.map_or(0, |ptr| {
|
|
||||||
PhyAddr::from_hhdm_virt(VirtAddr::from(ptr))
|
|
||||||
.expect("PhysicalPageNode left pointer is not in HHDM")
|
|
||||||
.page_index()
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_right(&self, right: Option<NonNull<Self>>) {
|
|
||||||
self.set_right_bits(right.map_or(0, |ptr| {
|
|
||||||
PhyAddr::from_hhdm_virt(VirtAddr::from(ptr))
|
|
||||||
.expect("PhysicalPageNode right pointer is not in HHDM")
|
|
||||||
.page_index()
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_parent(&self, parent: Option<NonNull<Self>>) {
|
|
||||||
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) {
|
|
||||||
self.set_color_bit(color == rbtree::Color::Red);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub mod bump {
|
pub mod bump {
|
||||||
use core::{
|
use core::{
|
||||||
alloc::{Allocator, Layout},
|
alloc::{Allocator, Layout},
|
||||||
|
|
@ -1057,3 +796,216 @@ pub mod bump {
|
||||||
assert!(*x == 3);
|
assert!(*x == 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A node for a red-black tree of free physical page chunks.
|
||||||
|
///
|
||||||
|
/// 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 {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
use rbtree::UnsafeNode;
|
||||||
|
|
||||||
|
f.debug_struct("PhysicalPageNode")
|
||||||
|
.field("parent", &self.parent())
|
||||||
|
.field("left", &self.left())
|
||||||
|
.field("right", &self.right())
|
||||||
|
.field("color", &self.color())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhysicalPageNode {
|
||||||
|
fn phy(&self) -> Option<PhyAddr> {
|
||||||
|
PhyAddr::from_hhdm_virt(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page_index(this: NonNull<Self>) -> usize {
|
||||||
|
let phy = PhyAddr::from_hhdm_virt(VirtAddr::from(this));
|
||||||
|
phy.expect("PhysicalPageNode is not in HHDM").page_index() as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_from_page_index(page_index: usize) -> NonNull<Self> {
|
||||||
|
let phy = PhyAddr::from_page_index(page_index);
|
||||||
|
let virt = phy.as_hhdm_virt();
|
||||||
|
let ptr = virt.as_mut::<Self>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ptr.write(Self::new_red());
|
||||||
|
}
|
||||||
|
|
||||||
|
NonNull::new(ptr).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_red() -> Self {
|
||||||
|
PhysicalPageNode(Cell::new(1 << 120))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bits(&self) -> u128 {
|
||||||
|
self.0.get()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent_bits(&self) -> u64 {
|
||||||
|
self.bits().get_bits(0..40) as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent_bits(&self, parent: u64) {
|
||||||
|
self.0.update(|mut bits| {
|
||||||
|
bits.set_bits(0..40, parent as u128);
|
||||||
|
bits
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn left_bits(&self) -> u64 {
|
||||||
|
self.bits().get_bits(40..80) as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_left_bits(&self, left: u64) {
|
||||||
|
self.0.update(|mut bits| {
|
||||||
|
bits.set_bits(40..80, left as u128);
|
||||||
|
bits
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn right_bits(&self) -> u64 {
|
||||||
|
self.bits().get_bits(80..120) as u64
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_right_bits(&self, right: u64) {
|
||||||
|
self.0.update(|mut bits| {
|
||||||
|
bits.set_bits(80..120, right as u128);
|
||||||
|
bits
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn color_bit(&self) -> bool {
|
||||||
|
self.bits().get_bit(120)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_color_bit(&self, color: bool) {
|
||||||
|
self.0.update(|mut bits| {
|
||||||
|
bits.set_bit(120, color);
|
||||||
|
bits
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A key for a red-black tree of free physical page chunks.
|
||||||
|
/// The key uses the address of the node as the key, which is unique and means
|
||||||
|
/// the key does not require any additional bits.
|
||||||
|
struct PhysicalPageNodeKey;
|
||||||
|
|
||||||
|
impl Debug for PhysicalPageNodeKey {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(f, "{:?}", self.phy())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PhysicalPageNodeKey {
|
||||||
|
fn from_page_index(page_index: usize) -> &'static Self {
|
||||||
|
let phy = PhyAddr::from_page_index(page_index);
|
||||||
|
let virt = phy.as_hhdm_virt();
|
||||||
|
let ptr = virt.as_ptr::<Self>();
|
||||||
|
|
||||||
|
unsafe { &*ptr }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn phy(&self) -> Option<PhyAddr> {
|
||||||
|
PhyAddr::from_hhdm_virt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for PhysicalPageNodeKey {}
|
||||||
|
|
||||||
|
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() as usize)
|
||||||
|
.map(|n| PhyAddr::from_page_index(n.get()))
|
||||||
|
.map(PhyAddr::into_hhdm_virt)
|
||||||
|
.and_then(VirtAddr::into_nonnull)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn right(&self) -> Option<NonNull<Self>> {
|
||||||
|
NonZeroUsize::new(self.right_bits() as usize)
|
||||||
|
.map(|n| PhyAddr::from_page_index(n.get()))
|
||||||
|
.map(PhyAddr::into_hhdm_virt)
|
||||||
|
.and_then(VirtAddr::into_nonnull)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parent(&self) -> Option<NonNull<Self>> {
|
||||||
|
NonZeroUsize::new(self.parent_bits() as usize)
|
||||||
|
.map(|n| PhyAddr::from_page_index(n.get()))
|
||||||
|
.map(PhyAddr::into_hhdm_virt)
|
||||||
|
.and_then(VirtAddr::into_nonnull)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key(&self) -> &Self::Key {
|
||||||
|
assert_eq!(
|
||||||
|
core::mem::size_of::<Self::Key>(),
|
||||||
|
0,
|
||||||
|
"PhysicalPageNodeKey must be zero-sized"
|
||||||
|
);
|
||||||
|
|
||||||
|
// SAFETY: The key is a zero-sized type, so we can transmute the
|
||||||
|
// reference to the node to a reference to the key.
|
||||||
|
unsafe { core::mem::transmute_copy::<&PhysicalPageNode, &PhysicalPageNodeKey>(&self) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn color(&self) -> rbtree::Color {
|
||||||
|
if self.color_bit() {
|
||||||
|
rbtree::Color::Red
|
||||||
|
} else {
|
||||||
|
rbtree::Color::Black
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_left(&self, left: Option<NonNull<Self>>) {
|
||||||
|
self.set_left_bits(left.map_or(0, |ptr| {
|
||||||
|
PhyAddr::from_hhdm_virt(VirtAddr::from(ptr))
|
||||||
|
.expect("PhysicalPageNode left pointer is not in HHDM")
|
||||||
|
.page_index()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_right(&self, right: Option<NonNull<Self>>) {
|
||||||
|
self.set_right_bits(right.map_or(0, |ptr| {
|
||||||
|
PhyAddr::from_hhdm_virt(VirtAddr::from(ptr))
|
||||||
|
.expect("PhysicalPageNode right pointer is not in HHDM")
|
||||||
|
.page_index()
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_parent(&self, parent: Option<NonNull<Self>>) {
|
||||||
|
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) {
|
||||||
|
self.set_color_bit(color == rbtree::Color::Red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue