page.rs 30 KB

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