1use core::marker::PhantomData;
2use core::num::NonZero;
3use core::ptr::addr_of;
4use crate::memory::{Frames, RawFrame};
5use crate::sync::RwSpinlock;
6use crate::allocator::AllocError;
7
8#[inline]
12pub const fn highmem() -> DynPmm<'static, true> {
13 DynPmm::from(&crate::bridge::memory::GLOBAL_HIGHMEM)
14}
15
16#[inline]
21pub const fn dmamem() -> DynPmm<'static, true> {
22 DynPmm::from(&crate::bridge::memory::GLOBAL_DMA)
23}
24
25#[inline]
27pub const fn highmem_zero() -> DynPmm<'static, true> {
28 struct Zero;
29
30 unsafe impl Pmm<true> for Zero {
31 fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> {
32 let mut frame = highmem().allocate_one()?;
33 frame.write_filled(0);
34 Ok(Frames::into_raw(frame).0.start)
35 }
36
37 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
38 let mut frames = highmem().allocate(count)?;
39 frames.write_filled(0);
40 Ok(Frames::into_raw(frames).0.start)
41 }
42
43 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
44 let mut frames = highmem().allocate_at(at, count)?;
45 frames.write_filled(0);
46 Ok(Frames::into_raw(frames).0.start)
47 }
48
49 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
50 unsafe { highmem().deallocate_raw(base, count) }
51 }
52 }
53
54 DynPmm::from(&Zero)
55}
56
57pub unsafe trait Pmm<const RAM_ONLY: bool>: Sync + Sized { fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> { self.allocate_raw(const { NonZero::new(1).unwrap() }) }
76
77 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError>;
85
86 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError>;
87
88 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>);
94}
95
96unsafe impl<'a, const RAM_ONLY: bool, T: Pmm<RAM_ONLY> + ?Sized> Pmm<RAM_ONLY> for &'a T {
97 fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> {
98 (**self).allocate_one_raw()
99 }
100
101 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
102 (**self).allocate_raw(count)
103 }
104
105 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
106 (**self).allocate_raw_at(at, count)
107 }
108
109 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
110 (**self).deallocate_raw(base, count)
111 }
112}
113
114#[doc(hidden)]
115pub struct GlobalAllocator {
116 pub __rwlock: RwSpinlock<Option<DynPmm<'static, true>>>
117}
118
119unsafe impl Pmm<true> for GlobalAllocator {
120 #[inline]
121 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
122 self.__rwlock.read()
123 .expect("no global Pmm")
124 .allocate_raw(count)
125 }
126
127 #[inline]
128 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
129 self.__rwlock.read()
130 .expect("no global Pmm")
131 .allocate_raw_at(at, count)
132 }
133
134 #[inline]
135 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
136 self.__rwlock.read()
137 .expect("no global Pmm")
138 .deallocate_raw(base, count)
139 }
140}
141
142#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct DynPmm<'a, const RAM: bool> {
145 data: *const (), allocate_raw_at: unsafe fn(*const (), at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError>,
147 allocate_one_raw: unsafe fn(*const ()) -> Result<RawFrame, AllocError>,
148 allocate_raw: unsafe fn(*const (), count: NonZero<usize>) -> Result<RawFrame, AllocError>,
149 deallocate_raw: unsafe fn(*const (), base: RawFrame, count: NonZero<usize>),
150 _phantom: PhantomData<&'a ()>,
151}
152
153unsafe impl<const RAM: bool> Sync for DynPmm<'_, RAM> {}
154unsafe impl<const RAM: bool> Send for DynPmm<'_, RAM> {}
155
156impl<'a, const RAM: bool, T: Pmm<RAM>> const From<&'a T> for DynPmm<'a, RAM> {
157 fn from(value: &'a T) -> Self {
158 DynPmm {
159 data: addr_of!(*value).cast(),
160 allocate_raw_at: unsafe { core::mem::transmute(T::allocate_raw_at as fn(_, _, _) -> _) },
161 allocate_one_raw: unsafe { core::mem::transmute(T::allocate_one_raw as fn(_) -> _) },
162 allocate_raw: unsafe { core::mem::transmute(T::allocate_raw as fn(_, _) -> _) },
163 deallocate_raw: unsafe { core::mem::transmute(T::deallocate_raw as unsafe fn(_, _, _)) },
164 _phantom: PhantomData,
165 }
166 }
167}
168
169impl<'a, const RAM: bool> DynPmm<'a, RAM> {
170 pub const fn into(self) -> DynPmm<'a, false> {
171 DynPmm::<false> {
172 ..self
173 }
174 }
175
176 pub fn allocate_one(&self) -> Result<Frames<RAM>, AllocError> where Self: 'static {
182 let base = self.allocate_one_raw()?;
183 Ok(unsafe {
184 Frames::from_raw(
185 base .. (base + 1usize),
186 *self,
187 )
188 })
189 }
190
191 pub fn allocate(&self, count: NonZero<usize>) -> Result<Frames<RAM>, AllocError> where Self: 'static {
199 let base = self.allocate_raw(count)?;
200 Ok(unsafe {
201 Frames::from_raw(
202 base .. (base + count.get()),
203 *self,
204 )
205 })
206 }
207
208 pub fn allocate_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<Frames<RAM>, AllocError> where Self: 'static {
209 let base = self.allocate_raw_at(at, count)?;
210 Ok(unsafe {
211 Frames::from_raw(
212 base .. (base + count.get()),
213 *self,
214 )
215 })
216 }
217}
218
219unsafe impl<const RAM: bool> Pmm<RAM> for DynPmm<'_, RAM> {
220 #[inline]
221 fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> {
222 unsafe { (self.allocate_one_raw)(self.data) }
223 }
224
225 #[inline]
226 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
227 unsafe { (self.allocate_raw)(self.data, count) }
228 }
229
230 #[inline]
231 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
232 unsafe { (self.allocate_raw_at)(self.data, at, count) }
233 }
234
235 #[inline]
236 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
237 unsafe { (self.deallocate_raw)(self.data, base, count) }
238 }
239}