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