1 use acpi::address; 2 use riscv::register::satp; 3 use sbi_rt::{HartMask, SbiRet}; 4 use system_error::SystemError; 5 6 use crate::{ 7 arch::MMArch, 8 kdebug, 9 libs::spinlock::SpinLock, 10 mm::{ 11 allocator::{ 12 buddy::BuddyAllocator, 13 page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame}, 14 }, 15 kernel_mapper::KernelMapper, 16 page::{PageEntry, PageFlags}, 17 ucontext::UserMapper, 18 MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 19 }, 20 smp::cpu::ProcessorId, 21 }; 22 23 use self::init::riscv_mm_init; 24 25 pub mod bump; 26 pub(super) mod init; 27 28 pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>; 29 30 /// 内核起始物理地址 31 pub(self) static mut KERNEL_BEGIN_PA: PhysAddr = PhysAddr::new(0); 32 /// 内核结束的物理地址 33 pub(self) static mut KERNEL_END_PA: PhysAddr = PhysAddr::new(0); 34 /// 内核起始虚拟地址 35 pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0); 36 /// 内核结束虚拟地址 37 pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0); 38 39 pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None); 40 41 /// RiscV64的内存管理架构结构体(sv39) 42 #[derive(Debug, Clone, Copy, Hash)] 43 pub struct RiscV64MMArch; 44 45 impl RiscV64MMArch { 46 pub const ENTRY_FLAG_GLOBAL: usize = 1 << 5; 47 48 /// 使远程cpu的TLB中,指定地址范围的页失效 49 pub fn remote_invalidate_page( 50 cpu: ProcessorId, 51 address: VirtAddr, 52 size: usize, 53 ) -> Result<(), SbiRet> { 54 let r = sbi_rt::remote_sfence_vma(Into::into(cpu), address.data(), size); 55 if r.is_ok() { 56 return Ok(()); 57 } else { 58 return Err(r); 59 } 60 } 61 62 /// 使指定远程cpu的TLB中,所有范围的页失效 63 pub fn remote_invalidate_all(cpu: ProcessorId) -> Result<(), SbiRet> { 64 let r = Self::remote_invalidate_page( 65 cpu, 66 VirtAddr::new(0), 67 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT, 68 ); 69 70 return r; 71 } 72 73 pub fn remote_invalidate_all_with_mask(mask: HartMask) -> Result<(), SbiRet> { 74 let r = sbi_rt::remote_sfence_vma(mask, 0, 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT); 75 if r.is_ok() { 76 return Ok(()); 77 } else { 78 return Err(r); 79 } 80 } 81 } 82 83 /// 内核空间起始地址在顶层页表中的索引 84 const KERNEL_TOP_PAGE_ENTRY_NO: usize = (RiscV64MMArch::PHYS_OFFSET 85 & ((1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT) - 1)) 86 >> (RiscV64MMArch::ENTRY_ADDRESS_SHIFT - RiscV64MMArch::PAGE_ENTRY_SHIFT); 87 88 impl MemoryManagementArch for RiscV64MMArch { 89 const PAGE_SHIFT: usize = 12; 90 91 const PAGE_ENTRY_SHIFT: usize = 9; 92 93 /// sv39分页只有三级 94 const PAGE_LEVELS: usize = 3; 95 96 const ENTRY_ADDRESS_SHIFT: usize = 39; 97 98 const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT 99 | Self::ENTRY_FLAG_READWRITE 100 | Self::ENTRY_FLAG_DIRTY 101 | Self::ENTRY_FLAG_ACCESSED 102 | Self::ENTRY_FLAG_GLOBAL; 103 104 const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT; 105 106 const ENTRY_FLAG_PRESENT: usize = 1 << 0; 107 108 const ENTRY_FLAG_READONLY: usize = 0; 109 110 const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1); 111 112 const ENTRY_FLAG_USER: usize = (1 << 4); 113 114 const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61); 115 116 const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61); 117 118 const ENTRY_FLAG_NO_EXEC: usize = 0; 119 120 const ENTRY_FLAG_EXEC: usize = (1 << 3); 121 const ENTRY_FLAG_ACCESSED: usize = (1 << 6); 122 const ENTRY_FLAG_DIRTY: usize = (1 << 7); 123 124 const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000; 125 const KERNEL_LINK_OFFSET: usize = 0x1000000; 126 127 const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff); 128 129 const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff); 130 131 const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000); 132 133 /// 在距离sv39的顶端还有1G的位置,设置为FIXMAP的起始地址 134 const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000); 135 /// 设置1MB的fixmap空间 136 const FIXMAP_SIZE: usize = 256 * 4096; 137 138 #[inline(never)] 139 unsafe fn init() { 140 riscv_mm_init().expect("init kernel memory management architecture failed"); 141 } 142 143 unsafe fn invalidate_page(address: VirtAddr) { 144 riscv::asm::sfence_vma(0, address.data()); 145 } 146 147 unsafe fn invalidate_all() { 148 riscv::asm::sfence_vma_all(); 149 } 150 151 unsafe fn table(_table_kind: PageTableKind) -> PhysAddr { 152 // phys page number 153 let ppn = riscv::register::satp::read().ppn(); 154 155 let paddr = PhysPageFrame::from_ppn(ppn).phys_address(); 156 157 return paddr; 158 } 159 160 unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) { 161 let ppn = PhysPageFrame::new(table).ppn(); 162 riscv::asm::sfence_vma_all(); 163 satp::set(satp::Mode::Sv39, 0, ppn); 164 } 165 166 fn virt_is_valid(virt: VirtAddr) -> bool { 167 virt.is_canonical() 168 } 169 170 fn initial_page_table() -> PhysAddr { 171 todo!() 172 } 173 174 fn setup_new_usermapper() -> Result<UserMapper, SystemError> { 175 let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe { 176 PageMapper::create(PageTableKind::User, LockedFrameAllocator) 177 .ok_or(SystemError::ENOMEM)? 178 }; 179 180 let current_ktable: KernelMapper = KernelMapper::lock(); 181 let copy_mapping = |pml4_entry_no| unsafe { 182 let entry: PageEntry<RiscV64MMArch> = current_ktable 183 .table() 184 .entry(pml4_entry_no) 185 .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no)); 186 new_umapper.table().set_entry(pml4_entry_no, entry) 187 }; 188 189 // 复制内核的映射 190 for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 { 191 copy_mapping(pml4_entry_no); 192 } 193 194 return Ok(crate::mm::ucontext::UserMapper::new(new_umapper)); 195 } 196 197 unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> { 198 // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系 199 // 因此这里需要特殊处理 200 if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA { 201 let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA); 202 return Some(r); 203 } 204 205 if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) { 206 return Some(VirtAddr::new(vaddr)); 207 } else { 208 return None; 209 } 210 } 211 212 unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> { 213 if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA { 214 let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA); 215 return Some(r); 216 } 217 218 if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) { 219 let r = PhysAddr::new(paddr); 220 return Some(r); 221 } else { 222 return None; 223 } 224 } 225 226 fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { 227 let ppn = PhysPageFrame::new(paddr).ppn(); 228 let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags; 229 return r; 230 } 231 } 232 233 impl VirtAddr { 234 /// 判断虚拟地址是否合法 235 #[inline(always)] 236 pub fn is_canonical(self) -> bool { 237 let x = self.data() & RiscV64MMArch::PHYS_OFFSET; 238 // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址 239 // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址 240 return x == 0 || x == RiscV64MMArch::PHYS_OFFSET; 241 } 242 } 243 244 /// 获取内核地址默认的页面标志 245 pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> { 246 PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE) 247 .set_user(false) 248 .set_execute(true) 249 } 250 251 /// 全局的页帧分配器 252 #[derive(Debug, Clone, Copy, Hash)] 253 pub struct LockedFrameAllocator; 254 255 impl FrameAllocator for LockedFrameAllocator { 256 unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 257 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 258 return allocator.allocate(count); 259 } else { 260 return None; 261 } 262 } 263 264 unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) { 265 assert!(count.data().is_power_of_two()); 266 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 267 return allocator.free(address, count); 268 } 269 } 270 271 unsafe fn usage(&self) -> PageFrameUsage { 272 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 273 return allocator.usage(); 274 } else { 275 panic!("usage error"); 276 } 277 } 278 } 279