Skip to main content

ax_alloc/
page.rs

1use ax_memory_addr::{PhysAddr, VirtAddr};
2
3use crate::{AllocResult, PAGE_SIZE, UsageKind, global_allocator};
4
5/// A RAII wrapper of contiguous 4K-sized pages.
6///
7/// It will automatically deallocate the pages when dropped.
8#[derive(Debug)]
9pub struct GlobalPage {
10    start_vaddr: VirtAddr,
11    num_pages: usize,
12}
13
14impl GlobalPage {
15    /// Allocate one 4K-sized page.
16    pub fn alloc() -> AllocResult<Self> {
17        let vaddr = global_allocator().alloc_pages(1, PAGE_SIZE, UsageKind::Global)?;
18        Ok(Self {
19            start_vaddr: vaddr.into(),
20            num_pages: 1,
21        })
22    }
23
24    /// Allocate one 4K-sized page and fill with zero.
25    pub fn alloc_zero() -> AllocResult<Self> {
26        let mut p = Self::alloc()?;
27        p.zero();
28        Ok(p)
29    }
30
31    /// Allocate contiguous 4K-sized pages.
32    pub fn alloc_contiguous(num_pages: usize, alignment: usize) -> AllocResult<Self> {
33        let vaddr = global_allocator().alloc_pages(num_pages, alignment, UsageKind::Global)?;
34        Ok(Self {
35            start_vaddr: vaddr.into(),
36            num_pages,
37        })
38    }
39
40    /// Get the start virtual address of this page.
41    pub fn start_vaddr(&self) -> VirtAddr {
42        self.start_vaddr
43    }
44
45    /// Get the start physical address of this page.
46    pub fn start_paddr<F>(&self, virt_to_phys: F) -> PhysAddr
47    where
48        F: FnOnce(VirtAddr) -> PhysAddr,
49    {
50        virt_to_phys(self.start_vaddr)
51    }
52
53    /// Get the total size (in bytes) of these page(s).
54    pub fn size(&self) -> usize {
55        self.num_pages * PAGE_SIZE
56    }
57
58    /// Convert to a raw pointer.
59    pub fn as_ptr(&self) -> *const u8 {
60        self.start_vaddr.as_ptr()
61    }
62
63    /// Convert to a mutable raw pointer.
64    pub fn as_mut_ptr(&mut self) -> *mut u8 {
65        self.start_vaddr.as_mut_ptr()
66    }
67
68    /// Fill `self` with `byte`.
69    pub fn fill(&mut self, byte: u8) {
70        unsafe { core::ptr::write_bytes(self.as_mut_ptr(), byte, self.size()) }
71    }
72
73    /// Fill `self` with zero.
74    pub fn zero(&mut self) {
75        self.fill(0)
76    }
77
78    /// Forms a slice that can read data.
79    pub fn as_slice(&self) -> &[u8] {
80        unsafe { core::slice::from_raw_parts(self.as_ptr(), self.size()) }
81    }
82
83    /// Forms a mutable slice that can write data.
84    pub fn as_slice_mut(&mut self) -> &mut [u8] {
85        unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.size()) }
86    }
87}
88
89impl Drop for GlobalPage {
90    fn drop(&mut self) {
91        global_allocator().dealloc_pages(
92            self.start_vaddr.into(),
93            self.num_pages,
94            UsageKind::Global,
95        );
96    }
97}