mm_list.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. mod page_fault;
  2. use core::{
  3. ops::Sub as _,
  4. sync::atomic::{AtomicUsize, Ordering},
  5. };
  6. use crate::{prelude::*, sync::ArcSwap};
  7. use alloc::{collections::btree_set::BTreeSet, sync::Arc};
  8. use bindings::{EEXIST, EFAULT, EINVAL, ENOMEM, KERNEL_PML4};
  9. use crate::kernel::vfs::dentry::Dentry;
  10. use super::{MMArea, Page, PageTable, VAddr, VRange};
  11. pub use page_fault::handle_page_fault;
  12. #[derive(Debug, Clone)]
  13. pub struct FileMapping {
  14. pub file: Arc<Dentry>,
  15. /// Offset in the file, aligned to 4KB boundary.
  16. pub offset: usize,
  17. /// Length of the mapping. Exceeding part will be zeroed.
  18. pub length: usize,
  19. }
  20. #[derive(Debug, Clone, Copy)]
  21. pub struct Permission {
  22. pub write: bool,
  23. pub execute: bool,
  24. }
  25. #[derive(Debug, Clone)]
  26. pub enum Mapping {
  27. Anonymous,
  28. File(FileMapping),
  29. }
  30. #[derive(Debug)]
  31. struct MMListInner {
  32. areas: BTreeSet<MMArea>,
  33. page_table: PageTable,
  34. break_start: Option<VRange>,
  35. break_pos: Option<VAddr>,
  36. }
  37. #[derive(Debug)]
  38. pub struct MMList {
  39. /// # Safety
  40. /// This field might be used in IRQ context, so it should be locked with `lock_irq()`.
  41. inner: ArcSwap<Mutex<MMListInner>>,
  42. /// Only used in kernel space to switch page tables on context switch.
  43. root_page_table: AtomicUsize,
  44. }
  45. impl FileMapping {
  46. pub fn new(file: Arc<Dentry>, offset: usize, length: usize) -> Self {
  47. assert_eq!(offset & 0xfff, 0);
  48. Self {
  49. file,
  50. offset,
  51. length,
  52. }
  53. }
  54. pub fn offset(&self, offset: usize) -> Self {
  55. if self.length <= offset {
  56. Self::new(self.file.clone(), self.offset + self.length, 0)
  57. } else {
  58. Self::new(
  59. self.file.clone(),
  60. self.offset + offset,
  61. self.length - offset,
  62. )
  63. }
  64. }
  65. }
  66. impl MMListInner {
  67. fn overlapping_addr(&self, addr: VAddr) -> Option<&MMArea> {
  68. self.areas.get(&VRange::from(addr))
  69. }
  70. fn check_overlapping_addr(&self, addr: VAddr) -> bool {
  71. addr.is_user() && self.overlapping_addr(addr).is_none()
  72. }
  73. fn overlapping_range(&self, range: VRange) -> impl DoubleEndedIterator<Item = &MMArea> + '_ {
  74. self.areas.range(range.into_range())
  75. }
  76. fn check_overlapping_range(&self, range: VRange) -> bool {
  77. range.is_user() && self.overlapping_range(range).next().is_none()
  78. }
  79. fn find_available(&self, hint: VAddr, len: usize) -> Option<VAddr> {
  80. let mut range = if hint == VAddr::NULL {
  81. VRange::new(VAddr(0x1234000), VAddr(0x1234000 + len).ceil())
  82. } else {
  83. VRange::new(hint.floor(), (hint + len).ceil())
  84. };
  85. let len = range.len();
  86. loop {
  87. if !range.is_user() {
  88. return None;
  89. }
  90. match self.overlapping_range(range).next_back() {
  91. None => return Some(range.start()),
  92. Some(area) => {
  93. range = VRange::new(area.range().end().ceil(), area.range().end().ceil() + len);
  94. }
  95. }
  96. }
  97. }
  98. fn unmap(&mut self, start: VAddr, len: usize) -> KResult<()> {
  99. assert_eq!(start.floor(), start);
  100. let end = (start + len).ceil();
  101. let range = VRange::new(start, end);
  102. if !range.is_user() {
  103. return Err(EINVAL);
  104. }
  105. let check_range = VRange::from(range.start())..VRange::from(range.end());
  106. let mut front_remaining = None;
  107. let mut back_remaining = None;
  108. self.areas.retain(|area| {
  109. if !check_range.contains(&area.range()) {
  110. return true;
  111. }
  112. if area.range() == range.start().into() {
  113. let (left, right) = area.clone().split(range.start());
  114. self.page_table.unmap(&right.unwrap());
  115. if let Some(left) = left {
  116. assert!(
  117. front_remaining.replace(left).is_none(),
  118. "There should be only one `front`."
  119. );
  120. }
  121. } else if area.range() == range.end().into() {
  122. let (left, right) = area.clone().split(range.end());
  123. self.page_table.unmap(&left.unwrap());
  124. assert!(
  125. back_remaining
  126. .replace(right.expect("`right` should be valid"))
  127. .is_none(),
  128. "There should be only one `back`."
  129. );
  130. } else {
  131. self.page_table.unmap(area);
  132. }
  133. false
  134. });
  135. if let Some(front) = front_remaining {
  136. self.areas.insert(front);
  137. }
  138. if let Some(back) = back_remaining {
  139. self.areas.insert(back);
  140. }
  141. Ok(())
  142. }
  143. fn mmap(
  144. &mut self,
  145. at: VAddr,
  146. len: usize,
  147. mapping: Mapping,
  148. permission: Permission,
  149. ) -> KResult<()> {
  150. assert_eq!(at.floor(), at);
  151. assert_eq!(len & 0xfff, 0);
  152. let range = VRange::new(at, at + len);
  153. // We are doing a area marker insertion.
  154. if len == 0 && !self.check_overlapping_addr(at) || !self.check_overlapping_range(range) {
  155. return Err(EEXIST);
  156. }
  157. match &mapping {
  158. Mapping::Anonymous => self.page_table.set_anonymous(range, permission),
  159. Mapping::File(_) => self.page_table.set_mmapped(range, permission),
  160. }
  161. self.areas.insert(MMArea::new(range, mapping, permission));
  162. Ok(())
  163. }
  164. }
  165. impl MMList {
  166. pub fn new() -> Self {
  167. let page_table = PageTable::new();
  168. Self {
  169. root_page_table: AtomicUsize::from(page_table.root_page_table()),
  170. inner: ArcSwap::new(Mutex::new(MMListInner {
  171. areas: BTreeSet::new(),
  172. page_table,
  173. break_start: None,
  174. break_pos: None,
  175. })),
  176. }
  177. }
  178. pub fn new_cloned(&self) -> Self {
  179. let inner = self.inner.borrow();
  180. let inner = inner.lock_irq();
  181. let page_table = PageTable::new();
  182. let list = Self {
  183. root_page_table: AtomicUsize::from(page_table.root_page_table()),
  184. inner: ArcSwap::new(Mutex::new(MMListInner {
  185. areas: inner.areas.clone(),
  186. page_table,
  187. break_start: inner.break_start,
  188. break_pos: inner.break_pos,
  189. })),
  190. };
  191. {
  192. let list_inner = list.inner.borrow();
  193. let list_inner = list_inner.lock();
  194. for area in list_inner.areas.iter() {
  195. let new_iter = list_inner.page_table.iter_user(area.range()).unwrap();
  196. let old_iter = inner.page_table.iter_user(area.range()).unwrap();
  197. for (new, old) in new_iter.zip(old_iter) {
  198. new.setup_cow(old);
  199. }
  200. }
  201. }
  202. // We set some pages as COW, so we need to invalidate TLB.
  203. inner.page_table.lazy_invalidate_tlb_all();
  204. list
  205. }
  206. pub fn switch_page_table(&self) {
  207. let root_page_table = self.root_page_table.load(Ordering::Relaxed);
  208. assert_ne!(root_page_table, 0);
  209. arch::set_root_page_table(root_page_table);
  210. }
  211. pub fn replace(&self, new: Self) {
  212. // Switch to kernel page table in case we are using the page table to be swapped and released.
  213. let mut switched = false;
  214. if arch::get_root_page_table() == self.root_page_table.load(Ordering::Relaxed) {
  215. arch::set_root_page_table(KERNEL_PML4 as usize);
  216. switched = true;
  217. }
  218. unsafe {
  219. // SAFETY: Even if we're using the page table, we've switched to kernel page table.
  220. // So it's safe to release the old memory list.
  221. self.release();
  222. }
  223. // SAFETY: `self.inner` should be `None` after releasing.
  224. self.inner.swap(Some(new.inner.borrow().clone()));
  225. self.root_page_table.store(
  226. new.root_page_table.load(Ordering::Relaxed),
  227. Ordering::Relaxed,
  228. );
  229. if switched {
  230. self.switch_page_table();
  231. }
  232. }
  233. /// # Safety
  234. /// This function is unsafe because the caller should make sure that the `inner` is not currently used.
  235. pub unsafe fn release(&self) {
  236. // TODO: Check whether we should wake someone up if they've been put to sleep when calling `vfork`.
  237. self.inner.swap(None);
  238. self.root_page_table
  239. .swap(KERNEL_PML4 as _, Ordering::Relaxed);
  240. }
  241. /// No need to do invalidation manually, `PageTable` already does it.
  242. pub fn unmap(&self, start: VAddr, len: usize) -> KResult<()> {
  243. self.inner.borrow().lock_irq().unmap(start, len)
  244. }
  245. pub fn mmap_hint(
  246. &self,
  247. hint: VAddr,
  248. len: usize,
  249. mapping: Mapping,
  250. permission: Permission,
  251. ) -> KResult<VAddr> {
  252. let inner = self.inner.borrow();
  253. let mut inner = inner.lock_irq();
  254. if hint == VAddr::NULL {
  255. let at = inner.find_available(hint, len).ok_or(ENOMEM)?;
  256. inner.mmap(at, len, mapping, permission)?;
  257. return Ok(at);
  258. }
  259. match inner.mmap(hint, len, mapping.clone(), permission) {
  260. Ok(()) => Ok(hint),
  261. Err(EEXIST) => {
  262. let at = inner.find_available(hint, len).ok_or(ENOMEM)?;
  263. inner.mmap(at, len, mapping, permission)?;
  264. Ok(at)
  265. }
  266. Err(err) => Err(err),
  267. }
  268. }
  269. pub fn mmap_fixed(
  270. &self,
  271. at: VAddr,
  272. len: usize,
  273. mapping: Mapping,
  274. permission: Permission,
  275. ) -> KResult<VAddr> {
  276. self.inner
  277. .borrow()
  278. .lock_irq()
  279. .mmap(at, len, mapping.clone(), permission)
  280. .map(|_| at)
  281. }
  282. pub fn set_break(&self, pos: Option<VAddr>) -> VAddr {
  283. let inner = self.inner.borrow();
  284. let mut inner = inner.lock_irq();
  285. // SAFETY: `set_break` is only called in syscalls, where program break should be valid.
  286. assert!(inner.break_start.is_some() && inner.break_pos.is_some());
  287. let break_start = inner.break_start.unwrap();
  288. let current_break = inner.break_pos.unwrap();
  289. let pos = match pos {
  290. None => return current_break,
  291. Some(pos) => pos.ceil(),
  292. };
  293. let range = VRange::new(current_break, pos);
  294. if !inner.check_overlapping_range(range) {
  295. return current_break;
  296. }
  297. if !inner.areas.contains(&break_start) {
  298. inner.areas.insert(MMArea::new(
  299. break_start,
  300. Mapping::Anonymous,
  301. Permission {
  302. write: true,
  303. execute: false,
  304. },
  305. ));
  306. }
  307. let program_break = inner
  308. .areas
  309. .get(&break_start)
  310. .expect("Program break area should be valid");
  311. let len: usize = pos.sub(current_break);
  312. inner.page_table.set_anonymous(
  313. VRange::from(program_break.range().end()).grow(len),
  314. Permission {
  315. write: true,
  316. execute: false,
  317. },
  318. );
  319. program_break.grow(len);
  320. inner.break_pos = Some(pos);
  321. pos
  322. }
  323. /// This should be called only **once** for every thread.
  324. pub fn register_break(&self, start: VAddr) {
  325. let inner = self.inner.borrow();
  326. let mut inner = inner.lock_irq();
  327. assert!(inner.break_start.is_none() && inner.break_pos.is_none());
  328. inner.break_start = Some(start.into());
  329. inner.break_pos = Some(start);
  330. }
  331. /// Access the memory area with the given function.
  332. /// The function will be called with the offset of the area and the slice of the area.
  333. pub fn access_mut<F>(&self, start: VAddr, len: usize, func: F) -> KResult<()>
  334. where
  335. F: Fn(usize, &mut [u8]),
  336. {
  337. // First, validate the address range.
  338. let end = start + len;
  339. if !start.is_user() || !end.is_user() {
  340. return Err(EINVAL);
  341. }
  342. let inner = self.inner.borrow();
  343. let inner = inner.lock_irq();
  344. let mut offset = 0;
  345. let mut remaining = len;
  346. let mut current = start;
  347. while remaining > 0 {
  348. let area = inner.overlapping_addr(current).ok_or(EFAULT)?;
  349. let area_start = area.range().start();
  350. let area_end = area.range().end();
  351. let area_remaining = area_end - current;
  352. let access_len = remaining.min(area_remaining);
  353. let access_end = current + access_len;
  354. for (idx, pte) in inner
  355. .page_table
  356. .iter_user(VRange::new(current, access_end))?
  357. .enumerate()
  358. {
  359. let page_start = current.floor() + idx * 0x1000;
  360. let page_end = page_start + 0x1000;
  361. area.handle(pte, page_start - area_start)?;
  362. let start_offset;
  363. if page_start < current {
  364. start_offset = current - page_start;
  365. } else {
  366. start_offset = 0;
  367. }
  368. let end_offset;
  369. if page_end > access_end {
  370. end_offset = access_end - page_start;
  371. } else {
  372. end_offset = 0x1000;
  373. }
  374. unsafe {
  375. let page = Page::from_pfn(pte.pfn(), 0);
  376. func(
  377. offset + idx * 0x1000,
  378. &mut page.as_mut_slice()[start_offset..end_offset],
  379. );
  380. }
  381. }
  382. offset += access_len;
  383. remaining -= access_len;
  384. current = access_end;
  385. }
  386. Ok(())
  387. }
  388. }