kernel/vm/
vmem.rs

1/// Represents a mapping between physical and virtual memory areas.
2///
3/// This structure defines the relationship between a physical memory area
4/// and its corresponding virtual memory area in the kernel's memory management system.
5///
6/// # Fields
7///
8/// * `pmarea` - The physical memory area that is being mapped
9/// * `vmarea` - The virtual memory area where the physical memory is mapped to
10#[derive(Debug, Clone, Copy, PartialEq)]
11pub struct VirtualMemoryMap {
12    pub pmarea: MemoryArea,
13    pub vmarea: MemoryArea,
14    pub permissions: usize,
15    pub is_shared: bool,
16}
17
18impl VirtualMemoryMap {
19    /// Creates a new virtual memory map with the given physical and virtual memory areas.
20    /// 
21    /// # Arguments
22    /// * `pmarea` - The physical memory area to map
23    /// * `vmarea` - The virtual memory area to map to
24    /// * `permissions` - The permissions to set for the virtual memory area
25    /// * `is_shared` - Whether this memory map should be shared between tasks
26    /// 
27    /// # Returns
28    /// A new virtual memory map with the given physical and virtual memory areas.
29    pub fn new(pmarea: MemoryArea, vmarea: MemoryArea, permissions: usize, is_shared: bool) -> Self {
30        VirtualMemoryMap {
31            pmarea,
32            vmarea,
33            permissions,
34            is_shared,
35        }
36    }
37
38    /// Returns the physical address corresponding to the given virtual address.
39    ///
40    /// # Arguments
41    /// * `vaddr` - The virtual address to translate
42    /// 
43    /// # Returns
44    /// The physical address corresponding to the given virtual address, if it exists.
45    /// If the virtual address is not part of the memory map, `None` is returned.
46    pub fn get_paddr(&self, vaddr: usize) -> Option<usize> {
47        if self.vmarea.start <= vaddr && vaddr <= self.vmarea.end {
48            Some(self.pmarea.start + (vaddr - self.vmarea.start))
49        } else {
50            None
51        }
52    }
53}
54
55#[derive(Debug, Clone, Copy, PartialEq)]
56pub struct MemoryArea {
57    pub start: usize,
58    pub end: usize,
59}
60
61impl MemoryArea {
62    /// Creates a new memory area with the given start and end addresses
63    pub fn new(start: usize, end: usize) -> Self {
64        Self { start, end }
65    }
66    
67    /// Creates a new memory area from a pointer and size
68    pub fn from_ptr(ptr: *const u8, size: usize) -> Self {
69        let start = ptr as usize;
70        let end = if size > 0 { start + size - 1 } else { start };
71        Self { start, end }
72    }
73    
74    /// Returns the size of the memory area in bytes
75    pub fn size(&self) -> usize {
76        if self.start > self.end {
77            panic!("Invalid memory area: start > end: {:#x} > {:#x}", self.start, self.end);
78        }
79        self.end - self.start + 1
80    }
81    
82    /// Returns a slice reference to the memory area
83    /// 
84    /// # Safety
85    /// This function assumes that the start and end of MemoryArea point to valid memory ranges.
86    /// If not, undefined behavior may occur.
87    /// Therefore, make sure that MemoryArea points to a valid range before using this function.
88    /// 
89    /// # Returns
90    /// 
91    /// A slice reference to the memory area
92    ///
93    pub unsafe fn as_slice(&self) -> &[u8] {
94        unsafe { core::slice::from_raw_parts(self.start as *const u8, self.size()) }
95    }
96    
97    /// Returns a mutable slice reference to the memory area
98    /// 
99    /// # Safety
100    /// This function assumes that the start and end of MemoryArea point to valid memory ranges.
101    /// If not, undefined behavior may occur.
102    /// Therefore, make sure that MemoryArea points to a valid range before using this function.
103    ///
104    /// # Returns
105    ///
106    /// A mutable slice reference to the memory area
107    ///
108    pub unsafe fn as_slice_mut(&self) -> &mut [u8] {
109        unsafe { core::slice::from_raw_parts_mut(self.start as *mut u8, self.size()) }
110    }
111}
112
113#[derive(Debug, Clone, Copy)]
114pub enum VirtualMemoryPermission {
115    Read = 0x01,
116    Write = 0x02,
117    Execute = 0x04,
118    User = 0x08,
119}
120
121impl From<usize> for VirtualMemoryPermission {
122    fn from(value: usize) -> Self {
123        match value {
124            0x01 => VirtualMemoryPermission::Read,
125            0x02 => VirtualMemoryPermission::Write,
126            0x04 => VirtualMemoryPermission::Execute,
127            0x08 => VirtualMemoryPermission::User,
128            _ => panic!("Invalid permission value: {}", value),
129        }
130    }
131}
132
133impl VirtualMemoryPermission {
134    pub fn contained_in(&self, permissions: usize) -> bool {
135        permissions & (*self as usize) != 0
136    }
137}
138
139pub enum VirtualMemoryRegion {
140    Text,
141    Data,
142    Bss,
143    Heap,
144    Stack,
145    Guard,
146    Unknown,
147}
148
149impl VirtualMemoryRegion {
150    pub fn default_permissions(&self) -> usize {
151        match self {
152            VirtualMemoryRegion::Text => VirtualMemoryPermission::Read as usize | VirtualMemoryPermission::Execute as usize | VirtualMemoryPermission::User as usize,
153            VirtualMemoryRegion::Data => VirtualMemoryPermission::Read as usize | VirtualMemoryPermission::Write as usize | VirtualMemoryPermission::User as usize,
154            VirtualMemoryRegion::Bss => VirtualMemoryPermission::Read as usize | VirtualMemoryPermission::Write as usize | VirtualMemoryPermission::User as usize,
155            VirtualMemoryRegion::Heap => VirtualMemoryPermission::Read as usize | VirtualMemoryPermission::Write as usize | VirtualMemoryPermission::User as usize,
156            VirtualMemoryRegion::Stack => VirtualMemoryPermission::Read as usize | VirtualMemoryPermission::Write as usize | VirtualMemoryPermission::User as usize,
157            VirtualMemoryRegion::Guard => 0, // Any access to the guard page should cause a page fault
158            VirtualMemoryRegion::Unknown => panic!("Unknown memory segment"),
159        }
160    }
161
162    /// Returns whether this memory region should be shared between tasks by default
163    pub fn is_shareable(&self) -> bool {
164        match self {
165            VirtualMemoryRegion::Text => true,  // Text segments can be shared (read-only executable code)
166            VirtualMemoryRegion::Data => false, // Data segments should not be shared (writable)
167            VirtualMemoryRegion::Bss => false,  // BSS segments should not be shared (writable)
168            VirtualMemoryRegion::Heap => false, // Heap should not be shared (writable)
169            VirtualMemoryRegion::Stack => false, // Stack should not be shared (writable, task-specific)
170            VirtualMemoryRegion::Guard => true,  // Guard pages can be shared (no physical backing)
171            VirtualMemoryRegion::Unknown => false, // Unknown segments should not be shared by default
172        }
173    }
174}