xref: /DragonOS/kernel/src/arch/riscv64/mm/mod.rs (revision a381e482cbe742b2e4bbeaacae134a8131bf3f91)
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