Skip to main content

strat9_kernel/memory/
block.rs

1//! Block-oriented physical memory handles.
2
3use core::marker::PhantomData;
4use x86_64::PhysAddr;
5
6use crate::memory::{frame::PAGE_SIZE, zone::MAX_ORDER};
7
8/// Lightweight identifier for a physical block.
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct BlockHandle {
11    /// Base physical address of the block.
12    pub base: PhysAddr,
13    /// Buddy order of the block.
14    pub order: u8,
15}
16
17impl BlockHandle {
18    /// Creates a new block handle.
19    pub fn new(base: PhysAddr, order: u8) -> Self {
20        Self { base, order }
21    }
22
23    /// Returns the block size in bytes.
24    pub fn size_bytes(&self) -> u64 {
25        PAGE_SIZE.checked_shl(self.order as u32).unwrap_or(0)
26    }
27
28    /// Returns the number of 4 KiB pages covered by the block.
29    pub fn page_count(&self) -> u64 {
30        1u64.checked_shl(self.order as u32).unwrap_or(0)
31    }
32
33    /// Returns `true` when the handle is aligned and within the supported buddy range.
34    pub fn is_valid(&self) -> bool {
35        let size = self.size_bytes();
36        size != 0 && self.order <= MAX_ORDER as u8 && self.base.is_aligned(size)
37    }
38}
39
40/// State marker for a block reserved by the buddy allocator.
41#[derive(Debug)]
42pub struct BuddyReserved;
43
44/// State marker for an exclusively owned block.
45#[derive(Debug)]
46pub struct Exclusive;
47
48/// State marker for an exclusively owned mapped block.
49#[derive(Debug)]
50pub struct MappedExclusive;
51
52/// State marker for a shared mapped block.
53#[derive(Debug)]
54pub struct MappedShared;
55
56/// State marker for a block released back to the buddy layer.
57#[derive(Debug)]
58pub struct Released;
59
60/// Ephemeral typed handle for local state transitions.
61#[derive(Debug)]
62pub struct PhysBlock<S> {
63    handle: BlockHandle,
64    _state: PhantomData<S>,
65}
66
67impl<S> PhysBlock<S> {
68    /// Returns the underlying block handle.
69    pub fn handle(&self) -> BlockHandle {
70        self.handle
71    }
72
73    /// Returns the base physical address of the block.
74    pub fn base(&self) -> PhysAddr {
75        self.handle.base
76    }
77
78    /// Returns the buddy order of the block.
79    pub fn order(&self) -> u8 {
80        self.handle.order
81    }
82
83    /// Creates a typed block from a raw handle.
84    pub(crate) fn from_handle(handle: BlockHandle) -> Self {
85        Self {
86            handle,
87            _state: PhantomData,
88        }
89    }
90}
91
92impl PhysBlock<BuddyReserved> {
93    /// Transitions a reserved block into exclusive ownership.
94    pub(crate) fn into_exclusive(self) -> PhysBlock<Exclusive> {
95        PhysBlock::from_handle(self.handle)
96    }
97}
98
99impl PhysBlock<Exclusive> {
100    /// Marks the block as mapped while remaining exclusive.
101    pub(crate) fn into_mapped(self) -> PhysBlock<MappedExclusive> {
102        PhysBlock::from_handle(self.handle)
103    }
104
105    /// Releases the block to the buddy-facing state.
106    pub(crate) fn into_released(self) -> PhysBlock<Released> {
107        PhysBlock::from_handle(self.handle)
108    }
109}
110
111impl PhysBlock<MappedExclusive> {
112    /// Transitions a mapped exclusive block into a shared mapped block.
113    pub(crate) fn into_shared(self) -> PhysBlock<MappedShared> {
114        PhysBlock::from_handle(self.handle)
115    }
116
117    /// Transitions a mapped exclusive block back to an unmapped exclusive block.
118    pub(crate) fn into_unmapped(self) -> PhysBlock<Exclusive> {
119        PhysBlock::from_handle(self.handle)
120    }
121}
122
123impl PhysBlock<MappedShared> {
124    /// Transitions a shared mapped block back to a mapped exclusive block.
125    pub(crate) fn into_exclusive_mapped(self) -> PhysBlock<MappedExclusive> {
126        PhysBlock::from_handle(self.handle)
127    }
128
129    /// Rebuilds the shared typed handle after an ownership-layer check.
130    pub(crate) fn still_shared(self) -> PhysBlock<MappedShared> {
131        self
132    }
133}
134
135impl PhysBlock<Released> {
136    /// Consumes the released block and returns its raw handle.
137    pub(crate) fn into_handle(self) -> BlockHandle {
138        self.handle
139    }
140}