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