1use core::marker::PhantomData;
2use core::num::NonZero;
3use crate::memory::{Frames, RawFrame};
4use crate::sync::RwSpinlock;
5use crate::allocator::AllocError;
6
7#[inline]
13#[must_use]
14pub const fn highmem() -> DynPmm<'static, true> {
15 DynPmm::from(&crate::bridge::memory::GLOBAL_HIGHMEM)
16}
17
18#[inline]
25#[must_use]
26pub const fn dmamem() -> DynPmm<'static, true> {
27 DynPmm::from(&crate::bridge::memory::GLOBAL_DMA)
28}
29
30#[inline]
32#[must_use]
33pub const fn highmem_zero() -> DynPmm<'static, true> {
34 struct Zero;
35
36 unsafe impl Pmm<true> for Zero {
38 fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> {
39 let mut frame = highmem().allocate_one()?;
40 frame.write_filled(0);
41 Ok(Frames::into_raw(frame).0.start)
42 }
43
44 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
45 let mut frames = highmem().allocate(count)?;
46 frames.write_filled(0);
47 Ok(Frames::into_raw(frames).0.start)
48 }
49
50 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
51 let mut frames = highmem().allocate_at(at, count)?;
52 frames.write_filled(0);
53 Ok(Frames::into_raw(frames).0.start)
54 }
55
56 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
57 unsafe { highmem().deallocate_raw(base, count) }
59 }
60 }
61
62 DynPmm::from(&Zero)
63}
64
65pub unsafe trait Pmm<const RAM_ONLY: bool>: Sync + Sized { #[must_use = "memory will be leaked unless the frame is explicitly deallocated"]
84 fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> { self.allocate_raw(const { NonZero::new(1).unwrap() }) }
85
86 #[must_use = "memory will be leaked unless the frame is explicitly deallocated"]
94 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError>;
95
96 #[must_use = "memory will be leaked unless the frame is explicitly deallocated"]
104 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError>;
105
106 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>);
112}
113
114unsafe impl<const RAM_ONLY: bool, T: Pmm<RAM_ONLY>> Pmm<RAM_ONLY> for &T {
116 fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> {
117 (**self).allocate_one_raw()
118 }
119
120 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
121 (**self).allocate_raw(count)
122 }
123
124 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
125 (**self).allocate_raw_at(at, count)
126 }
127
128 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
129 unsafe { (**self).deallocate_raw(base, count) }
131 }
132}
133
134#[derive(Debug)]
135#[doc(hidden)]
136pub struct GlobalAllocator {
137 #[doc(hidden)]
138 pub __rwlock: RwSpinlock<Option<DynPmm<'static, true>>>
139}
140
141unsafe impl Pmm<true> for GlobalAllocator {
143 #[inline]
144 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
145 self.__rwlock.read()
146 .expect("no global Pmm")
147 .allocate_raw(count)
148 }
149
150 #[inline]
151 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
152 self.__rwlock.read()
153 .expect("no global Pmm")
154 .allocate_raw_at(at, count)
155 }
156
157 #[inline]
158 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
159 let pmm = self.__rwlock.read()
160 .expect("no global Pmm");
161
162 unsafe { pmm.deallocate_raw(base, count) }
164 }
165}
166
167#[derive(Copy, Clone, Debug)] #[repr(C)] pub struct DynPmm<'a, const RAM: bool> {
178 data: *const (), allocate_raw_at: unsafe fn(*const (), at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError>,
180 allocate_one_raw: unsafe fn(*const ()) -> Result<RawFrame, AllocError>,
181 allocate_raw: unsafe fn(*const (), count: NonZero<usize>) -> Result<RawFrame, AllocError>,
182 deallocate_raw: unsafe fn(*const (), base: RawFrame, count: NonZero<usize>),
183 _phantom: PhantomData<&'a ()>,
184}
185
186unsafe impl<const RAM: bool> Sync for DynPmm<'_, RAM> {}
188unsafe impl<const RAM: bool> Send for DynPmm<'_, RAM> {}
190
191const impl<'a, const RAM: bool, T: Pmm<RAM>> From<&'a T> for DynPmm<'a, RAM> {
192 fn from(value: &'a T) -> Self {
193 #[inline]
198 unsafe fn allocate_raw_at_shim<const RAM: bool, T: Pmm<RAM>>(this: *const (), at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
199 T::allocate_raw_at(unsafe { &*this.cast() }, at, count)
201 }
202
203 #[inline]
208 unsafe fn allocate_one_raw_shim<const RAM: bool, T: Pmm<RAM>>(this: *const ()) -> Result<RawFrame, AllocError> {
209 T::allocate_one_raw(unsafe { &*this.cast() })
211 }
212
213 #[inline]
218 unsafe fn allocate_raw_shim<const RAM: bool, T: Pmm<RAM>>(this: *const (), count: NonZero<usize>) -> Result<RawFrame, AllocError> {
219 T::allocate_raw(unsafe { &*this.cast() }, count)
221 }
222
223 #[inline]
227 unsafe fn deallocate_raw_shim<const RAM: bool, T: Pmm<RAM>>(this: *const (), base: RawFrame, count: NonZero<usize>) {
228 let this = unsafe { &*this.cast() };
230 unsafe { T::deallocate_raw(this, base, count) }
232 }
233
234 DynPmm {
235 data: core::ptr::from_ref(value).cast(),
236 allocate_raw_at: allocate_raw_at_shim::<RAM, T>,
237 allocate_one_raw: allocate_one_raw_shim::<RAM, T>,
238 allocate_raw: allocate_raw_shim::<RAM, T>,
239 deallocate_raw: deallocate_raw_shim::<RAM, T>,
240 _phantom: PhantomData,
241 }
242 }
243}
244
245impl<'a, const RAM: bool> DynPmm<'a, RAM> {
246 #[must_use]
248 #[expect(clippy::unnecessary_struct_initialization, reason = "false positive since it changes type param")]
249 pub const fn into(self) -> DynPmm<'a, false> {
250 DynPmm::<false> {
251 ..self
252 }
253 }
254
255 pub fn allocate_one(&self) -> Result<Frames<RAM>, AllocError> where Self: 'static {
261 let base = self.allocate_one_raw()?;
262 Ok(unsafe {
264 Frames::from_raw(
265 base .. (base + 1usize),
266 *self,
267 )
268 })
269 }
270
271 pub fn allocate(&self, count: NonZero<usize>) -> Result<Frames<RAM>, AllocError> where Self: 'static {
279 let base = self.allocate_raw(count)?;
280 Ok(unsafe {
282 Frames::from_raw(
283 base .. (base + count.get()),
284 *self,
285 )
286 })
287 }
288
289 pub fn allocate_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<Frames<RAM>, AllocError> where Self: 'static {
297 let base = self.allocate_raw_at(at, count)?;
298 Ok(unsafe {
300 Frames::from_raw(
301 base .. (base + count.get()),
302 *self,
303 )
304 })
305 }
306}
307
308unsafe impl<const RAM: bool> Pmm<RAM> for DynPmm<'_, RAM> {
311 #[inline]
312 fn allocate_one_raw(&self) -> Result<RawFrame, AllocError> {
313 unsafe { (self.allocate_one_raw)(self.data) }
315 }
316
317 #[inline]
318 fn allocate_raw(&self, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
319 unsafe { (self.allocate_raw)(self.data, count) }
321 }
322
323 #[inline]
324 fn allocate_raw_at(&self, at: RawFrame, count: NonZero<usize>) -> Result<RawFrame, AllocError> {
325 unsafe { (self.allocate_raw_at)(self.data, at, count) }
327 }
328
329 #[inline]
330 unsafe fn deallocate_raw(&self, base: RawFrame, count: NonZero<usize>) {
331 unsafe { (self.deallocate_raw)(self.data, base, count) }
334 }
335}