Skip to main content

rustubs/mm/
vmm.rs

1//! a very simple virtual memory manager
2
3use alloc::string::String;
4use alloc::vec::Vec;
5use bitflags::bitflags;
6use core::fmt;
7use core::ops::Range;
8
9#[derive(Clone)]
10pub struct VMMan {
11	pub vmas: Vec<VMArea>,
12}
13
14impl VMMan {
15	pub fn new() -> Self { Self { vmas: Vec::<VMArea>::new() } }
16}
17
18bitflags! {
19  #[derive(Clone)]
20	pub struct VMPerms: u8 {
21		const NONE = 0;
22		const R = 1 << 0;
23		const W = 1 << 1;
24		const X = 1 << 2;
25	}
26}
27
28impl fmt::Debug for VMPerms {
29	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30		write!(
31			f,
32			"{}{}{}",
33			if self.contains(Self::R) { "R" } else { "-" },
34			if self.contains(Self::W) { "W" } else { "-" },
35			if self.contains(Self::X) { "X" } else { "-" }
36		)
37	}
38}
39
40/// The paging facility must handle the case where vm_range > file range, i.e.
41/// vm_range.end - vm_range.start > f.len(). The trailing virtual memory range
42/// will be BSS (anonymous backed, zeroed). See fn bss_range
43#[derive(Clone)]
44pub struct VMArea {
45	pub vm_range: Range<u64>,
46	pub tag: String,
47	pub user_perms: VMPerms,
48	pub backing: VMType,
49}
50
51impl VMArea {
52	/// returns the virtual address range of BSS.
53	pub fn bss_range(&self) -> Option<Range<u64>> {
54		if let VMType::FILE(f) = self.backing {
55			assert!(
56				self.vm_range.end - self.vm_range.start >= f.len() as u64,
57				"ill-formed VMA"
58			);
59			Some((self.vm_range.start + f.len() as u64)..self.vm_range.end)
60		} else {
61			None
62		}
63	}
64}
65
66impl fmt::Debug for VMArea {
67	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
68		write!(
69			f,
70			"{:016X}-{:016X} {:?} - {:?} - {}",
71			self.vm_range.start,
72			self.vm_range.end,
73			self.user_perms,
74			self.backing,
75			self.tag
76		)
77	}
78}
79
80#[derive(Clone)]
81pub enum VMType {
82	ANOM,
83	FILE(&'static [u8]),
84	// NONE for device memory mappings
85	NONE,
86}
87
88impl fmt::Debug for VMType {
89	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90		write!(
91			f,
92			"{}",
93			match self {
94				Self::ANOM => "ANOM",
95				Self::FILE(_) => "FILE",
96				Self::NONE => "DEV",
97			},
98		)
99	}
100}