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