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 { 86a17651b1SMemoryShore /// riscv64暂不支持缺页中断 87a17651b1SMemoryShore const PAGE_FAULT_ENABLED: bool = false; 88a17651b1SMemoryShore 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 108*471d65cfSLoGin const ENTRY_FLAG_READONLY: usize = (1 << 1); 109*471d65cfSLoGin 110*471d65cfSLoGin const ENTRY_FLAG_WRITEABLE: usize = (1 << 2); 1114fda81ceSLoGin 1124fda81ceSLoGin const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1); 1134fda81ceSLoGin 1144fda81ceSLoGin const ENTRY_FLAG_USER: usize = (1 << 4); 115731bc2b3SLoGin const ENTRY_ADDRESS_MASK: usize = Self::ENTRY_ADDRESS_SIZE - (1 << 10); 1164fda81ceSLoGin const ENTRY_FLAG_WRITE_THROUGH: usize = (2 << 61); 1174fda81ceSLoGin 1184fda81ceSLoGin const ENTRY_FLAG_CACHE_DISABLE: usize = (2 << 61); 1194fda81ceSLoGin 1204fda81ceSLoGin const ENTRY_FLAG_NO_EXEC: usize = 0; 1214fda81ceSLoGin 1224fda81ceSLoGin const ENTRY_FLAG_EXEC: usize = (1 << 3); 12392849878SLoGin const ENTRY_FLAG_ACCESSED: usize = (1 << 6); 12492849878SLoGin const ENTRY_FLAG_DIRTY: usize = (1 << 7); 125a17651b1SMemoryShore const ENTRY_FLAG_GLOBAL: usize = (1 << 5); 1264fda81ceSLoGin 1274fda81ceSLoGin const PHYS_OFFSET: usize = 0xffff_ffc0_0000_0000; 128453452ccSLoGin const KERNEL_LINK_OFFSET: usize = 0x1000000; 1294fda81ceSLoGin 1304fda81ceSLoGin const USER_END_VADDR: crate::mm::VirtAddr = VirtAddr::new(0x0000_003f_ffff_ffff); 1314fda81ceSLoGin 1324fda81ceSLoGin const USER_BRK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffff_ffff); 1334fda81ceSLoGin 1344fda81ceSLoGin const USER_STACK_START: crate::mm::VirtAddr = VirtAddr::new(0x0000_001f_ffa0_0000); 1354fda81ceSLoGin 13623ef2b33SLoGin /// 在距离sv39的顶端还有64M的位置,设置为FIXMAP的起始地址 13723ef2b33SLoGin const FIXMAP_START_VADDR: VirtAddr = VirtAddr::new(0xffff_ffff_fc00_0000); 13874ffde66SLoGin /// 设置1MB的fixmap空间 13974ffde66SLoGin const FIXMAP_SIZE: usize = 256 * 4096; 14074ffde66SLoGin 14123ef2b33SLoGin /// 在距离sv39的顶端还有2G的位置,设置为MMIO空间的起始地址 14223ef2b33SLoGin const MMIO_BASE: VirtAddr = VirtAddr::new(0xffff_ffff_8000_0000); 14323ef2b33SLoGin /// 设置1g的MMIO空间 14423ef2b33SLoGin const MMIO_SIZE: usize = 1 << PAGE_1G_SHIFT; 14523ef2b33SLoGin 146a17651b1SMemoryShore const ENTRY_FLAG_HUGE_PAGE: usize = Self::ENTRY_FLAG_PRESENT | Self::ENTRY_FLAG_READWRITE; 147a17651b1SMemoryShore 148453452ccSLoGin #[inline(never)] 14945626c85SLoGin unsafe fn init() { 150453452ccSLoGin riscv_mm_init().expect("init kernel memory management architecture failed"); 1514fda81ceSLoGin } 1524fda81ceSLoGin 15323ef2b33SLoGin unsafe fn arch_post_init() { 15423ef2b33SLoGin // 映射fdt 15523ef2b33SLoGin open_firmware_fdt_driver() 15623ef2b33SLoGin .map_fdt() 15723ef2b33SLoGin .expect("openfirmware map fdt failed"); 15823ef2b33SLoGin } 15923ef2b33SLoGin 1607a29d4fcSLoGin unsafe fn invalidate_page(address: VirtAddr) { 1617a29d4fcSLoGin riscv::asm::sfence_vma(0, address.data()); 1624fda81ceSLoGin } 1634fda81ceSLoGin 1644fda81ceSLoGin unsafe fn invalidate_all() { 1657a29d4fcSLoGin riscv::asm::sfence_vma_all(); 1664fda81ceSLoGin } 1674fda81ceSLoGin 1687a29d4fcSLoGin unsafe fn table(_table_kind: PageTableKind) -> PhysAddr { 1697a29d4fcSLoGin // phys page number 1707a29d4fcSLoGin let ppn = riscv::register::satp::read().ppn(); 1717a29d4fcSLoGin 1727a29d4fcSLoGin let paddr = PhysPageFrame::from_ppn(ppn).phys_address(); 1737a29d4fcSLoGin 1747a29d4fcSLoGin return paddr; 1754fda81ceSLoGin } 1764fda81ceSLoGin 1777a29d4fcSLoGin unsafe fn set_table(_table_kind: PageTableKind, table: PhysAddr) { 1787a29d4fcSLoGin let ppn = PhysPageFrame::new(table).ppn(); 1797a29d4fcSLoGin riscv::asm::sfence_vma_all(); 1807a29d4fcSLoGin satp::set(satp::Mode::Sv39, 0, ppn); 1814fda81ceSLoGin } 1824fda81ceSLoGin 18370f159a3SLoGin fn virt_is_valid(virt: VirtAddr) -> bool { 1847a29d4fcSLoGin virt.is_canonical() 1854fda81ceSLoGin } 1864fda81ceSLoGin 18770f159a3SLoGin fn initial_page_table() -> PhysAddr { 1884fda81ceSLoGin todo!() 1894fda81ceSLoGin } 1904fda81ceSLoGin 19170f159a3SLoGin fn setup_new_usermapper() -> Result<UserMapper, SystemError> { 19270f159a3SLoGin let new_umapper: crate::mm::page::PageMapper<MMArch, LockedFrameAllocator> = unsafe { 19370f159a3SLoGin PageMapper::create(PageTableKind::User, LockedFrameAllocator) 19470f159a3SLoGin .ok_or(SystemError::ENOMEM)? 19570f159a3SLoGin }; 19670f159a3SLoGin 19770f159a3SLoGin let current_ktable: KernelMapper = KernelMapper::lock(); 19870f159a3SLoGin let copy_mapping = |pml4_entry_no| unsafe { 19970f159a3SLoGin let entry: PageEntry<RiscV64MMArch> = current_ktable 20070f159a3SLoGin .table() 20170f159a3SLoGin .entry(pml4_entry_no) 20270f159a3SLoGin .unwrap_or_else(|| panic!("entry {} not found", pml4_entry_no)); 20370f159a3SLoGin new_umapper.table().set_entry(pml4_entry_no, entry) 20470f159a3SLoGin }; 20570f159a3SLoGin 20670f159a3SLoGin // 复制内核的映射 20770f159a3SLoGin for pml4_entry_no in KERNEL_TOP_PAGE_ENTRY_NO..512 { 20870f159a3SLoGin copy_mapping(pml4_entry_no); 20970f159a3SLoGin } 21070f159a3SLoGin 21170f159a3SLoGin return Ok(crate::mm::ucontext::UserMapper::new(new_umapper)); 2124fda81ceSLoGin } 2137a29d4fcSLoGin 2147a29d4fcSLoGin unsafe fn phys_2_virt(phys: PhysAddr) -> Option<VirtAddr> { 2157a29d4fcSLoGin // riscv的内核文件所占用的空间,由于重定位而导致不满足线性偏移量的关系 2167a29d4fcSLoGin // 因此这里需要特殊处理 2177a29d4fcSLoGin if phys >= KERNEL_BEGIN_PA && phys < KERNEL_END_PA { 2187a29d4fcSLoGin let r = KERNEL_BEGIN_VA + (phys - KERNEL_BEGIN_PA); 2197a29d4fcSLoGin return Some(r); 2207a29d4fcSLoGin } 2217a29d4fcSLoGin 2227a29d4fcSLoGin if let Some(vaddr) = phys.data().checked_add(Self::PHYS_OFFSET) { 2237a29d4fcSLoGin return Some(VirtAddr::new(vaddr)); 2247a29d4fcSLoGin } else { 2257a29d4fcSLoGin return None; 2267a29d4fcSLoGin } 2277a29d4fcSLoGin } 2287a29d4fcSLoGin 2297a29d4fcSLoGin unsafe fn virt_2_phys(virt: VirtAddr) -> Option<PhysAddr> { 2307a29d4fcSLoGin if virt >= KERNEL_BEGIN_VA && virt < KERNEL_END_VA { 2317a29d4fcSLoGin let r = KERNEL_BEGIN_PA + (virt - KERNEL_BEGIN_VA); 2327a29d4fcSLoGin return Some(r); 2337a29d4fcSLoGin } 2347a29d4fcSLoGin 2357a29d4fcSLoGin if let Some(paddr) = virt.data().checked_sub(Self::PHYS_OFFSET) { 2367a29d4fcSLoGin let r = PhysAddr::new(paddr); 2377a29d4fcSLoGin return Some(r); 2387a29d4fcSLoGin } else { 2397a29d4fcSLoGin return None; 2407a29d4fcSLoGin } 2417a29d4fcSLoGin } 2427a29d4fcSLoGin 2437a29d4fcSLoGin fn make_entry(paddr: PhysAddr, page_flags: usize) -> usize { 2447a29d4fcSLoGin let ppn = PhysPageFrame::new(paddr).ppn(); 245453452ccSLoGin let r = ((ppn & ((1 << 54) - 1)) << 10) | page_flags; 2467a29d4fcSLoGin return r; 2477a29d4fcSLoGin } 248a17651b1SMemoryShore 249a17651b1SMemoryShore fn vma_access_permitted( 250a17651b1SMemoryShore _vma: alloc::sync::Arc<crate::mm::ucontext::LockedVMA>, 251a17651b1SMemoryShore _write: bool, 252a17651b1SMemoryShore _execute: bool, 253a17651b1SMemoryShore _foreign: bool, 254a17651b1SMemoryShore ) -> bool { 255a17651b1SMemoryShore true 256a17651b1SMemoryShore } 2577a29d4fcSLoGin } 2587a29d4fcSLoGin 2597a29d4fcSLoGin impl VirtAddr { 2607a29d4fcSLoGin /// 判断虚拟地址是否合法 2617a29d4fcSLoGin #[inline(always)] 2627a29d4fcSLoGin pub fn is_canonical(self) -> bool { 2637a29d4fcSLoGin let x = self.data() & RiscV64MMArch::PHYS_OFFSET; 2647a29d4fcSLoGin // 如果x为0,说明虚拟地址的高位为0,是合法的用户地址 2657a29d4fcSLoGin // 如果x为PHYS_OFFSET,说明虚拟地址的高位全为1,是合法的内核地址 2667a29d4fcSLoGin return x == 0 || x == RiscV64MMArch::PHYS_OFFSET; 2677a29d4fcSLoGin } 2684fda81ceSLoGin } 2694fda81ceSLoGin 2704fda81ceSLoGin /// 获取内核地址默认的页面标志 271453452ccSLoGin pub unsafe fn kernel_page_flags<A: MemoryManagementArch>(_virt: VirtAddr) -> PageFlags<A> { 272453452ccSLoGin PageFlags::from_data(RiscV64MMArch::ENTRY_FLAG_DEFAULT_PAGE) 273453452ccSLoGin .set_user(false) 274453452ccSLoGin .set_execute(true) 2754fda81ceSLoGin } 2764fda81ceSLoGin 2774fda81ceSLoGin /// 全局的页帧分配器 2784fda81ceSLoGin #[derive(Debug, Clone, Copy, Hash)] 2794fda81ceSLoGin pub struct LockedFrameAllocator; 2804fda81ceSLoGin 2814fda81ceSLoGin impl FrameAllocator for LockedFrameAllocator { 2824fda81ceSLoGin unsafe fn allocate(&mut self, count: PageFrameCount) -> Option<(PhysAddr, PageFrameCount)> { 283453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 284453452ccSLoGin return allocator.allocate(count); 285453452ccSLoGin } else { 286453452ccSLoGin return None; 287453452ccSLoGin } 2884fda81ceSLoGin } 2894fda81ceSLoGin 2904fda81ceSLoGin unsafe fn free(&mut self, address: crate::mm::PhysAddr, count: PageFrameCount) { 2914fda81ceSLoGin assert!(count.data().is_power_of_two()); 292453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 293453452ccSLoGin return allocator.free(address, count); 294453452ccSLoGin } 2954fda81ceSLoGin } 2964fda81ceSLoGin 2974fda81ceSLoGin unsafe fn usage(&self) -> PageFrameUsage { 298453452ccSLoGin if let Some(ref mut allocator) = *INNER_ALLOCATOR.lock_irqsave() { 299453452ccSLoGin return allocator.usage(); 300453452ccSLoGin } else { 301453452ccSLoGin panic!("usage error"); 302453452ccSLoGin } 3034fda81ceSLoGin } 3044fda81ceSLoGin } 305