1use ax_errno::AxResult;
2use ax_memory_addr::{PhysAddr, VirtAddr};
3
4use crate::{PAGE_SIZE, UsageKind, global_allocator};
5
6#[derive(Debug)]
10pub struct GlobalPage {
11 start_vaddr: VirtAddr,
12 num_pages: usize,
13}
14
15impl GlobalPage {
16 pub fn alloc() -> AxResult<Self> {
18 let vaddr = global_allocator()
19 .alloc_pages(1, PAGE_SIZE, UsageKind::Global)
20 .map_err(|_| ax_errno::AxError::NoMemory)?;
21 Ok(Self {
22 start_vaddr: vaddr.into(),
23 num_pages: 1,
24 })
25 }
26
27 pub fn alloc_zero() -> AxResult<Self> {
29 let mut p = Self::alloc()?;
30 p.zero();
31 Ok(p)
32 }
33
34 pub fn alloc_contiguous(num_pages: usize, alignment: usize) -> AxResult<Self> {
36 let vaddr = global_allocator()
37 .alloc_pages(num_pages, alignment, UsageKind::Global)
38 .map_err(|_| ax_errno::AxError::NoMemory)?;
39 Ok(Self {
40 start_vaddr: vaddr.into(),
41 num_pages,
42 })
43 }
44
45 pub fn start_vaddr(&self) -> VirtAddr {
47 self.start_vaddr
48 }
49
50 pub fn start_paddr<F>(&self, virt_to_phys: F) -> PhysAddr
52 where
53 F: FnOnce(VirtAddr) -> PhysAddr,
54 {
55 virt_to_phys(self.start_vaddr)
56 }
57
58 pub fn size(&self) -> usize {
60 self.num_pages * PAGE_SIZE
61 }
62
63 pub fn as_ptr(&self) -> *const u8 {
65 self.start_vaddr.as_ptr()
66 }
67
68 pub fn as_mut_ptr(&mut self) -> *mut u8 {
70 self.start_vaddr.as_mut_ptr()
71 }
72
73 pub fn fill(&mut self, byte: u8) {
75 unsafe { core::ptr::write_bytes(self.as_mut_ptr(), byte, self.size()) }
76 }
77
78 pub fn zero(&mut self) {
80 self.fill(0)
81 }
82
83 pub fn as_slice(&self) -> &[u8] {
85 unsafe { core::slice::from_raw_parts(self.as_ptr(), self.size()) }
86 }
87
88 pub fn as_slice_mut(&mut self) -> &mut [u8] {
90 unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.size()) }
91 }
92}
93
94impl Drop for GlobalPage {
95 fn drop(&mut self) {
96 global_allocator().dealloc_pages(
97 self.start_vaddr.into(),
98 self.num_pages,
99 UsageKind::Global,
100 );
101 }
102}