Skip to main content

arcbox_hypervisor/
memory.rs

1//! Guest memory types and utilities.
2
3use std::fmt;
4
5/// A guest physical address.
6#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
7pub struct GuestAddress(pub u64);
8
9impl GuestAddress {
10    /// Creates a new guest address.
11    #[must_use]
12    pub const fn new(addr: u64) -> Self {
13        Self(addr)
14    }
15
16    /// Returns the raw address value.
17    #[must_use]
18    pub const fn raw(&self) -> u64 {
19        self.0
20    }
21
22    /// Returns the address offset by the given amount.
23    #[must_use]
24    pub const fn offset(&self, offset: u64) -> Self {
25        Self(self.0 + offset)
26    }
27
28    /// Aligns the address up to the given alignment.
29    #[must_use]
30    pub const fn align_up(&self, alignment: u64) -> Self {
31        let mask = alignment - 1;
32        Self((self.0 + mask) & !mask)
33    }
34
35    /// Aligns the address down to the given alignment.
36    #[must_use]
37    pub const fn align_down(&self, alignment: u64) -> Self {
38        let mask = alignment - 1;
39        Self(self.0 & !mask)
40    }
41
42    /// Checks if the address is aligned to the given alignment.
43    #[must_use]
44    pub const fn is_aligned(&self, alignment: u64) -> bool {
45        self.0 & (alignment - 1) == 0
46    }
47}
48
49impl fmt::Display for GuestAddress {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        write!(f, "{:#x}", self.0)
52    }
53}
54
55impl From<u64> for GuestAddress {
56    fn from(addr: u64) -> Self {
57        Self(addr)
58    }
59}
60
61impl From<GuestAddress> for u64 {
62    fn from(addr: GuestAddress) -> Self {
63        addr.0
64    }
65}
66
67/// A contiguous region of guest memory.
68#[derive(Debug, Clone)]
69pub struct MemoryRegion {
70    /// Guest physical address of the region start.
71    pub guest_addr: GuestAddress,
72    /// Size of the region in bytes.
73    pub size: u64,
74    /// Host virtual address (if mapped).
75    pub host_addr: Option<*mut u8>,
76    /// Whether the region is read-only.
77    pub read_only: bool,
78}
79
80impl MemoryRegion {
81    /// Creates a new memory region.
82    #[must_use]
83    pub const fn new(guest_addr: GuestAddress, size: u64) -> Self {
84        Self {
85            guest_addr,
86            size,
87            host_addr: None,
88            read_only: false,
89        }
90    }
91
92    /// Returns the end address of the region (exclusive).
93    #[must_use]
94    pub const fn end(&self) -> GuestAddress {
95        GuestAddress(self.guest_addr.0 + self.size)
96    }
97
98    /// Checks if the region contains the given address.
99    #[must_use]
100    pub const fn contains(&self, addr: GuestAddress) -> bool {
101        addr.0 >= self.guest_addr.0 && addr.0 < self.guest_addr.0 + self.size
102    }
103
104    /// Checks if the region contains the given range.
105    #[must_use]
106    pub const fn contains_range(&self, addr: GuestAddress, size: u64) -> bool {
107        addr.0 >= self.guest_addr.0 && addr.0 + size <= self.guest_addr.0 + self.size
108    }
109}
110
111// Safety: The host_addr pointer, if present, points to memory that is valid
112// for the lifetime of the VM and is properly synchronized.
113unsafe impl Send for MemoryRegion {}
114unsafe impl Sync for MemoryRegion {}
115
116/// Standard page size (4KB).
117pub const PAGE_SIZE: u64 = 4096;
118
119/// Large page size (2MB).
120pub const LARGE_PAGE_SIZE: u64 = 2 * 1024 * 1024;
121
122/// Huge page size (1GB).
123pub const HUGE_PAGE_SIZE: u64 = 1024 * 1024 * 1024;