xref: /DragonOS/kernel/src/arch/riscv64/mm/mod.rs (revision 453452cc02e2766a28d87dd47bdee37caddc4c44)
17a29d4fcSLoGin use riscv::register::satp;
291e9d4abSLoGin use system_error::SystemError;
391e9d4abSLoGin 
4*453452ccSLoGin use crate::{
5*453452ccSLoGin     arch::MMArch,
6*453452ccSLoGin     libs::spinlock::SpinLock,
7*453452ccSLoGin     mm::{
8*453452ccSLoGin         allocator::{
9*453452ccSLoGin             buddy::BuddyAllocator,
10*453452ccSLoGin             page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
11*453452ccSLoGin         },
124fda81ceSLoGin         page::PageFlags,
137a29d4fcSLoGin         MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
14*453452ccSLoGin     },
154fda81ceSLoGin };
164fda81ceSLoGin 
17*453452ccSLoGin use self::init::riscv_mm_init;
18*453452ccSLoGin 
194fda81ceSLoGin pub mod bump;
20666cffedSLoGin pub(super) mod init;
214fda81ceSLoGin 
224fda81ceSLoGin pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>;
234fda81ceSLoGin 
247a29d4fcSLoGin /// 内核起始物理地址
257a29d4fcSLoGin pub(self) static mut KERNEL_BEGIN_PA: PhysAddr = PhysAddr::new(0);
267a29d4fcSLoGin /// 内核结束的物理地址
277a29d4fcSLoGin pub(self) static mut KERNEL_END_PA: PhysAddr = PhysAddr::new(0);
287a29d4fcSLoGin /// 内核起始虚拟地址
297a29d4fcSLoGin pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0);
307a29d4fcSLoGin /// 内核结束虚拟地址
317a29d4fcSLoGin pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
327a29d4fcSLoGin 
33*453452ccSLoGin pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
34*453452ccSLoGin 
3574ffde66SLoGin /// RiscV64的内存管理架构结构体(sv39)
364fda81ceSLoGin #[derive(Debug, Clone, Copy, Hash)]
374fda81ceSLoGin pub struct RiscV64MMArch;
384fda81ceSLoGin 
3992849878SLoGin impl RiscV64MMArch {
4092849878SLoGin     pub const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
4192849878SLoGin }
424fda81ceSLoGin impl MemoryManagementArch for RiscV64MMArch {
434fda81ceSLoGin     const PAGE_SHIFT: usize = 12;
444fda81ceSLoGin 
454fda81ceSLoGin     const PAGE_ENTRY_SHIFT: usize = 9;
464fda81ceSLoGin 
474fda81ceSLoGin     /// sv39分页只有三级
484fda81ceSLoGin     const PAGE_LEVELS: usize = 3;
494fda81ceSLoGin 
504fda81ceSLoGin     const ENTRY_ADDRESS_SHIFT: usize = 39;
514fda81ceSLoGin 
5292849878SLoGin     const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT
5392849878SLoGin         | Self::ENTRY_FLAG_READWRITE
5492849878SLoGin         | Self::ENTRY_FLAG_DIRTY
5592849878SLoGin         | Self::ENTRY_FLAG_ACCESSED
5692849878SLoGin         | Self::ENTRY_FLAG_GLOBAL;
574fda81ceSLoGin 
584fda81ceSLoGin     const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
594fda81ceSLoGin 
604fda81ceSLoGin     const ENTRY_FLAG_PRESENT: usize = 1 << 0;
614fda81ceSLoGin 
6292849878SLoGin     const ENTRY_FLAG_READONLY: usize = 0;
634fda81ceSLoGin 
644fda81ceSLoGin     const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);
654fda81ceSLoGin 
664fda81ceSLoGin     const ENTRY_FLAG_USER: usize = (1 << 4);
674fda81ceSLoGin 
684fda81ceSLoGin     const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61);
694fda81ceSLoGin 
704fda81ceSLoGin     const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61);
714fda81ceSLoGin 
724fda81ceSLoGin     const ENTRY_FLAG_NO_EXEC: usize = 0;
734fda81ceSLoGin 
744fda81ceSLoGin     const ENTRY_FLAG_EXEC: usize = (1 << 3);
7592849878SLoGin     const ENTRY_FLAG_ACCESSED: usize = (1 << 6);
7692849878SLoGin     const ENTRY_FLAG_DIRTY: usize = (1 << 7);
774fda81ceSLoGin 
784fda81ceSLoGin     const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000;
79*453452ccSLoGin     const KERNEL_LINK_OFFSET: usize = 0x1000000;
804fda81ceSLoGin 
814fda81ceSLoGin     const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff);
824fda81ceSLoGin 
834fda81ceSLoGin     const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff);
844fda81ceSLoGin 
854fda81ceSLoGin     const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000);
864fda81ceSLoGin 
8774ffde66SLoGin     /// 在距离sv39的顶端还有1G的位置,设置为FIXMAP的起始地址
8874ffde66SLoGin     const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000);
8974ffde66SLoGin     /// 设置1MB的fixmap空间
9074ffde66SLoGin     const FIXMAP_SIZE: usize = 256 * 4096;
9174ffde66SLoGin 
92*453452ccSLoGin     #[inline(never)]
9345626c85SLoGin     unsafe fn init() {
94*453452ccSLoGin         riscv_mm_init().expect("init kernel memory management architecture failed");
954fda81ceSLoGin     }
964fda81ceSLoGin 
977a29d4fcSLoGin     unsafe fn invalidate_page(address: VirtAddr) {
987a29d4fcSLoGin         riscv::asm::sfence_vma(0, address.data());
994fda81ceSLoGin     }
1004fda81ceSLoGin 
1014fda81ceSLoGin     unsafe fn invalidate_all() {
1027a29d4fcSLoGin         riscv::asm::sfence_vma_all();
1034fda81ceSLoGin     }
1044fda81ceSLoGin 
1057a29d4fcSLoGin     unsafe fn table(_table_kind: PageTableKind) -> PhysAddr {
1067a29d4fcSLoGin         // phys page number
1077a29d4fcSLoGin         let ppn = riscv::register::satp::read().ppn();
1087a29d4fcSLoGin 
1097a29d4fcSLoGin         let paddr = PhysPageFrame::from_ppn(ppn).phys_address();
1107a29d4fcSLoGin 
1117a29d4fcSLoGin         return paddr;
1124fda81ceSLoGin     }
1134fda81ceSLoGin 
1147a29d4fcSLoGin     unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) {
1157a29d4fcSLoGin         let ppn = PhysPageFrame::new(table).ppn();
1167a29d4fcSLoGin         riscv::asm::sfence_vma_all();
1177a29d4fcSLoGin         satp::set(satp::Mode::Sv39, 0, ppn);
1184fda81ceSLoGin     }
1194fda81ceSLoGin 
1204fda81ceSLoGin     fn virt_is_valid(virt: crate::mm::VirtAddr) -> bool {
1217a29d4fcSLoGin         virt.is_canonical()
1224fda81ceSLoGin     }
1234fda81ceSLoGin 
1244fda81ceSLoGin     fn initial_page_table() -> crate::mm::PhysAddr {
1254fda81ceSLoGin         todo!()
1264fda81ceSLoGin     }
1274fda81ceSLoGin 
12891e9d4abSLoGin     fn setup_new_usermapper() -> Result<crate::mm::ucontext::UserMapper, SystemError> {
1294fda81ceSLoGin         todo!()
1304fda81ceSLoGin     }
1317a29d4fcSLoGin 
1327a29d4fcSLoGin     unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {
1337a29d4fcSLoGin         // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系
1347a29d4fcSLoGin         // 因此这里需要特殊处理
1357a29d4fcSLoGin         if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA {
1367a29d4fcSLoGin             let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA);
1377a29d4fcSLoGin             return Some(r);
1387a29d4fcSLoGin         }
1397a29d4fcSLoGin 
1407a29d4fcSLoGin         if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) {
1417a29d4fcSLoGin             return Some(VirtAddr::new(vaddr));
1427a29d4fcSLoGin         } else {
1437a29d4fcSLoGin             return None;
1447a29d4fcSLoGin         }
1457a29d4fcSLoGin     }
1467a29d4fcSLoGin 
1477a29d4fcSLoGin     unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> {
1487a29d4fcSLoGin         if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA {
1497a29d4fcSLoGin             let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA);
1507a29d4fcSLoGin             return Some(r);
1517a29d4fcSLoGin         }
1527a29d4fcSLoGin 
1537a29d4fcSLoGin         if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) {
1547a29d4fcSLoGin             let r = PhysAddr::new(paddr);
1557a29d4fcSLoGin             return Some(r);
1567a29d4fcSLoGin         } else {
1577a29d4fcSLoGin             return None;
1587a29d4fcSLoGin         }
1597a29d4fcSLoGin     }
1607a29d4fcSLoGin 
1617a29d4fcSLoGin     fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
1627a29d4fcSLoGin         let ppn = PhysPageFrame::new(paddr).ppn();
163*453452ccSLoGin         let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags;
1647a29d4fcSLoGin         return r;
1657a29d4fcSLoGin     }
1667a29d4fcSLoGin }
1677a29d4fcSLoGin 
1687a29d4fcSLoGin impl VirtAddr {
1697a29d4fcSLoGin     /// 判断虚拟地址是否合法
1707a29d4fcSLoGin     #[inline(always)]
1717a29d4fcSLoGin     pub fn is_canonical(self) -> bool {
1727a29d4fcSLoGin         let x = self.data() & RiscV64MMArch::PHYS_OFFSET;
1737a29d4fcSLoGin         // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址
1747a29d4fcSLoGin         // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址
1757a29d4fcSLoGin         return x == 0 || x == RiscV64MMArch::PHYS_OFFSET;
1767a29d4fcSLoGin     }
1774fda81ceSLoGin }
1784fda81ceSLoGin 
1794fda81ceSLoGin /// 获取内核地址默认的页面标志
180*453452ccSLoGin pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
181*453452ccSLoGin     PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
182*453452ccSLoGin         .set_user(false)
183*453452ccSLoGin         .set_execute(true)
1844fda81ceSLoGin }
1854fda81ceSLoGin 
1864fda81ceSLoGin /// 全局的页帧分配器
1874fda81ceSLoGin #[derive(Debug, Clone, Copy, Hash)]
1884fda81ceSLoGin pub struct LockedFrameAllocator;
1894fda81ceSLoGin 
1904fda81ceSLoGin impl FrameAllocator for LockedFrameAllocator {
1914fda81ceSLoGin     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
192*453452ccSLoGin         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
193*453452ccSLoGin             return allocator.allocate(count);
194*453452ccSLoGin         } else {
195*453452ccSLoGin             return None;
196*453452ccSLoGin         }
1974fda81ceSLoGin     }
1984fda81ceSLoGin 
1994fda81ceSLoGin     unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) {
2004fda81ceSLoGin         assert!(count.data().is_power_of_two());
201*453452ccSLoGin         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
202*453452ccSLoGin             return allocator.free(address, count);
203*453452ccSLoGin         }
2044fda81ceSLoGin     }
2054fda81ceSLoGin 
2064fda81ceSLoGin     unsafe fn usage(&self) -> PageFrameUsage {
207*453452ccSLoGin         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
208*453452ccSLoGin             return allocator.usage();
209*453452ccSLoGin         } else {
210*453452ccSLoGin             panic!("usage error");
211*453452ccSLoGin         }
2124fda81ceSLoGin     }
2134fda81ceSLoGin }
214