17a29d4fcSLoGin use riscv::register::satp; 270f159a3SLoGin use sbi_rt::{HartMask, SbiRet}; 391e9d4abSLoGin use system_error::SystemError; 491e9d4abSLoGin 5453452ccSLoGin use crate::{ 6453452ccSLoGin arch::MMArch, 723ef2b33SLoGin driver::open_firmware::fdt::open_firmware_fdt_driver, 8453452ccSLoGin libs::spinlock::SpinLock, 9453452ccSLoGin mm::{ 10453452ccSLoGin allocator::{ 11453452ccSLoGin buddy::BuddyAllocator, 12453452ccSLoGin page_frame::{FrameAllocator, PageFrameCount, PageFrameUsage, PhysPageFrame}, 13453452ccSLoGin }, 1470f159a3SLoGin kernel_mapper::KernelMapper, 1523ef2b33SLoGin page::{PageEntry, PageFlags, PAGE_1G_SHIFT}, 1670f159a3SLoGin ucontext::UserMapper, 177a29d4fcSLoGin MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 18453452ccSLoGin }, 1970f159a3SLoGin smp::cpu::ProcessorId, 204fda81ceSLoGin }; 214fda81ceSLoGin 22f75cb0f8SLoGin use self::init::{riscv_mm_init, INITIAL_PGTABLE_VALUE}; 23453452ccSLoGin 244fda81ceSLoGin pub mod bump; 25666cffedSLoGin pub(super) mod init; 264fda81ceSLoGin 274fda81ceSLoGin pub type PageMapper = crate::mm::page::PageMapper<RiscV64MMArch, LockedFrameAllocator>; 284fda81ceSLoGin 297a29d4fcSLoGin /// 内核起始物理地址 307a29d4fcSLoGin pub(self) static mut KERNEL_BEGIN_PA: PhysAddr = PhysAddr::new(0); 317a29d4fcSLoGin /// 内核结束的物理地址 327a29d4fcSLoGin pub(self) static mut KERNEL_END_PA: PhysAddr = PhysAddr::new(0); 337a29d4fcSLoGin /// 内核起始虚拟地址 347a29d4fcSLoGin pub(self) static mut KERNEL_BEGIN_VA: VirtAddr = VirtAddr::new(0); 357a29d4fcSLoGin /// 内核结束虚拟地址 367a29d4fcSLoGin pub(self) static mut KERNEL_END_VA: VirtAddr = VirtAddr::new(0); 377a29d4fcSLoGin 38453452ccSLoGin pub(self) static INNER_ALLOCATOR: SpinLock<Option<BuddyAllocator<MMArch>>> = SpinLock::new(None); 39453452ccSLoGin 4074ffde66SLoGin /// RiscV64的内存管理架构结构体(sv39) 414fda81ceSLoGin #[derive(Debug, Clone, Copy, Hash)] 424fda81ceSLoGin pub struct RiscV64MMArch; 434fda81ceSLoGin 4492849878SLoGin impl RiscV64MMArch { 4570f159a3SLoGin /// 使远程cpu的TLB中,指定地址范围的页失效 46*0102d69fSLoGin #[allow(dead_code)] 4770f159a3SLoGin pub fn remote_invalidate_page( 4870f159a3SLoGin cpu: ProcessorId, 4970f159a3SLoGin address: VirtAddr, 5070f159a3SLoGin size: usize, 5170f159a3SLoGin ) -> Result<(), SbiRet> { 5270f159a3SLoGin let r = sbi_rt::remote_sfence_vma(Into::into(cpu), address.data(), size); 5370f159a3SLoGin if r.is_ok() { 5470f159a3SLoGin return Ok(()); 5570f159a3SLoGin } else { 5670f159a3SLoGin return Err(r); 5792849878SLoGin } 5870f159a3SLoGin } 5970f159a3SLoGin 6070f159a3SLoGin /// 使指定远程cpu的TLB中,所有范围的页失效 61*0102d69fSLoGin #[allow(dead_code)] 6270f159a3SLoGin pub fn remote_invalidate_all(cpu: ProcessorId) -> Result<(), SbiRet> { 6370f159a3SLoGin let r = Self::remote_invalidate_page( 6470f159a3SLoGin cpu, 6570f159a3SLoGin VirtAddr::new(0), 6670f159a3SLoGin 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT, 6770f159a3SLoGin ); 6870f159a3SLoGin 6970f159a3SLoGin return r; 7070f159a3SLoGin } 7170f159a3SLoGin 7270f159a3SLoGin pub fn remote_invalidate_all_with_mask(mask: HartMask) -> Result<(), SbiRet> { 7370f159a3SLoGin let r = sbi_rt::remote_sfence_vma(mask, 0, 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT); 7470f159a3SLoGin if r.is_ok() { 7570f159a3SLoGin return Ok(()); 7670f159a3SLoGin } else { 7770f159a3SLoGin return Err(r); 7870f159a3SLoGin } 7970f159a3SLoGin } 8070f159a3SLoGin } 8170f159a3SLoGin 8270f159a3SLoGin /// 内核空间起始地址在顶层页表中的索引 8370f159a3SLoGin const KERNEL_TOP_PAGE_ENTRY_NO: usize = (RiscV64MMArch::PHYS_OFFSET 8470f159a3SLoGin & ((1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT) - 1)) 8570f159a3SLoGin >> (RiscV64MMArch::ENTRY_ADDRESS_SHIFT - RiscV64MMArch::PAGE_ENTRY_SHIFT); 8670f159a3SLoGin 874fda81ceSLoGin impl MemoryManagementArch for RiscV64MMArch { 88a17651b1SMemoryShore /// riscv64暂不支持缺页中断 89a17651b1SMemoryShore const PAGE_FAULT_ENABLED: bool = false; 90a17651b1SMemoryShore 914fda81ceSLoGin const PAGE_SHIFT: usize = 12; 924fda81ceSLoGin 934fda81ceSLoGin const PAGE_ENTRY_SHIFT: usize = 9; 944fda81ceSLoGin 954fda81ceSLoGin /// sv39分页只有三级 964fda81ceSLoGin const PAGE_LEVELS: usize = 3; 974fda81ceSLoGin 984fda81ceSLoGin const ENTRY_ADDRESS_SHIFT: usize = 39; 994fda81ceSLoGin 10092849878SLoGin const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT 10192849878SLoGin | Self::ENTRY_FLAG_READWRITE 10292849878SLoGin | Self::ENTRY_FLAG_DIRTY 10392849878SLoGin | Self::ENTRY_FLAG_ACCESSED 10492849878SLoGin | Self::ENTRY_FLAG_GLOBAL; 1054fda81ceSLoGin 1064fda81ceSLoGin const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT; 1074fda81ceSLoGin 1084fda81ceSLoGin const ENTRY_FLAG_PRESENT: usize = 1 << 0; 1094fda81ceSLoGin 110471d65cfSLoGin const ENTRY_FLAG_READONLY: usize = (1 << 1); 111471d65cfSLoGin 112471d65cfSLoGin const ENTRY_FLAG_WRITEABLE: usize = (1 << 2); 1134fda81ceSLoGin 1144fda81ceSLoGin const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1); 1154fda81ceSLoGin 1164fda81ceSLoGin const ENTRY_FLAG_USER: usize = (1 << 4); 117731bc2b3SLoGin const ENTRY_ADDRESS_MASK: usize = Self::ENTRY_ADDRESS_SIZE - (1 << 10); 1184fda81ceSLoGin const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61); 1194fda81ceSLoGin 1204fda81ceSLoGin const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61); 1214fda81ceSLoGin 1224fda81ceSLoGin const ENTRY_FLAG_NO_EXEC: usize = 0; 1234fda81ceSLoGin 1244fda81ceSLoGin const ENTRY_FLAG_EXEC: usize = (1 << 3); 12592849878SLoGin const ENTRY_FLAG_ACCESSED: usize = (1 << 6); 12692849878SLoGin const ENTRY_FLAG_DIRTY: usize = (1 << 7); 127a17651b1SMemoryShore const ENTRY_FLAG_GLOBAL: usize = (1 << 5); 1284fda81ceSLoGin 1294fda81ceSLoGin const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000; 130453452ccSLoGin const KERNEL_LINK_OFFSET: usize = 0x1000000; 1314fda81ceSLoGin 1324fda81ceSLoGin const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff); 1334fda81ceSLoGin 1344fda81ceSLoGin const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff); 1354fda81ceSLoGin 1364fda81ceSLoGin const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000); 1374fda81ceSLoGin 13823ef2b33SLoGin /// 在距离sv39的顶端还有64M的位置,设置为FIXMAP的起始地址 13923ef2b33SLoGin const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_fc00_0000); 14074ffde66SLoGin /// 设置1MB的fixmap空间 14174ffde66SLoGin const FIXMAP_SIZE: usize = 256 * 4096; 14274ffde66SLoGin 14323ef2b33SLoGin /// 在距离sv39的顶端还有2G的位置,设置为MMIO空间的起始地址 14423ef2b33SLoGin const MMIO_BASE: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000); 14523ef2b33SLoGin /// 设置1g的MMIO空间 14623ef2b33SLoGin const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT; 14723ef2b33SLoGin 148a17651b1SMemoryShore const ENTRY_FLAG_HUGE_PAGE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READWRITE; 149a17651b1SMemoryShore 150453452ccSLoGin #[inline(never)] 15145626c85SLoGin unsafe fn init() { 152453452ccSLoGin riscv_mm_init().expect("init kernel memory management architecture failed"); 1534fda81ceSLoGin } 1544fda81ceSLoGin 15523ef2b33SLoGin unsafe fn arch_post_init() { 15623ef2b33SLoGin // 映射fdt 15723ef2b33SLoGin open_firmware_fdt_driver() 15823ef2b33SLoGin .map_fdt() 15923ef2b33SLoGin .expect("openfirmware map fdt failed"); 16023ef2b33SLoGin } 16123ef2b33SLoGin 1627a29d4fcSLoGin unsafe fn invalidate_page(address: VirtAddr) { 1637a29d4fcSLoGin riscv::asm::sfence_vma(0, address.data()); 1644fda81ceSLoGin } 1654fda81ceSLoGin 1664fda81ceSLoGin unsafe fn invalidate_all() { 1677a29d4fcSLoGin riscv::asm::sfence_vma_all(); 1684fda81ceSLoGin } 1694fda81ceSLoGin 1707a29d4fcSLoGin unsafe fn table(_table_kind: PageTableKind) -> PhysAddr { 1717a29d4fcSLoGin // phys page number 1727a29d4fcSLoGin let ppn = riscv::register::satp::read().ppn(); 1737a29d4fcSLoGin 1747a29d4fcSLoGin let paddr = PhysPageFrame::from_ppn(ppn).phys_address(); 1757a29d4fcSLoGin 1767a29d4fcSLoGin return paddr; 1774fda81ceSLoGin } 1784fda81ceSLoGin 1797a29d4fcSLoGin unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) { 1807a29d4fcSLoGin let ppn = PhysPageFrame::new(table).ppn(); 1817a29d4fcSLoGin riscv::asm::sfence_vma_all(); 1827a29d4fcSLoGin satp::set(satp::Mode::Sv39, 0, ppn); 1834fda81ceSLoGin } 1844fda81ceSLoGin 18570f159a3SLoGin fn virt_is_valid(virt: VirtAddr) -> bool { 1867a29d4fcSLoGin virt.is_canonical() 1874fda81ceSLoGin } 1884fda81ceSLoGin 18970f159a3SLoGin fn initial_page_table() -> PhysAddr { 190f75cb0f8SLoGin unsafe { INITIAL_PGTABLE_VALUE } 1914fda81ceSLoGin } 1924fda81ceSLoGin 19370f159a3SLoGin fn setup_new_usermapper() -> Result<UserMapper, SystemError> { 19470f159a3SLoGin let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe { 19570f159a3SLoGin PageMapper::create(PageTableKind::User, LockedFrameAllocator) 19670f159a3SLoGin .ok_or(SystemError::ENOMEM)? 19770f159a3SLoGin }; 19870f159a3SLoGin 19970f159a3SLoGin let current_ktable: KernelMapper = KernelMapper::lock(); 20070f159a3SLoGin let copy_mapping = |pml4_entry_no| unsafe { 20170f159a3SLoGin let entry: PageEntry<RiscV64MMArch> = current_ktable 20270f159a3SLoGin .table() 20370f159a3SLoGin .entry(pml4_entry_no) 20470f159a3SLoGin .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no)); 20570f159a3SLoGin new_umapper.table().set_entry(pml4_entry_no, entry) 20670f159a3SLoGin }; 20770f159a3SLoGin 20870f159a3SLoGin // 复制内核的映射 20970f159a3SLoGin for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 { 21070f159a3SLoGin copy_mapping(pml4_entry_no); 21170f159a3SLoGin } 21270f159a3SLoGin 21370f159a3SLoGin return Ok(crate::mm::ucontext::UserMapper::new(new_umapper)); 2144fda81ceSLoGin } 2157a29d4fcSLoGin 2167a29d4fcSLoGin unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> { 2177a29d4fcSLoGin // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系 2187a29d4fcSLoGin // 因此这里需要特殊处理 2197a29d4fcSLoGin if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA { 2207a29d4fcSLoGin let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA); 2217a29d4fcSLoGin return Some(r); 2227a29d4fcSLoGin } 2237a29d4fcSLoGin 2247a29d4fcSLoGin if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) { 2257a29d4fcSLoGin return Some(VirtAddr::new(vaddr)); 2267a29d4fcSLoGin } else { 2277a29d4fcSLoGin return None; 2287a29d4fcSLoGin } 2297a29d4fcSLoGin } 2307a29d4fcSLoGin 2317a29d4fcSLoGin unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> { 2327a29d4fcSLoGin if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA { 2337a29d4fcSLoGin let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA); 2347a29d4fcSLoGin return Some(r); 2357a29d4fcSLoGin } 2367a29d4fcSLoGin 2377a29d4fcSLoGin if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) { 2387a29d4fcSLoGin let r = PhysAddr::new(paddr); 2397a29d4fcSLoGin return Some(r); 2407a29d4fcSLoGin } else { 2417a29d4fcSLoGin return None; 2427a29d4fcSLoGin } 2437a29d4fcSLoGin } 2447a29d4fcSLoGin 2457a29d4fcSLoGin fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { 2467a29d4fcSLoGin let ppn = PhysPageFrame::new(paddr).ppn(); 247453452ccSLoGin let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags; 2487a29d4fcSLoGin return r; 2497a29d4fcSLoGin } 250a17651b1SMemoryShore 251a17651b1SMemoryShore fn vma_access_permitted( 252a17651b1SMemoryShore _vma: alloc::sync::Arc<crate::mm::ucontext::LockedVMA>, 253a17651b1SMemoryShore _write: bool, 254a17651b1SMemoryShore _execute: bool, 255a17651b1SMemoryShore _foreign: bool, 256a17651b1SMemoryShore ) -> bool { 257a17651b1SMemoryShore true 258a17651b1SMemoryShore } 2597a29d4fcSLoGin } 2607a29d4fcSLoGin 2617a29d4fcSLoGin impl VirtAddr { 2627a29d4fcSLoGin /// 判断虚拟地址是否合法 2637a29d4fcSLoGin #[inline(always)] 2647a29d4fcSLoGin pub fn is_canonical(self) -> bool { 2657a29d4fcSLoGin let x = self.data() & RiscV64MMArch::PHYS_OFFSET; 2667a29d4fcSLoGin // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址 2677a29d4fcSLoGin // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址 2687a29d4fcSLoGin return x == 0 || x == RiscV64MMArch::PHYS_OFFSET; 2697a29d4fcSLoGin } 2704fda81ceSLoGin } 2714fda81ceSLoGin 2724fda81ceSLoGin /// 获取内核地址默认的页面标志 273453452ccSLoGin pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> { 274453452ccSLoGin PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE) 275453452ccSLoGin .set_user(false) 276453452ccSLoGin .set_execute(true) 2774fda81ceSLoGin } 2784fda81ceSLoGin 2794fda81ceSLoGin /// 全局的页帧分配器 2804fda81ceSLoGin #[derive(Debug, Clone, Copy, Hash)] 2814fda81ceSLoGin pub struct LockedFrameAllocator; 2824fda81ceSLoGin 2834fda81ceSLoGin impl FrameAllocator for LockedFrameAllocator { 2844fda81ceSLoGin unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 285453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 286453452ccSLoGin return allocator.allocate(count); 287453452ccSLoGin } else { 288453452ccSLoGin return None; 289453452ccSLoGin } 2904fda81ceSLoGin } 2914fda81ceSLoGin 2924fda81ceSLoGin unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) { 2934fda81ceSLoGin assert!(count.data().is_power_of_two()); 294453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 295453452ccSLoGin return allocator.free(address, count); 296453452ccSLoGin } 2974fda81ceSLoGin } 2984fda81ceSLoGin 2994fda81ceSLoGin unsafe fn usage(&self) -> PageFrameUsage { 300453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 301453452ccSLoGin return allocator.usage(); 302453452ccSLoGin } else { 303453452ccSLoGin panic!("usage error"); 304453452ccSLoGin } 3054fda81ceSLoGin } 3064fda81ceSLoGin } 307