mm_list.rs 14 KB

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