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 22453452ccSLoGin use self::init::riscv_mm_init; 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中,指定地址范围的页失效 4670f159a3SLoGin pub fn remote_invalidate_page( 4770f159a3SLoGin cpu: ProcessorId, 4870f159a3SLoGin address: VirtAddr, 4970f159a3SLoGin size: usize, 5070f159a3SLoGin ) -> Result<(), SbiRet> { 5170f159a3SLoGin let r = sbi_rt::remote_sfence_vma(Into::into(cpu), address.data(), size); 5270f159a3SLoGin if r.is_ok() { 5370f159a3SLoGin return Ok(()); 5470f159a3SLoGin } else { 5570f159a3SLoGin return Err(r); 5692849878SLoGin } 5770f159a3SLoGin } 5870f159a3SLoGin 5970f159a3SLoGin /// 使指定远程cpu的TLB中,所有范围的页失效 6070f159a3SLoGin pub fn remote_invalidate_all(cpu: ProcessorId) -> Result<(), SbiRet> { 6170f159a3SLoGin let r = Self::remote_invalidate_page( 6270f159a3SLoGin cpu, 6370f159a3SLoGin VirtAddr::new(0), 6470f159a3SLoGin 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT, 6570f159a3SLoGin ); 6670f159a3SLoGin 6770f159a3SLoGin return r; 6870f159a3SLoGin } 6970f159a3SLoGin 7070f159a3SLoGin pub fn remote_invalidate_all_with_mask(mask: HartMask) -> Result<(), SbiRet> { 7170f159a3SLoGin let r = sbi_rt::remote_sfence_vma(mask, 0, 1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT); 7270f159a3SLoGin if r.is_ok() { 7370f159a3SLoGin return Ok(()); 7470f159a3SLoGin } else { 7570f159a3SLoGin return Err(r); 7670f159a3SLoGin } 7770f159a3SLoGin } 7870f159a3SLoGin } 7970f159a3SLoGin 8070f159a3SLoGin /// 内核空间起始地址在顶层页表中的索引 8170f159a3SLoGin const KERNEL_TOP_PAGE_ENTRY_NO: usize = (RiscV64MMArch::PHYS_OFFSET 8270f159a3SLoGin & ((1 << RiscV64MMArch::ENTRY_ADDRESS_SHIFT) - 1)) 8370f159a3SLoGin >> (RiscV64MMArch::ENTRY_ADDRESS_SHIFT - RiscV64MMArch::PAGE_ENTRY_SHIFT); 8470f159a3SLoGin 854fda81ceSLoGin impl MemoryManagementArch for RiscV64MMArch { 86*a17651b1SMemoryShore /// riscv64暂不支持缺页中断 87*a17651b1SMemoryShore const PAGE_FAULT_ENABLED: bool = false; 88*a17651b1SMemoryShore 894fda81ceSLoGin const PAGE_SHIFT: usize = 12; 904fda81ceSLoGin 914fda81ceSLoGin const PAGE_ENTRY_SHIFT: usize = 9; 924fda81ceSLoGin 934fda81ceSLoGin /// sv39分页只有三级 944fda81ceSLoGin const PAGE_LEVELS: usize = 3; 954fda81ceSLoGin 964fda81ceSLoGin const ENTRY_ADDRESS_SHIFT: usize = 39; 974fda81ceSLoGin 9892849878SLoGin const ENTRY_FLAG_DEFAULT_PAGE: usize = Self::ENTRY_FLAG_PRESENT 9992849878SLoGin | Self::ENTRY_FLAG_READWRITE 10092849878SLoGin | Self::ENTRY_FLAG_DIRTY 10192849878SLoGin | Self::ENTRY_FLAG_ACCESSED 10292849878SLoGin | Self::ENTRY_FLAG_GLOBAL; 1034fda81ceSLoGin 1044fda81ceSLoGin const ENTRY_FLAG_DEFAULT_TABLE: usize = Self::ENTRY_FLAG_PRESENT; 1054fda81ceSLoGin 1064fda81ceSLoGin const ENTRY_FLAG_PRESENT: usize = 1 << 0; 1074fda81ceSLoGin 10892849878SLoGin const ENTRY_FLAG_READONLY: usize = 0; 1094fda81ceSLoGin 1104fda81ceSLoGin const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1); 1114fda81ceSLoGin 1124fda81ceSLoGin const ENTRY_FLAG_USER: usize = (1 << 4); 1134fda81ceSLoGin 1144fda81ceSLoGin const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61); 1154fda81ceSLoGin 1164fda81ceSLoGin const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61); 1174fda81ceSLoGin 1184fda81ceSLoGin const ENTRY_FLAG_NO_EXEC: usize = 0; 1194fda81ceSLoGin 1204fda81ceSLoGin const ENTRY_FLAG_EXEC: usize = (1 << 3); 12192849878SLoGin const ENTRY_FLAG_ACCESSED: usize = (1 << 6); 12292849878SLoGin const ENTRY_FLAG_DIRTY: usize = (1 << 7); 123*a17651b1SMemoryShore const ENTRY_FLAG_GLOBAL: usize = (1 << 5); 1244fda81ceSLoGin 1254fda81ceSLoGin const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000; 126453452ccSLoGin const KERNEL_LINK_OFFSET: usize = 0x1000000; 1274fda81ceSLoGin 1284fda81ceSLoGin const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff); 1294fda81ceSLoGin 1304fda81ceSLoGin const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff); 1314fda81ceSLoGin 1324fda81ceSLoGin const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000); 1334fda81ceSLoGin 13423ef2b33SLoGin /// 在距离sv39的顶端还有64M的位置,设置为FIXMAP的起始地址 13523ef2b33SLoGin const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_fc00_0000); 13674ffde66SLoGin /// 设置1MB的fixmap空间 13774ffde66SLoGin const FIXMAP_SIZE: usize = 256 * 4096; 13874ffde66SLoGin 13923ef2b33SLoGin /// 在距离sv39的顶端还有2G的位置,设置为MMIO空间的起始地址 14023ef2b33SLoGin const MMIO_BASE: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000); 14123ef2b33SLoGin /// 设置1g的MMIO空间 14223ef2b33SLoGin const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT; 14323ef2b33SLoGin 144*a17651b1SMemoryShore const ENTRY_FLAG_HUGE_PAGE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READWRITE; 145*a17651b1SMemoryShore 146453452ccSLoGin #[inline(never)] 14745626c85SLoGin unsafe fn init() { 148453452ccSLoGin riscv_mm_init().expect("init kernel memory management architecture failed"); 1494fda81ceSLoGin } 1504fda81ceSLoGin 15123ef2b33SLoGin unsafe fn arch_post_init() { 15223ef2b33SLoGin // 映射fdt 15323ef2b33SLoGin open_firmware_fdt_driver() 15423ef2b33SLoGin .map_fdt() 15523ef2b33SLoGin .expect("openfirmware map fdt failed"); 15623ef2b33SLoGin } 15723ef2b33SLoGin 1587a29d4fcSLoGin unsafe fn invalidate_page(address: VirtAddr) { 1597a29d4fcSLoGin riscv::asm::sfence_vma(0, address.data()); 1604fda81ceSLoGin } 1614fda81ceSLoGin 1624fda81ceSLoGin unsafe fn invalidate_all() { 1637a29d4fcSLoGin riscv::asm::sfence_vma_all(); 1644fda81ceSLoGin } 1654fda81ceSLoGin 1667a29d4fcSLoGin unsafe fn table(_table_kind: PageTableKind) -> PhysAddr { 1677a29d4fcSLoGin // phys page number 1687a29d4fcSLoGin let ppn = riscv::register::satp::read().ppn(); 1697a29d4fcSLoGin 1707a29d4fcSLoGin let paddr = PhysPageFrame::from_ppn(ppn).phys_address(); 1717a29d4fcSLoGin 1727a29d4fcSLoGin return paddr; 1734fda81ceSLoGin } 1744fda81ceSLoGin 1757a29d4fcSLoGin unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) { 1767a29d4fcSLoGin let ppn = PhysPageFrame::new(table).ppn(); 1777a29d4fcSLoGin riscv::asm::sfence_vma_all(); 1787a29d4fcSLoGin satp::set(satp::Mode::Sv39, 0, ppn); 1794fda81ceSLoGin } 1804fda81ceSLoGin 18170f159a3SLoGin fn virt_is_valid(virt: VirtAddr) -> bool { 1827a29d4fcSLoGin virt.is_canonical() 1834fda81ceSLoGin } 1844fda81ceSLoGin 18570f159a3SLoGin fn initial_page_table() -> PhysAddr { 1864fda81ceSLoGin todo!() 1874fda81ceSLoGin } 1884fda81ceSLoGin 18970f159a3SLoGin fn setup_new_usermapper() -> Result<UserMapper, SystemError> { 19070f159a3SLoGin let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe { 19170f159a3SLoGin PageMapper::create(PageTableKind::User, LockedFrameAllocator) 19270f159a3SLoGin .ok_or(SystemError::ENOMEM)? 19370f159a3SLoGin }; 19470f159a3SLoGin 19570f159a3SLoGin let current_ktable: KernelMapper = KernelMapper::lock(); 19670f159a3SLoGin let copy_mapping = |pml4_entry_no| unsafe { 19770f159a3SLoGin let entry: PageEntry<RiscV64MMArch> = current_ktable 19870f159a3SLoGin .table() 19970f159a3SLoGin .entry(pml4_entry_no) 20070f159a3SLoGin .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no)); 20170f159a3SLoGin new_umapper.table().set_entry(pml4_entry_no, entry) 20270f159a3SLoGin }; 20370f159a3SLoGin 20470f159a3SLoGin // 复制内核的映射 20570f159a3SLoGin for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 { 20670f159a3SLoGin copy_mapping(pml4_entry_no); 20770f159a3SLoGin } 20870f159a3SLoGin 20970f159a3SLoGin return Ok(crate::mm::ucontext::UserMapper::new(new_umapper)); 2104fda81ceSLoGin } 2117a29d4fcSLoGin 2127a29d4fcSLoGin unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> { 2137a29d4fcSLoGin // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系 2147a29d4fcSLoGin // 因此这里需要特殊处理 2157a29d4fcSLoGin if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA { 2167a29d4fcSLoGin let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA); 2177a29d4fcSLoGin return Some(r); 2187a29d4fcSLoGin } 2197a29d4fcSLoGin 2207a29d4fcSLoGin if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) { 2217a29d4fcSLoGin return Some(VirtAddr::new(vaddr)); 2227a29d4fcSLoGin } else { 2237a29d4fcSLoGin return None; 2247a29d4fcSLoGin } 2257a29d4fcSLoGin } 2267a29d4fcSLoGin 2277a29d4fcSLoGin unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> { 2287a29d4fcSLoGin if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA { 2297a29d4fcSLoGin let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA); 2307a29d4fcSLoGin return Some(r); 2317a29d4fcSLoGin } 2327a29d4fcSLoGin 2337a29d4fcSLoGin if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) { 2347a29d4fcSLoGin let r = PhysAddr::new(paddr); 2357a29d4fcSLoGin return Some(r); 2367a29d4fcSLoGin } else { 2377a29d4fcSLoGin return None; 2387a29d4fcSLoGin } 2397a29d4fcSLoGin } 2407a29d4fcSLoGin 2417a29d4fcSLoGin fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { 2427a29d4fcSLoGin let ppn = PhysPageFrame::new(paddr).ppn(); 243453452ccSLoGin let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags; 2447a29d4fcSLoGin return r; 2457a29d4fcSLoGin } 246*a17651b1SMemoryShore 247*a17651b1SMemoryShore fn vma_access_permitted( 248*a17651b1SMemoryShore _vma: alloc::sync::Arc<crate::mm::ucontext::LockedVMA>, 249*a17651b1SMemoryShore _write: bool, 250*a17651b1SMemoryShore _execute: bool, 251*a17651b1SMemoryShore _foreign: bool, 252*a17651b1SMemoryShore ) -> bool { 253*a17651b1SMemoryShore true 254*a17651b1SMemoryShore } 2557a29d4fcSLoGin } 2567a29d4fcSLoGin 2577a29d4fcSLoGin impl VirtAddr { 2587a29d4fcSLoGin /// 判断虚拟地址是否合法 2597a29d4fcSLoGin #[inline(always)] 2607a29d4fcSLoGin pub fn is_canonical(self) -> bool { 2617a29d4fcSLoGin let x = self.data() & RiscV64MMArch::PHYS_OFFSET; 2627a29d4fcSLoGin // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址 2637a29d4fcSLoGin // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址 2647a29d4fcSLoGin return x == 0 || x == RiscV64MMArch::PHYS_OFFSET; 2657a29d4fcSLoGin } 2664fda81ceSLoGin } 2674fda81ceSLoGin 2684fda81ceSLoGin /// 获取内核地址默认的页面标志 269453452ccSLoGin pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> { 270453452ccSLoGin PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE) 271453452ccSLoGin .set_user(false) 272453452ccSLoGin .set_execute(true) 2734fda81ceSLoGin } 2744fda81ceSLoGin 2754fda81ceSLoGin /// 全局的页帧分配器 2764fda81ceSLoGin #[derive(Debug, Clone, Copy, Hash)] 2774fda81ceSLoGin pub struct LockedFrameAllocator; 2784fda81ceSLoGin 2794fda81ceSLoGin impl FrameAllocator for LockedFrameAllocator { 2804fda81ceSLoGin unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 281453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 282453452ccSLoGin return allocator.allocate(count); 283453452ccSLoGin } else { 284453452ccSLoGin return None; 285453452ccSLoGin } 2864fda81ceSLoGin } 2874fda81ceSLoGin 2884fda81ceSLoGin unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) { 2894fda81ceSLoGin assert!(count.data().is_power_of_two()); 290453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 291453452ccSLoGin return allocator.free(address, count); 292453452ccSLoGin } 2934fda81ceSLoGin } 2944fda81ceSLoGin 2954fda81ceSLoGin unsafe fn usage(&self) -> PageFrameUsage { 296453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 297453452ccSLoGin return allocator.usage(); 298453452ccSLoGin } else { 299453452ccSLoGin panic!("usage error"); 300453452ccSLoGin } 3014fda81ceSLoGin } 3024fda81ceSLoGin } 303