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