1use crate::error::Result;
2use crate::hal::mem::{PhysAddr, VirtAddr};
3
4mod nommu;
5
6pub type AddressSpace = nommu::AddressSpace;
7
8bitflags::bitflags! {
9 #[derive(Clone, Copy)]
10 pub struct Perms: u8 {
11 const Read = 0b0001;
12 const Write = 0b0010;
13 const Exec = 0b0100;
14 }
15}
16
17#[derive(Clone)]
18#[allow(dead_code)]
19pub enum Backing {
20 Zeroed,
21 Uninit,
22 Anon(PhysAddr),
23}
24
25#[derive(Clone)]
26#[allow(dead_code)]
27pub struct Region {
28 start: Option<VirtAddr>,
29 len: usize,
30 backing: Backing,
31 perms: Perms,
32}
33
34impl Region {
35 pub fn new(start: Option<VirtAddr>, len: usize, backing: Backing, perms: Perms) -> Self {
43 Self {
44 start,
45 len,
46 backing,
47 perms,
48 }
49 }
50
51 #[allow(dead_code)]
52 pub fn start(&self) -> VirtAddr {
53 self.start.unwrap_or_else(|| VirtAddr::new(0))
54 }
55
56 pub fn len(&self) -> usize {
57 self.len
58 }
59
60 #[allow(dead_code)]
61 pub fn contains(&self, addr: VirtAddr) -> bool {
62 let Some(start) = self.start else {
63 return false;
64 };
65 start.saturating_add(self.len()) > addr && addr >= start
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::*;
72
73 #[test]
74 fn unplaced_region_contains_nothing() {
75 let r = Region::new(None, 100, Backing::Uninit, Perms::Read);
76 assert!(!r.contains(VirtAddr::new(0)));
77 assert!(!r.contains(VirtAddr::new(50)));
78 assert!(!r.contains(VirtAddr::new(100)));
79 }
80
81 #[test]
82 fn placed_region_contains_within_bounds() {
83 let r = Region::new(Some(VirtAddr::new(100)), 50, Backing::Uninit, Perms::Read);
84 assert!(!r.contains(VirtAddr::new(99)));
85 assert!(r.contains(VirtAddr::new(100)));
86 assert!(r.contains(VirtAddr::new(149)));
87 assert!(!r.contains(VirtAddr::new(150)));
88 }
89
90 #[test]
91 fn placed_region_saturates_at_usize_max() {
92 let r = Region::new(
93 Some(VirtAddr::new(usize::MAX - 10)),
94 100,
95 Backing::Uninit,
96 Perms::Read,
97 );
98 assert!(r.contains(VirtAddr::new(usize::MAX - 10)));
99 assert!(r.contains(VirtAddr::new(usize::MAX - 1)));
100 assert!(!r.contains(VirtAddr::new(usize::MAX)));
101 }
102}
103
104#[allow(dead_code)]
105pub trait AddressSpacelike {
106 fn new(pages: usize) -> Result<Self>
108 where
109 Self: Sized;
110 fn map(&mut self, region: Region) -> Result<PhysAddr>;
111 fn unmap(&mut self, region: &Region) -> Result<()>;
112 fn protect(&mut self, region: &Region, perms: Perms) -> Result<()>;
113 fn virt_to_phys(&self, addr: VirtAddr) -> Option<PhysAddr>;
114 fn phys_to_virt(&self, addr: PhysAddr) -> Option<VirtAddr>;
115 fn end(&self) -> VirtAddr;
116 fn activate(&self) -> Result<()>;
117}