page.rs 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  1. use core::{
  2. fmt::{self, Debug, Error, Formatter},
  3. marker::PhantomData,
  4. mem,
  5. ops::Add,
  6. sync::atomic::{compiler_fence, Ordering},
  7. };
  8. use alloc::sync::Arc;
  9. use hashbrown::{HashMap, HashSet};
  10. use crate::{
  11. arch::{interrupt::ipi::send_ipi, MMArch},
  12. exception::ipi::{IpiKind, IpiTarget},
  13. kerror, kwarn,
  14. libs::spinlock::{SpinLock, SpinLockGuard},
  15. };
  16. use super::{
  17. allocator::page_frame::FrameAllocator, syscall::ProtFlags, ucontext::LockedVMA,
  18. MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
  19. };
  20. pub const PAGE_4K_SHIFT: usize = 12;
  21. #[allow(dead_code)]
  22. pub const PAGE_2M_SHIFT: usize = 21;
  23. pub const PAGE_1G_SHIFT: usize = 30;
  24. /// 全局物理页信息管理器
  25. pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None;
  26. /// 初始化PAGE_MANAGER
  27. pub fn page_manager_init() {
  28. kinfo!("page_manager_init");
  29. let page_manager = SpinLock::new(PageManager::new());
  30. compiler_fence(Ordering::SeqCst);
  31. unsafe { PAGE_MANAGER = Some(page_manager) };
  32. compiler_fence(Ordering::SeqCst);
  33. kinfo!("page_manager_init done");
  34. }
  35. pub fn page_manager_lock_irasave() -> SpinLockGuard<'static, PageManager> {
  36. unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() }
  37. }
  38. // 物理页管理器
  39. pub struct PageManager {
  40. phys2page: HashMap<PhysAddr, Page>,
  41. }
  42. impl PageManager {
  43. pub fn new() -> Self {
  44. Self {
  45. phys2page: HashMap::new(),
  46. }
  47. }
  48. pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page {
  49. self.phys2page.get_mut(paddr).unwrap()
  50. }
  51. pub fn insert(&mut self, paddr: PhysAddr, page: Page) {
  52. self.phys2page.insert(paddr, page);
  53. }
  54. pub fn remove_page(&mut self, paddr: &PhysAddr) {
  55. self.phys2page.remove(paddr);
  56. }
  57. }
  58. /// 物理页面信息
  59. pub struct Page {
  60. /// 映射计数
  61. map_count: usize,
  62. /// 是否为共享页
  63. shared: bool,
  64. /// 映射到当前page的VMA
  65. anon_vma: HashSet<Arc<LockedVMA>>,
  66. }
  67. impl Page {
  68. pub fn new(shared: bool) -> Self {
  69. Self {
  70. map_count: 0,
  71. shared,
  72. anon_vma: HashSet::new(),
  73. }
  74. }
  75. /// 将vma加入anon_vma
  76. pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
  77. self.anon_vma.insert(vma);
  78. self.map_count += 1;
  79. }
  80. /// 将vma从anon_vma中删去
  81. pub fn remove_vma(&mut self, vma: &LockedVMA) {
  82. self.anon_vma.remove(vma);
  83. self.map_count -= 1;
  84. }
  85. /// 判断当前物理页是否能被回
  86. pub fn can_deallocate(&self) -> bool {
  87. self.map_count == 0 && !self.shared
  88. }
  89. }
  90. #[derive(Debug)]
  91. pub struct PageTable<Arch> {
  92. /// 当前页表表示的虚拟地址空间的起始地址
  93. base: VirtAddr,
  94. /// 当前页表所在的物理地址
  95. phys: PhysAddr,
  96. /// 当前页表的层级(请注意,最顶级页表的level为[Arch::PAGE_LEVELS - 1])
  97. level: usize,
  98. phantom: PhantomData<Arch>,
  99. }
  100. #[allow(dead_code)]
  101. impl<Arch: MemoryManagementArch> PageTable<Arch> {
  102. pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self {
  103. Self {
  104. base,
  105. phys,
  106. level,
  107. phantom: PhantomData,
  108. }
  109. }
  110. /// 获取顶级页表
  111. ///
  112. /// ## 参数
  113. ///
  114. /// - table_kind 页表类型
  115. ///
  116. /// ## 返回值
  117. ///
  118. /// 返回顶级页表
  119. pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self {
  120. return Self::new(
  121. VirtAddr::new(0),
  122. Arch::table(table_kind),
  123. Arch::PAGE_LEVELS - 1,
  124. );
  125. }
  126. /// 获取当前页表的物理地址
  127. #[inline(always)]
  128. pub fn phys(&self) -> PhysAddr {
  129. self.phys
  130. }
  131. /// 当前页表表示的虚拟地址空间的起始地址
  132. #[inline(always)]
  133. pub fn base(&self) -> VirtAddr {
  134. self.base
  135. }
  136. /// 获取当前页表的层级
  137. #[inline(always)]
  138. pub fn level(&self) -> usize {
  139. self.level
  140. }
  141. /// 获取当前页表自身所在的虚拟地址
  142. #[inline(always)]
  143. pub unsafe fn virt(&self) -> VirtAddr {
  144. return Arch::phys_2_virt(self.phys).unwrap();
  145. }
  146. /// 获取第i个页表项所表示的虚拟内存空间的起始地址
  147. pub fn entry_base(&self, i: usize) -> Option<VirtAddr> {
  148. if i < Arch::PAGE_ENTRY_NUM {
  149. let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
  150. return Some(self.base.add(i << shift));
  151. } else {
  152. return None;
  153. }
  154. }
  155. /// 获取当前页表的第i个页表项所在的虚拟地址(注意与entry_base进行区分)
  156. pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> {
  157. if i < Arch::PAGE_ENTRY_NUM {
  158. return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE));
  159. } else {
  160. return None;
  161. }
  162. }
  163. /// 获取当前页表的第i个页表项
  164. pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
  165. let entry_virt = self.entry_virt(i)?;
  166. return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt)));
  167. }
  168. /// 设置当前页表的第i个页表项
  169. pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> {
  170. let entry_virt = self.entry_virt(i)?;
  171. Arch::write::<usize>(entry_virt, entry.data());
  172. return Some(());
  173. }
  174. /// 判断当前页表的第i个页表项是否已经填写了值
  175. ///
  176. /// ## 参数
  177. /// - Some(true) 如果已经填写了值
  178. /// - Some(false) 如果未填写值
  179. /// - None 如果i超出了页表项的范围
  180. pub fn entry_mapped(&self, i: usize) -> Option<bool> {
  181. let etv = unsafe { self.entry_virt(i) }?;
  182. if unsafe { Arch::read::<usize>(etv) } != 0 {
  183. return Some(true);
  184. } else {
  185. return Some(false);
  186. }
  187. }
  188. /// 根据虚拟地址,获取对应的页表项在页表中的下标
  189. ///
  190. /// ## 参数
  191. ///
  192. /// - addr: 虚拟地址
  193. ///
  194. /// ## 返回值
  195. ///
  196. /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中,则返回None
  197. pub unsafe fn index_of(&self, addr: VirtAddr) -> Option<usize> {
  198. let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK);
  199. let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
  200. let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1;
  201. if addr < self.base || addr >= self.base.add(mask) {
  202. return None;
  203. } else {
  204. return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK);
  205. }
  206. }
  207. /// 获取第i个页表项指向的下一级页表
  208. pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> {
  209. if self.level == 0 {
  210. return None;
  211. }
  212. // 返回下一级页表
  213. return Some(PageTable::new(
  214. self.entry_base(index)?,
  215. self.entry(index)?.address().ok()?,
  216. self.level - 1,
  217. ));
  218. }
  219. }
  220. /// 页表项
  221. #[derive(Copy, Clone)]
  222. pub struct PageEntry<Arch> {
  223. data: usize,
  224. phantom: PhantomData<Arch>,
  225. }
  226. impl<Arch> Debug for PageEntry<Arch> {
  227. fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
  228. f.write_fmt(format_args!("PageEntry({:#x})", self.data))
  229. }
  230. }
  231. impl<Arch: MemoryManagementArch> PageEntry<Arch> {
  232. #[inline(always)]
  233. pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> Self {
  234. Self {
  235. data: MMArch::make_entry(paddr, flags.data()),
  236. phantom: PhantomData,
  237. }
  238. }
  239. #[inline(always)]
  240. pub fn from_usize(data: usize) -> Self {
  241. Self {
  242. data,
  243. phantom: PhantomData,
  244. }
  245. }
  246. #[inline(always)]
  247. pub fn data(&self) -> usize {
  248. self.data
  249. }
  250. /// 获取当前页表项指向的物理地址
  251. ///
  252. /// ## 返回值
  253. ///
  254. /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址
  255. /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
  256. #[inline(always)]
  257. pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
  258. let paddr: PhysAddr = {
  259. #[cfg(target_arch = "x86_64")]
  260. {
  261. PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK)
  262. }
  263. #[cfg(target_arch = "riscv64")]
  264. {
  265. let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1);
  266. super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
  267. }
  268. };
  269. if self.present() {
  270. Ok(paddr)
  271. } else {
  272. Err(paddr)
  273. }
  274. }
  275. #[inline(always)]
  276. pub fn flags(&self) -> PageFlags<Arch> {
  277. unsafe { PageFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
  278. }
  279. #[inline(always)]
  280. pub fn set_flags(&mut self, flags: PageFlags<Arch>) {
  281. self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data();
  282. }
  283. #[inline(always)]
  284. pub fn present(&self) -> bool {
  285. return self.data & Arch::ENTRY_FLAG_PRESENT != 0;
  286. }
  287. }
  288. /// 页表项的标志位
  289. #[derive(Copy, Clone, Hash)]
  290. pub struct PageFlags<Arch> {
  291. data: usize,
  292. phantom: PhantomData<Arch>,
  293. }
  294. #[allow(dead_code)]
  295. impl<Arch: MemoryManagementArch> PageFlags<Arch> {
  296. #[inline(always)]
  297. pub fn new() -> Self {
  298. let mut r = unsafe {
  299. Self::from_data(
  300. Arch::ENTRY_FLAG_DEFAULT_PAGE
  301. | Arch::ENTRY_FLAG_READONLY
  302. | Arch::ENTRY_FLAG_NO_EXEC,
  303. )
  304. };
  305. #[cfg(target_arch = "x86_64")]
  306. {
  307. if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
  308. r = r.set_execute(true);
  309. }
  310. }
  311. return r;
  312. }
  313. /// 根据ProtFlags生成PageFlags
  314. ///
  315. /// ## 参数
  316. ///
  317. /// - prot_flags: 页的保护标志
  318. /// - user: 用户空间是否可访问
  319. pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> {
  320. let flags: PageFlags<Arch> = PageFlags::new()
  321. .set_user(user)
  322. .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
  323. .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
  324. return flags;
  325. }
  326. #[inline(always)]
  327. pub fn data(&self) -> usize {
  328. self.data
  329. }
  330. #[inline(always)]
  331. pub const unsafe fn from_data(data: usize) -> Self {
  332. return Self {
  333. data,
  334. phantom: PhantomData,
  335. };
  336. }
  337. /// 为新页表的页表项设置默认值
  338. ///
  339. /// 默认值为:
  340. /// - present
  341. /// - read only
  342. /// - kernel space
  343. /// - no exec
  344. #[inline(always)]
  345. pub fn new_page_table(user: bool) -> Self {
  346. return unsafe {
  347. let r = {
  348. #[cfg(target_arch = "x86_64")]
  349. {
  350. Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE)
  351. }
  352. #[cfg(target_arch = "riscv64")]
  353. {
  354. // riscv64指向下一级页表的页表项,不应设置R/W/X权限位
  355. Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
  356. }
  357. };
  358. if user {
  359. r.set_user(true)
  360. } else {
  361. r
  362. }
  363. };
  364. }
  365. /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。
  366. ///
  367. /// ## 参数
  368. /// - flag 要更新的标志位的值
  369. /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0
  370. ///
  371. /// ## 返回值
  372. ///
  373. /// 更新后的页表项
  374. #[inline(always)]
  375. #[must_use]
  376. pub fn update_flags(mut self, flag: usize, value: bool) -> Self {
  377. if value {
  378. self.data |= flag;
  379. } else {
  380. self.data &= !flag;
  381. }
  382. return self;
  383. }
  384. /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true)
  385. #[inline(always)]
  386. pub fn has_flag(&self, flag: usize) -> bool {
  387. return self.data & flag == flag;
  388. }
  389. #[inline(always)]
  390. pub fn present(&self) -> bool {
  391. return self.has_flag(Arch::ENTRY_FLAG_PRESENT);
  392. }
  393. /// 设置当前页表项的权限
  394. ///
  395. /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问
  396. #[must_use]
  397. #[inline(always)]
  398. pub fn set_user(self, value: bool) -> Self {
  399. return self.update_flags(Arch::ENTRY_FLAG_USER, value);
  400. }
  401. /// 用户态是否可以访问当前页表项
  402. #[inline(always)]
  403. pub fn has_user(&self) -> bool {
  404. return self.has_flag(Arch::ENTRY_FLAG_USER);
  405. }
  406. /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读
  407. ///
  408. /// ## 返回值
  409. ///
  410. /// 更新后的页表项.
  411. ///
  412. /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项
  413. #[must_use]
  414. #[inline(always)]
  415. pub fn set_write(self, value: bool) -> Self {
  416. #[cfg(target_arch = "x86_64")]
  417. {
  418. // 有的架构同时具有可写和不可写的标志位,因此需要同时更新
  419. return self
  420. .update_flags(Arch::ENTRY_FLAG_READONLY, !value)
  421. .update_flags(Arch::ENTRY_FLAG_READWRITE, value);
  422. }
  423. #[cfg(target_arch = "riscv64")]
  424. {
  425. if value {
  426. return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
  427. } else {
  428. return self.update_flags(Arch::ENTRY_FLAG_READONLY, true);
  429. }
  430. }
  431. }
  432. /// 当前页表项是否可写
  433. #[inline(always)]
  434. pub fn has_write(&self) -> bool {
  435. // 有的架构同时具有可写和不可写的标志位,因此需要同时判断
  436. return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY)
  437. == Arch::ENTRY_FLAG_READWRITE;
  438. }
  439. /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行
  440. #[must_use]
  441. #[inline(always)]
  442. pub fn set_execute(self, mut value: bool) -> Self {
  443. #[cfg(target_arch = "x86_64")]
  444. {
  445. // 如果xd位被保留,那么将可执行性设置为true
  446. if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
  447. value = true;
  448. }
  449. }
  450. // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新
  451. return self
  452. .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value)
  453. .update_flags(Arch::ENTRY_FLAG_EXEC, value);
  454. }
  455. /// 当前页表项是否可执行
  456. #[inline(always)]
  457. pub fn has_execute(&self) -> bool {
  458. // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断
  459. return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC)
  460. == Arch::ENTRY_FLAG_EXEC;
  461. }
  462. /// 设置当前页表项的缓存策略
  463. ///
  464. /// ## 参数
  465. ///
  466. /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。
  467. #[inline(always)]
  468. pub fn set_page_cache_disable(self, value: bool) -> Self {
  469. return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value);
  470. }
  471. /// 获取当前页表项的缓存策略
  472. ///
  473. /// ## 返回值
  474. ///
  475. /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。
  476. #[inline(always)]
  477. pub fn has_page_cache_disable(&self) -> bool {
  478. return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE);
  479. }
  480. /// 设置当前页表项的写穿策略
  481. ///
  482. /// ## 参数
  483. ///
  484. /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。
  485. #[inline(always)]
  486. pub fn set_page_write_through(self, value: bool) -> Self {
  487. return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value);
  488. }
  489. /// 获取当前页表项的写穿策略
  490. ///
  491. /// ## 返回值
  492. ///
  493. /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。
  494. #[inline(always)]
  495. pub fn has_page_write_through(&self) -> bool {
  496. return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH);
  497. }
  498. /// MMIO内存的页表项标志
  499. #[inline(always)]
  500. pub fn mmio_flags() -> Self {
  501. return Self::new()
  502. .set_user(false)
  503. .set_write(true)
  504. .set_execute(true)
  505. .set_page_cache_disable(true)
  506. .set_page_write_through(true);
  507. }
  508. }
  509. impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> {
  510. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  511. f.debug_struct("PageFlags")
  512. .field("bits", &format_args!("{:#0x}", self.data))
  513. .field("present", &self.present())
  514. .field("has_write", &self.has_write())
  515. .field("has_execute", &self.has_execute())
  516. .field("has_user", &self.has_user())
  517. .finish()
  518. }
  519. }
  520. /// 页表映射器
  521. #[derive(Hash)]
  522. pub struct PageMapper<Arch, F> {
  523. /// 页表类型
  524. table_kind: PageTableKind,
  525. /// 根页表物理地址
  526. table_paddr: PhysAddr,
  527. /// 页分配器
  528. frame_allocator: F,
  529. phantom: PhantomData<fn() -> Arch>,
  530. }
  531. impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
  532. /// 创建新的页面映射器
  533. ///
  534. /// ## 参数
  535. /// - table_kind 页表类型
  536. /// - table_paddr 根页表物理地址
  537. /// - allocator 页分配器
  538. ///
  539. /// ## 返回值
  540. ///
  541. /// 页面映射器
  542. pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self {
  543. return Self {
  544. table_kind,
  545. table_paddr,
  546. frame_allocator: allocator,
  547. phantom: PhantomData,
  548. };
  549. }
  550. /// 创建页表,并为这个页表创建页面映射器
  551. pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> {
  552. let table_paddr = allocator.allocate_one()?;
  553. // 清空页表
  554. let table_vaddr = Arch::phys_2_virt(table_paddr)?;
  555. Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE);
  556. return Some(Self::new(table_kind, table_paddr, allocator));
  557. }
  558. /// 获取当前页表的页面映射器
  559. #[inline(always)]
  560. pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self {
  561. let table_paddr = Arch::table(table_kind);
  562. return Self::new(table_kind, table_paddr, allocator);
  563. }
  564. /// 判断当前页表分配器所属的页表是否是当前页表
  565. #[inline(always)]
  566. pub fn is_current(&self) -> bool {
  567. return unsafe { self.table().phys() == Arch::table(self.table_kind) };
  568. }
  569. /// 将当前页表分配器所属的页表设置为当前页表
  570. #[inline(always)]
  571. pub unsafe fn make_current(&self) {
  572. Arch::set_table(self.table_kind, self.table_paddr);
  573. }
  574. /// 获取当前页表分配器所属的根页表的结构体
  575. #[inline(always)]
  576. pub fn table(&self) -> PageTable<Arch> {
  577. // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的
  578. return unsafe {
  579. PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1)
  580. };
  581. }
  582. /// 获取当前PageMapper所对应的页分配器实例的引用
  583. #[inline(always)]
  584. #[allow(dead_code)]
  585. pub fn allocator_ref(&self) -> &F {
  586. return &self.frame_allocator;
  587. }
  588. /// 获取当前PageMapper所对应的页分配器实例的可变引用
  589. #[inline(always)]
  590. pub fn allocator_mut(&mut self) -> &mut F {
  591. return &mut self.frame_allocator;
  592. }
  593. /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址
  594. pub unsafe fn map(
  595. &mut self,
  596. virt: VirtAddr,
  597. flags: PageFlags<Arch>,
  598. ) -> Option<PageFlush<Arch>> {
  599. compiler_fence(Ordering::SeqCst);
  600. let phys: PhysAddr = self.frame_allocator.allocate_one()?;
  601. compiler_fence(Ordering::SeqCst);
  602. page_manager_lock_irasave().insert(phys, Page::new(false));
  603. return self.map_phys(virt, phys, flags);
  604. }
  605. /// 映射一个物理页到指定的虚拟地址
  606. pub unsafe fn map_phys(
  607. &mut self,
  608. virt: VirtAddr,
  609. phys: PhysAddr,
  610. flags: PageFlags<Arch>,
  611. ) -> Option<PageFlush<Arch>> {
  612. // 验证虚拟地址和物理地址是否对齐
  613. if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
  614. kerror!(
  615. "Try to map unaligned page: virt={:?}, phys={:?}",
  616. virt,
  617. phys
  618. );
  619. return None;
  620. }
  621. let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
  622. // TODO: 验证flags是否合法
  623. // 创建页表项
  624. let entry = PageEntry::new(phys, flags);
  625. let mut table = self.table();
  626. loop {
  627. let i = table.index_of(virt)?;
  628. assert!(i < Arch::PAGE_ENTRY_NUM);
  629. if table.level() == 0 {
  630. // todo: 检查是否已经映射
  631. // 现在不检查的原因是,刚刚启动系统时,内核会映射一些页。
  632. if table.entry_mapped(i)? {
  633. kwarn!("Page {:?} already mapped", virt);
  634. }
  635. compiler_fence(Ordering::SeqCst);
  636. table.set_entry(i, entry);
  637. compiler_fence(Ordering::SeqCst);
  638. return Some(PageFlush::new(virt));
  639. } else {
  640. let next_table = table.next_level_table(i);
  641. if let Some(next_table) = next_table {
  642. table = next_table;
  643. // kdebug!("Mapping {:?} to next level table...", virt);
  644. } else {
  645. // 分配下一级页表
  646. let frame = self.frame_allocator.allocate_one()?;
  647. // 清空这个页帧
  648. MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
  649. // 设置页表项的flags
  650. let flags: PageFlags<Arch> =
  651. PageFlags::new_page_table(virt.kind() == PageTableKind::User);
  652. // kdebug!("Flags: {:?}", flags);
  653. // 把新分配的页表映射到当前页表
  654. table.set_entry(i, PageEntry::new(frame, flags));
  655. // 获取新分配的页表
  656. table = table.next_level_table(i)?;
  657. }
  658. }
  659. }
  660. }
  661. /// 将物理地址映射到具有线性偏移量的虚拟地址
  662. #[allow(dead_code)]
  663. pub unsafe fn map_linearly(
  664. &mut self,
  665. phys: PhysAddr,
  666. flags: PageFlags<Arch>,
  667. ) -> Option<(VirtAddr, PageFlush<Arch>)> {
  668. let virt: VirtAddr = Arch::phys_2_virt(phys)?;
  669. return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
  670. }
  671. /// 修改虚拟地址的页表项的flags,并返回页表项刷新器
  672. ///
  673. /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效
  674. ///
  675. /// ## 参数
  676. /// - virt 虚拟地址
  677. /// - flags 新的页表项的flags
  678. ///
  679. /// ## 返回值
  680. ///
  681. /// 如果修改成功,返回刷新器,否则返回None
  682. pub unsafe fn remap(
  683. &mut self,
  684. virt: VirtAddr,
  685. flags: PageFlags<Arch>,
  686. ) -> Option<PageFlush<Arch>> {
  687. return self
  688. .visit(virt, |p1, i| {
  689. let mut entry = p1.entry(i)?;
  690. entry.set_flags(flags);
  691. p1.set_entry(i, entry);
  692. Some(PageFlush::new(virt))
  693. })
  694. .flatten();
  695. }
  696. /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags
  697. ///
  698. /// ## 参数
  699. ///
  700. /// - virt 虚拟地址
  701. ///
  702. /// ## 返回值
  703. ///
  704. /// 如果查找成功,返回物理地址和页表项的flags,否则返回None
  705. pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> {
  706. let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
  707. let paddr = entry.address().ok()?;
  708. let flags = entry.flags();
  709. return Some((paddr, flags));
  710. }
  711. /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器
  712. ///
  713. /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效
  714. ///
  715. /// ## 参数
  716. ///
  717. /// - virt 虚拟地址
  718. /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
  719. ///
  720. /// ## 返回值
  721. /// 如果取消成功,返回刷新器,否则返回None
  722. #[allow(dead_code)]
  723. pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> {
  724. let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?;
  725. self.frame_allocator.free_one(paddr);
  726. return Some(flusher);
  727. }
  728. /// 取消虚拟地址的映射,并返回物理地址和页表项的flags
  729. ///
  730. /// ## 参数
  731. ///
  732. /// - vaddr 虚拟地址
  733. /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
  734. ///
  735. /// ## 返回值
  736. ///
  737. /// 如果取消成功,返回物理地址和页表项的flags,否则返回None
  738. pub unsafe fn unmap_phys(
  739. &mut self,
  740. virt: VirtAddr,
  741. unmap_parents: bool,
  742. ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> {
  743. if !virt.check_aligned(Arch::PAGE_SIZE) {
  744. kerror!("Try to unmap unaligned page: virt={:?}", virt);
  745. return None;
  746. }
  747. let table = self.table();
  748. return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut())
  749. .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt)));
  750. }
  751. /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F
  752. fn visit<T>(
  753. &self,
  754. virt: VirtAddr,
  755. f: impl FnOnce(&mut PageTable<Arch>, usize) -> T,
  756. ) -> Option<T> {
  757. let mut table = self.table();
  758. unsafe {
  759. loop {
  760. let i = table.index_of(virt)?;
  761. if table.level() == 0 {
  762. return Some(f(&mut table, i));
  763. } else {
  764. table = table.next_level_table(i)?;
  765. }
  766. }
  767. }
  768. }
  769. }
  770. /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】
  771. ///
  772. /// ## 参数
  773. ///
  774. /// - vaddr 虚拟地址
  775. /// - table 页表
  776. /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
  777. /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内)
  778. ///
  779. /// ## 返回值
  780. ///
  781. /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None
  782. unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
  783. vaddr: VirtAddr,
  784. table: &PageTable<Arch>,
  785. unmap_parents: bool,
  786. allocator: &mut impl FrameAllocator,
  787. ) -> Option<(PhysAddr, PageFlags<Arch>)> {
  788. // 获取页表项的索引
  789. let i = table.index_of(vaddr)?;
  790. // 如果当前是最后一级页表,直接取消页面映射
  791. if table.level() == 0 {
  792. let entry = table.entry(i)?;
  793. table.set_entry(i, PageEntry::from_usize(0));
  794. return Some((entry.address().ok()?, entry.flags()));
  795. }
  796. let subtable = table.next_level_table(i)?;
  797. // 递归地取消映射
  798. let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?;
  799. // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables,
  800. // as these mappings may become out of sync
  801. if unmap_parents {
  802. // 如果子页表已经没有映射的页面了,就取消子页表的映射
  803. // 检查子页表中是否还有映射的页面
  804. let x = (0..Arch::PAGE_ENTRY_NUM)
  805. .map(|k| subtable.entry(k).expect("invalid page entry"))
  806. .any(|e| e.present());
  807. if !x {
  808. // 如果没有,就取消子页表的映射
  809. table.set_entry(i, PageEntry::from_usize(0));
  810. // 释放子页表
  811. allocator.free_one(subtable.phys());
  812. }
  813. }
  814. return Some(result);
  815. }
  816. impl<Arch, F: Debug> Debug for PageMapper<Arch, F> {
  817. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  818. f.debug_struct("PageMapper")
  819. .field("table_paddr", &self.table_paddr)
  820. .field("frame_allocator", &self.frame_allocator)
  821. .finish()
  822. }
  823. }
  824. /// 页表刷新器的trait
  825. pub trait Flusher<Arch: MemoryManagementArch> {
  826. /// 取消对指定的page flusher的刷新
  827. fn consume(&mut self, flush: PageFlush<Arch>);
  828. }
  829. /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法,
  830. /// 否则会造成对页表的更改被忽略,这是不安全的
  831. #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
  832. pub struct PageFlush<Arch: MemoryManagementArch> {
  833. virt: VirtAddr,
  834. phantom: PhantomData<Arch>,
  835. }
  836. impl<Arch: MemoryManagementArch> PageFlush<Arch> {
  837. pub fn new(virt: VirtAddr) -> Self {
  838. return Self {
  839. virt,
  840. phantom: PhantomData,
  841. };
  842. }
  843. pub fn flush(self) {
  844. unsafe { Arch::invalidate_page(self.virt) };
  845. }
  846. /// 忽略掉这个刷新器
  847. pub unsafe fn ignore(self) {
  848. mem::forget(self);
  849. }
  850. }
  851. impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> {
  852. fn drop(&mut self) {
  853. unsafe {
  854. MMArch::invalidate_page(self.virt);
  855. }
  856. }
  857. }
  858. /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法,
  859. /// 否则会造成对页表的更改被忽略,这是不安全的
  860. #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
  861. pub struct PageFlushAll<Arch: MemoryManagementArch> {
  862. phantom: PhantomData<fn() -> Arch>,
  863. }
  864. #[allow(dead_code)]
  865. impl<Arch: MemoryManagementArch> PageFlushAll<Arch> {
  866. pub fn new() -> Self {
  867. return Self {
  868. phantom: PhantomData,
  869. };
  870. }
  871. pub fn flush(self) {
  872. unsafe { Arch::invalidate_all() };
  873. }
  874. /// 忽略掉这个刷新器
  875. pub unsafe fn ignore(self) {
  876. mem::forget(self);
  877. }
  878. }
  879. impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> {
  880. /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了)
  881. fn consume(&mut self, flush: PageFlush<Arch>) {
  882. unsafe { flush.ignore() };
  883. }
  884. }
  885. impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T {
  886. /// 允许一个flusher consume掉另一个flusher
  887. fn consume(&mut self, flush: PageFlush<Arch>) {
  888. <T as Flusher<Arch>>::consume(self, flush);
  889. }
  890. }
  891. impl<Arch: MemoryManagementArch> Flusher<Arch> for () {
  892. fn consume(&mut self, _flush: PageFlush<Arch>) {}
  893. }
  894. impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> {
  895. fn drop(&mut self) {
  896. unsafe {
  897. Arch::invalidate_all();
  898. }
  899. }
  900. }
  901. /// 未在当前CPU上激活的页表的刷新器
  902. ///
  903. /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表
  904. ///
  905. /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销)
  906. #[derive(Debug)]
  907. pub struct InactiveFlusher;
  908. impl InactiveFlusher {
  909. pub fn new() -> Self {
  910. return Self {};
  911. }
  912. }
  913. impl Flusher<MMArch> for InactiveFlusher {
  914. fn consume(&mut self, flush: PageFlush<MMArch>) {
  915. unsafe {
  916. flush.ignore();
  917. }
  918. }
  919. }
  920. impl Drop for InactiveFlusher {
  921. fn drop(&mut self) {
  922. // 发送刷新页表的IPI
  923. send_ipi(IpiKind::FlushTLB, IpiTarget::Other);
  924. }
  925. }
  926. /// # 把一个地址向下对齐到页大小
  927. pub fn round_down_to_page_size(addr: usize) -> usize {
  928. addr & !(MMArch::PAGE_SIZE - 1)
  929. }
  930. /// # 把一个地址向上对齐到页大小
  931. pub fn round_up_to_page_size(addr: usize) -> usize {
  932. round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1)
  933. }