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