mm_list.rs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. mod page_fault;
  2. use crate::prelude::*;
  3. use alloc::{collections::btree_set::BTreeSet, sync::Arc};
  4. use bindings::{EEXIST, EINVAL, ENOMEM};
  5. use crate::kernel::vfs::dentry::Dentry;
  6. use super::{MMArea, PageTable, VAddr, VRange};
  7. pub use page_fault::{handle_page_fault, PageFaultError};
  8. #[derive(Debug, Clone)]
  9. pub struct FileMapping {
  10. file: Arc<Dentry>,
  11. /// Offset in the file, aligned to 4KB boundary.
  12. offset: usize,
  13. /// Length of the mapping. Exceeding part will be zeroed.
  14. length: usize,
  15. }
  16. #[derive(Debug, Clone, Copy)]
  17. pub struct Permission {
  18. pub write: bool,
  19. pub execute: bool,
  20. }
  21. #[derive(Debug, Clone)]
  22. pub enum Mapping {
  23. Anonymous,
  24. File(FileMapping),
  25. }
  26. #[derive(Debug)]
  27. struct MMListInner {
  28. areas: BTreeSet<MMArea>,
  29. page_table: PageTable,
  30. break_start: Option<VRange>,
  31. break_pos: Option<VAddr>,
  32. }
  33. #[derive(Debug)]
  34. pub struct MMList {
  35. /// # Safety
  36. /// This field might be used in IRQ context, so it should be locked with `lock_irq()`.
  37. inner: Mutex<MMListInner>,
  38. }
  39. impl FileMapping {
  40. pub fn new(file: Arc<Dentry>, offset: usize, length: usize) -> Self {
  41. assert_eq!(offset & 0xfff, 0);
  42. Self {
  43. file,
  44. offset,
  45. length,
  46. }
  47. }
  48. pub fn offset(&self, offset: usize) -> Self {
  49. if self.length <= offset {
  50. Self::new(self.file.clone(), self.offset + self.length, 0)
  51. } else {
  52. Self::new(
  53. self.file.clone(),
  54. self.offset + offset,
  55. self.length - offset,
  56. )
  57. }
  58. }
  59. }
  60. impl MMListInner {
  61. fn clear_user(&mut self) {
  62. self.areas.retain(|area| {
  63. self.page_table.unmap(area);
  64. false
  65. });
  66. self.break_start = None;
  67. self.break_pos = None;
  68. }
  69. fn overlapping_addr(&self, addr: VAddr) -> Option<&MMArea> {
  70. self.areas.get(&VRange::from(addr))
  71. }
  72. fn check_overlapping_addr(&self, addr: VAddr) -> bool {
  73. addr.is_user() && self.overlapping_addr(addr).is_none()
  74. }
  75. fn overlapping_range(&self, range: VRange) -> impl DoubleEndedIterator<Item = &MMArea> + '_ {
  76. self.areas.range(range.into_range())
  77. }
  78. fn check_overlapping_range(&self, range: VRange) -> bool {
  79. range.is_user() && self.overlapping_range(range).next().is_none()
  80. }
  81. fn find_available(&self, hint: VAddr, len: usize) -> Option<VAddr> {
  82. let mut range = VRange::new(hint.floor(), (hint + len).ceil());
  83. let len = range.len();
  84. loop {
  85. if !range.is_user() {
  86. return None;
  87. }
  88. match self.overlapping_range(range).next_back() {
  89. None => return Some(range.start()),
  90. Some(area) => {
  91. range = VRange::new(area.range().end().ceil(), area.range().end().ceil() + len);
  92. }
  93. }
  94. }
  95. }
  96. fn unmap(&mut self, start: VAddr, len: usize) -> KResult<()> {
  97. assert_eq!(start.floor(), start);
  98. let end = (start + len).ceil();
  99. let range = VRange::new(start, end);
  100. if !range.is_user() {
  101. return Err(EINVAL);
  102. }
  103. let check_range = VRange::from(range.start())..VRange::from(range.end());
  104. let mut front_remaining = None;
  105. let mut back_remaining = None;
  106. self.areas.retain(|area| {
  107. if !check_range.contains(&area.range()) {
  108. return true;
  109. }
  110. if area.range() == range.start().into() {
  111. let (left, right) = area.clone().split(range.start());
  112. self.page_table.unmap(&right.unwrap());
  113. if let Some(left) = left {
  114. assert!(
  115. front_remaining.replace(left).is_none(),
  116. "There should be only one `front`."
  117. );
  118. }
  119. } else if area.range() == range.end().into() {
  120. let (left, right) = area.clone().split(range.end());
  121. self.page_table.unmap(&left.unwrap());
  122. assert!(
  123. back_remaining
  124. .replace(right.expect("`right` should be valid"))
  125. .is_none(),
  126. "There should be only one `back`."
  127. );
  128. } else {
  129. self.page_table.unmap(area);
  130. }
  131. false
  132. });
  133. if let Some(front) = front_remaining {
  134. self.areas.insert(front);
  135. }
  136. if let Some(back) = back_remaining {
  137. self.areas.insert(back);
  138. }
  139. Ok(())
  140. }
  141. fn mmap(
  142. &mut self,
  143. at: VAddr,
  144. len: usize,
  145. mapping: Mapping,
  146. permission: Permission,
  147. ) -> KResult<()> {
  148. assert_eq!(at.floor(), at);
  149. assert_eq!(len & 0xfff, 0);
  150. let range = VRange::new(at, at + len);
  151. // We are doing a area marker insertion.
  152. if len == 0 && !self.check_overlapping_addr(at) || !self.check_overlapping_range(range) {
  153. return Err(EEXIST);
  154. }
  155. match &mapping {
  156. Mapping::Anonymous => self.page_table.set_anonymous(range, permission),
  157. Mapping::File(_) => self.page_table.set_mmapped(range, permission),
  158. }
  159. self.areas.insert(MMArea::new(range, mapping, permission));
  160. Ok(())
  161. }
  162. fn set_break(&mut self, pos: Option<VAddr>) -> VAddr {
  163. // SAFETY: `set_break` is only called in syscalls, where program break should be valid.
  164. assert!(self.break_start.is_some() && self.break_pos.is_some());
  165. let break_start = self.break_start.unwrap();
  166. let current_break = self.break_pos.unwrap();
  167. let pos = match pos {
  168. None => return current_break,
  169. Some(pos) => pos.ceil(),
  170. };
  171. let range = VRange::new(current_break, pos);
  172. if !self.check_overlapping_range(range) {
  173. return current_break;
  174. }
  175. self.page_table.set_anonymous(
  176. range,
  177. Permission {
  178. write: true,
  179. execute: false,
  180. },
  181. );
  182. let program_break = self
  183. .areas
  184. .get(&break_start)
  185. .expect("Program break area should be valid");
  186. program_break.grow(pos - current_break);
  187. self.break_pos = Some(pos);
  188. pos
  189. }
  190. }
  191. impl MMList {
  192. pub fn new() -> Arc<Self> {
  193. Arc::new(Self {
  194. inner: Mutex::new(MMListInner {
  195. areas: BTreeSet::new(),
  196. page_table: PageTable::new(),
  197. break_start: None,
  198. break_pos: None,
  199. }),
  200. })
  201. }
  202. /// # Safety
  203. /// Calling this function on the `MMList` of current process will need invalidating
  204. /// the TLB cache after the clone will be done. We might set some of the pages as COW.
  205. pub fn new_cloned(&self) -> Arc<Self> {
  206. let inner = self.inner.lock_irq();
  207. let list = Arc::new(Self {
  208. inner: Mutex::new(MMListInner {
  209. areas: inner.areas.clone(),
  210. page_table: PageTable::new(),
  211. break_start: inner.break_start,
  212. break_pos: inner.break_pos,
  213. }),
  214. });
  215. // SAFETY: `self.inner` already locked with IRQ disabled.
  216. {
  217. let list_inner = list.inner.lock();
  218. for area in list_inner.areas.iter() {
  219. let new_iter = list_inner.page_table.iter_user(area.range()).unwrap();
  220. let old_iter = inner.page_table.iter_user(area.range()).unwrap();
  221. for (new, old) in new_iter.zip(old_iter) {
  222. new.setup_cow(old);
  223. }
  224. }
  225. }
  226. list
  227. }
  228. /// # Safety
  229. /// Calling this function on the `MMList` of current process will need invalidating
  230. /// the TLB cache after the clone will be done. We might remove some mappings.
  231. pub fn clear_user(&self) {
  232. self.inner.lock_irq().clear_user()
  233. }
  234. pub fn switch_page_table(&self) {
  235. self.inner.lock_irq().page_table.switch();
  236. }
  237. /// No need to do invalidation manually, `PageTable` already does it.
  238. pub fn unmap(&self, start: VAddr, len: usize) -> KResult<()> {
  239. self.inner.lock_irq().unmap(start, len)
  240. }
  241. pub fn mmap_hint(
  242. &self,
  243. hint: VAddr,
  244. len: usize,
  245. mapping: Mapping,
  246. permission: Permission,
  247. ) -> KResult<VAddr> {
  248. let mut inner = self.inner.lock_irq();
  249. match inner.mmap(hint, len, mapping.clone(), permission) {
  250. Ok(()) => Ok(hint),
  251. Err(EEXIST) => {
  252. let at = inner.find_available(hint, len).ok_or(ENOMEM)?;
  253. inner.mmap(at, len, mapping, permission)?;
  254. Ok(at)
  255. }
  256. Err(err) => Err(err),
  257. }
  258. }
  259. pub fn mmap_fixed(
  260. &self,
  261. at: VAddr,
  262. len: usize,
  263. mapping: Mapping,
  264. permission: Permission,
  265. ) -> KResult<VAddr> {
  266. let mut inner = self.inner.lock_irq();
  267. inner.mmap(at, len, mapping.clone(), permission).map(|_| at)
  268. }
  269. pub fn set_break(&self, pos: Option<VAddr>) -> VAddr {
  270. self.inner.lock_irq().set_break(pos)
  271. }
  272. pub fn register_break(&self, start: VAddr) {
  273. let mut inner = self.inner.lock_irq();
  274. assert!(inner.break_start.is_none() && inner.break_pos.is_none());
  275. inner
  276. .mmap(
  277. start,
  278. 0,
  279. Mapping::Anonymous,
  280. Permission {
  281. write: true,
  282. execute: false,
  283. },
  284. )
  285. .expect("Probably, we have a bug in the ELF loader?");
  286. inner.break_start = Some(start.into());
  287. inner.break_pos = Some(start);
  288. }
  289. }
  290. impl Drop for MMList {
  291. fn drop(&mut self) {
  292. self.clear_user();
  293. }
  294. }