xref: /DragonOS/kernel/src/arch/riscv64/mm/mod.rs (revision 06560afa2aa4db352526f4be8b6262719b8b3eac)
1 use acpi::address;
2 use riscv::register::satp;
3 use sbi_rt::{HartMask, SbiRet};
4 use system_error::SystemError;
5 
6 use crate::{
7     arch::MMArch,
8     driver::open_firmware::fdt::open_firmware_fdt_driver,
9     kdebug,
10     libs::spinlock::SpinLock,
11     mm::{
12         allocator::{
13             buddy::BuddyAllocator,
14             page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame},
15         },
16         kernel_mapper::KernelMapper,
17         page::{PageEntry, PageFlags, PAGE_1G_SHIFT},
18         ucontext::UserMapper,
19         MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
20     },
21     smp::cpu::ProcessorId,
22 };
23 
24 use self::init::riscv_mm_init;
25 
26 pub mod bump;
27 pub(super) mod init;
28 
29 pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>;
30 
31 /// 内核起始物理地址
32 pub(self) static mut KERNEL_BEGIN_PA: PhysAddr = PhysAddr::new(0);
33 /// 内核结束的物理地址
34 pub(self) static mut KERNEL_END_PA: PhysAddr = PhysAddr::new(0);
35 /// 内核起始虚拟地址
36 pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0);
37 /// 内核结束虚拟地址
38 pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0);
39 
40 pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None);
41 
42 /// RiscV64的内存管理架构结构体(sv39)
43 #[derive(Debug, Clone, Copy, Hash)]
44 pub struct RiscV64MMArch;
45 
46 impl RiscV64MMArch {
47     pub const ENTRY_FLAG_GLOBAL: usize = 1 << 5;
48 
49     /// 使远程cpu的TLB中,指定地址范围的页失效
50     pub fn remote_invalidate_page(
51         cpu: ProcessorId,
52         address: VirtAddr,
53         size: usize,
54     ) -> Result<(), SbiRet> {
55         let r = sbi_rt::remote_sfence_vma(Into::into(cpu), address.data(), size);
56         if r.is_ok() {
57             return Ok(());
58         } else {
59             return Err(r);
60         }
61     }
62 
63     /// 使指定远程cpu的TLB中,所有范围的页失效
64     pub fn remote_invalidate_all(cpu: ProcessorId) -> Result<(), SbiRet> {
65         let r = Self::remote_invalidate_page(
66             cpu,
67             VirtAddr::new(0),
68             1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT,
69         );
70 
71         return r;
72     }
73 
74     pub fn remote_invalidate_all_with_mask(mask: HartMask) -> Result<(), SbiRet> {
75         let r = sbi_rt::remote_sfence_vma(mask, 0, 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT);
76         if r.is_ok() {
77             return Ok(());
78         } else {
79             return Err(r);
80         }
81     }
82 }
83 
84 /// 内核空间起始地址在顶层页表中的索引
85 const KERNEL_TOP_PAGE_ENTRY_NO: usize = (RiscV64MMArch::PHYS_OFFSET
86     & ((1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT) - 1))
87     >> (RiscV64MMArch::ENTRY_ADDRESS_SHIFT - RiscV64MMArch::PAGE_ENTRY_SHIFT);
88 
89 impl MemoryManagementArch for RiscV64MMArch {
90     const PAGE_SHIFT: usize = 12;
91 
92     const PAGE_ENTRY_SHIFT: usize = 9;
93 
94     /// sv39分页只有三级
95     const PAGE_LEVELS: usize = 3;
96 
97     const ENTRY_ADDRESS_SHIFT: usize = 39;
98 
99     const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT
100         | Self::ENTRY_FLAG_READWRITE
101         | Self::ENTRY_FLAG_DIRTY
102         | Self::ENTRY_FLAG_ACCESSED
103         | Self::ENTRY_FLAG_GLOBAL;
104 
105     const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT;
106 
107     const ENTRY_FLAG_PRESENT: usize = 1 << 0;
108 
109     const ENTRY_FLAG_READONLY: usize = 0;
110 
111     const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);
112 
113     const ENTRY_FLAG_USER: usize = (1 << 4);
114 
115     const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61);
116 
117     const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61);
118 
119     const ENTRY_FLAG_NO_EXEC: usize = 0;
120 
121     const ENTRY_FLAG_EXEC: usize = (1 << 3);
122     const ENTRY_FLAG_ACCESSED: usize = (1 << 6);
123     const ENTRY_FLAG_DIRTY: usize = (1 << 7);
124 
125     const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000;
126     const KERNEL_LINK_OFFSET: usize = 0x1000000;
127 
128     const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff);
129 
130     const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff);
131 
132     const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000);
133 
134     /// 在距离sv39的顶端还有64M的位置,设置为FIXMAP的起始地址
135     const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_fc00_0000);
136     /// 设置1MB的fixmap空间
137     const FIXMAP_SIZE: usize = 256 * 4096;
138 
139     /// 在距离sv39的顶端还有2G的位置,设置为MMIO空间的起始地址
140     const MMIO_BASE: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000);
141     /// 设置1g的MMIO空间
142     const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT;
143 
144     #[inline(never)]
145     unsafe fn init() {
146         riscv_mm_init().expect("init kernel memory management architecture failed");
147     }
148 
149     unsafe fn arch_post_init() {
150         // 映射fdt
151         open_firmware_fdt_driver()
152             .map_fdt()
153             .expect("openfirmware map fdt failed");
154     }
155 
156     unsafe fn invalidate_page(address: VirtAddr) {
157         riscv::asm::sfence_vma(0, address.data());
158     }
159 
160     unsafe fn invalidate_all() {
161         riscv::asm::sfence_vma_all();
162     }
163 
164     unsafe fn table(_table_kind: PageTableKind) -> PhysAddr {
165         // phys page number
166         let ppn = riscv::register::satp::read().ppn();
167 
168         let paddr = PhysPageFrame::from_ppn(ppn).phys_address();
169 
170         return paddr;
171     }
172 
173     unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) {
174         let ppn = PhysPageFrame::new(table).ppn();
175         riscv::asm::sfence_vma_all();
176         satp::set(satp::Mode::Sv39, 0, ppn);
177     }
178 
179     fn virt_is_valid(virt: VirtAddr) -> bool {
180         virt.is_canonical()
181     }
182 
183     fn initial_page_table() -> PhysAddr {
184         todo!()
185     }
186 
187     fn setup_new_usermapper() -> Result<UserMapper, SystemError> {
188         let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe {
189             PageMapper::create(PageTableKind::User, LockedFrameAllocator)
190                 .ok_or(SystemError::ENOMEM)?
191         };
192 
193         let current_ktable: KernelMapper = KernelMapper::lock();
194         let copy_mapping = |pml4_entry_no| unsafe {
195             let entry: PageEntry<RiscV64MMArch> = current_ktable
196                 .table()
197                 .entry(pml4_entry_no)
198                 .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no));
199             new_umapper.table().set_entry(pml4_entry_no, entry)
200         };
201 
202         // 复制内核的映射
203         for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 {
204             copy_mapping(pml4_entry_no);
205         }
206 
207         return Ok(crate::mm::ucontext::UserMapper::new(new_umapper));
208     }
209 
210     unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> {
211         // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系
212         // 因此这里需要特殊处理
213         if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA {
214             let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA);
215             return Some(r);
216         }
217 
218         if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) {
219             return Some(VirtAddr::new(vaddr));
220         } else {
221             return None;
222         }
223     }
224 
225     unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> {
226         if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA {
227             let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA);
228             return Some(r);
229         }
230 
231         if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) {
232             let r = PhysAddr::new(paddr);
233             return Some(r);
234         } else {
235             return None;
236         }
237     }
238 
239     fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize {
240         let ppn = PhysPageFrame::new(paddr).ppn();
241         let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags;
242         return r;
243     }
244 }
245 
246 impl VirtAddr {
247     /// 判断虚拟地址是否合法
248     #[inline(always)]
249     pub fn is_canonical(self) -> bool {
250         let x = self.data() & RiscV64MMArch::PHYS_OFFSET;
251         // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址
252         // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址
253         return x == 0 || x == RiscV64MMArch::PHYS_OFFSET;
254     }
255 }
256 
257 /// 获取内核地址默认的页面标志
258 pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> {
259     PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE)
260         .set_user(false)
261         .set_execute(true)
262 }
263 
264 /// 全局的页帧分配器
265 #[derive(Debug, Clone, Copy, Hash)]
266 pub struct LockedFrameAllocator;
267 
268 impl FrameAllocator for LockedFrameAllocator {
269     unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> {
270         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
271             return allocator.allocate(count);
272         } else {
273             return None;
274         }
275     }
276 
277     unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) {
278         assert!(count.data().is_power_of_two());
279         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
280             return allocator.free(address, count);
281         }
282     }
283 
284     unsafe fn usage(&self) -> PageFrameUsage {
285         if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() {
286             return allocator.usage();
287         } else {
288             panic!("usage error");
289         }
290     }
291 }
292