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, INITIAL_PGTABLE_VALUE}; 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 = (1 << 1); 109 110 const ENTRY_FLAG_WRITEABLE: usize = (1 << 2); 111 112 const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1); 113 114 const ENTRY_FLAG_USER: usize = (1 << 4); 115 const ENTRY_ADDRESS_MASK: usize = Self::ENTRY_ADDRESS_SIZE - (1 << 10); 116 const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61); 117 118 const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61); 119 120 const ENTRY_FLAG_NO_EXEC: usize = 0; 121 122 const ENTRY_FLAG_EXEC: usize = (1 << 3); 123 const ENTRY_FLAG_ACCESSED: usize = (1 << 6); 124 const ENTRY_FLAG_DIRTY: usize = (1 << 7); 125 const ENTRY_FLAG_GLOBAL: usize = (1 << 5); 126 127 const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000; 128 const KERNEL_LINK_OFFSET: usize = 0x1000000; 129 130 const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff); 131 132 const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff); 133 134 const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000); 135 136 /// 在距离sv39的顶端还有64M的位置,设置为FIXMAP的起始地址 137 const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_fc00_0000); 138 /// 设置1MB的fixmap空间 139 const FIXMAP_SIZE: usize = 256 * 4096; 140 141 /// 在距离sv39的顶端还有2G的位置,设置为MMIO空间的起始地址 142 const MMIO_BASE: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000); 143 /// 设置1g的MMIO空间 144 const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT; 145 146 const ENTRY_FLAG_HUGE_PAGE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READWRITE; 147 148 #[inline(never)] 149 unsafe fn init() { 150 riscv_mm_init().expect("init kernel memory management architecture failed"); 151 } 152 153 unsafe fn arch_post_init() { 154 // 映射fdt 155 open_firmware_fdt_driver() 156 .map_fdt() 157 .expect("openfirmware map fdt failed"); 158 } 159 160 unsafe fn invalidate_page(address: VirtAddr) { 161 riscv::asm::sfence_vma(0, address.data()); 162 } 163 164 unsafe fn invalidate_all() { 165 riscv::asm::sfence_vma_all(); 166 } 167 168 unsafe fn table(_table_kind: PageTableKind) -> PhysAddr { 169 // phys page number 170 let ppn = riscv::register::satp::read().ppn(); 171 172 let paddr = PhysPageFrame::from_ppn(ppn).phys_address(); 173 174 return paddr; 175 } 176 177 unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) { 178 let ppn = PhysPageFrame::new(table).ppn(); 179 riscv::asm::sfence_vma_all(); 180 satp::set(satp::Mode::Sv39, 0, ppn); 181 } 182 183 fn virt_is_valid(virt: VirtAddr) -> bool { 184 virt.is_canonical() 185 } 186 187 fn initial_page_table() -> PhysAddr { 188 unsafe { INITIAL_PGTABLE_VALUE } 189 } 190 191 fn setup_new_usermapper() -> Result<UserMapper, SystemError> { 192 let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe { 193 PageMapper::create(PageTableKind::User, LockedFrameAllocator) 194 .ok_or(SystemError::ENOMEM)? 195 }; 196 197 let current_ktable: KernelMapper = KernelMapper::lock(); 198 let copy_mapping = |pml4_entry_no| unsafe { 199 let entry: PageEntry<RiscV64MMArch> = current_ktable 200 .table() 201 .entry(pml4_entry_no) 202 .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no)); 203 new_umapper.table().set_entry(pml4_entry_no, entry) 204 }; 205 206 // 复制内核的映射 207 for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 { 208 copy_mapping(pml4_entry_no); 209 } 210 211 return Ok(crate::mm::ucontext::UserMapper::new(new_umapper)); 212 } 213 214 unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> { 215 // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系 216 // 因此这里需要特殊处理 217 if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA { 218 let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA); 219 return Some(r); 220 } 221 222 if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) { 223 return Some(VirtAddr::new(vaddr)); 224 } else { 225 return None; 226 } 227 } 228 229 unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> { 230 if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA { 231 let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA); 232 return Some(r); 233 } 234 235 if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) { 236 let r = PhysAddr::new(paddr); 237 return Some(r); 238 } else { 239 return None; 240 } 241 } 242 243 fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { 244 let ppn = PhysPageFrame::new(paddr).ppn(); 245 let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags; 246 return r; 247 } 248 249 fn vma_access_permitted( 250 _vma: alloc::sync::Arc<crate::mm::ucontext::LockedVMA>, 251 _write: bool, 252 _execute: bool, 253 _foreign: bool, 254 ) -> bool { 255 true 256 } 257 } 258 259 impl VirtAddr { 260 /// 判断虚拟地址是否合法 261 #[inline(always)] 262 pub fn is_canonical(self) -> bool { 263 let x = self.data() & RiscV64MMArch::PHYS_OFFSET; 264 // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址 265 // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址 266 return x == 0 || x == RiscV64MMArch::PHYS_OFFSET; 267 } 268 } 269 270 /// 获取内核地址默认的页面标志 271 pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> { 272 PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE) 273 .set_user(false) 274 .set_execute(true) 275 } 276 277 /// 全局的页帧分配器 278 #[derive(Debug, Clone, Copy, Hash)] 279 pub struct LockedFrameAllocator; 280 281 impl FrameAllocator for LockedFrameAllocator { 282 unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 283 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 284 return allocator.allocate(count); 285 } else { 286 return None; 287 } 288 } 289 290 unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) { 291 assert!(count.data().is_power_of_two()); 292 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 293 return allocator.free(address, count); 294 } 295 } 296 297 unsafe fn usage(&self) -> PageFrameUsage { 298 if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 299 return allocator.usage(); 300 } else { 301 panic!("usage error"); 302 } 303 } 304 } 305