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