kernel: move pmm code around
This commit is contained in:
parent
238e822751
commit
80ffe15e6c
|
|
@ -368,6 +368,219 @@ unsafe impl Allocator for PanicingAllocator {
|
|||
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 {
|
||||
use core::{
|
||||
alloc::{Allocator, Layout},
|
||||
|
|
@ -796,216 +1009,3 @@ pub mod bump {
|
|||
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