174ffde66SLoGin use system_error::SystemError; 274ffde66SLoGin 374ffde66SLoGin use crate::{ 474ffde66SLoGin arch::MMArch, 592849878SLoGin libs::{ 692849878SLoGin align::{page_align_down, page_align_up}, 792849878SLoGin spinlock::SpinLock, 892849878SLoGin }, 97a29d4fcSLoGin mm::no_init::{pseudo_map_phys, pseudo_map_phys_ro, pseudo_unmap_phys}, 1074ffde66SLoGin }; 1174ffde66SLoGin 1274ffde66SLoGin use super::{allocator::page_frame::PageFrameCount, MemoryManagementArch, PhysAddr, VirtAddr}; 1374ffde66SLoGin 1474ffde66SLoGin static SLOTS: SpinLock<[Slot; EarlyIoRemap::SLOT_CNT]> = 1574ffde66SLoGin SpinLock::new([Slot::DEFAULT; EarlyIoRemap::SLOT_CNT]); 1674ffde66SLoGin 1774ffde66SLoGin /// 早期IO映射机制 1874ffde66SLoGin /// 1974ffde66SLoGin /// 该机制在内存管理初始化之前,提供IO重映射的功能。 2074ffde66SLoGin /// 2174ffde66SLoGin /// ## 注意 2274ffde66SLoGin /// 2374ffde66SLoGin /// 该机制使用固定大小的slot来记录所有的映射, 2474ffde66SLoGin /// 而这些映射空间是有限的,由MMArch::FIXMAP_SIZE指定 2574ffde66SLoGin pub struct EarlyIoRemap; 2674ffde66SLoGin 2774ffde66SLoGin impl EarlyIoRemap { 2874ffde66SLoGin const SLOT_CNT: usize = MMArch::FIXMAP_SIZE / MMArch::PAGE_SIZE; 2974ffde66SLoGin 3092849878SLoGin /// 把物理内存映射到虚拟内存中(物理地址不要求对齐 3192849878SLoGin /// 3292849878SLoGin /// ## 参数 3392849878SLoGin /// 3492849878SLoGin /// - phys: 物理内存地址(不需要对齐) 3592849878SLoGin /// - size: 映射的内存大小 3692849878SLoGin /// - read_only: 映射区与是否只读 3792849878SLoGin /// 3892849878SLoGin /// ## 返回值 3992849878SLoGin /// 4092849878SLoGin /// - 成功: (phys对应的虚拟内存地址) 4192849878SLoGin /// - Err(SystemError::ENOMEM): 可用的slot不足 4292849878SLoGin #[allow(dead_code)] map_not_aligned( mut phys: PhysAddr, mut size: usize, read_only: bool, ) -> Result<VirtAddr, SystemError>4392849878SLoGin pub fn map_not_aligned( 4492849878SLoGin mut phys: PhysAddr, 4592849878SLoGin mut size: usize, 4692849878SLoGin read_only: bool, 4792849878SLoGin ) -> Result<VirtAddr, SystemError> { 48*2eab6dd7S曾俊 // debug!("map not aligned phys:{phys:?}, size:{size:?}, read_only:{read_only:?}"); 4992849878SLoGin 5092849878SLoGin let offset = phys.data() - page_align_down(phys.data()); 5192849878SLoGin size += offset; 5292849878SLoGin phys -= offset; 5392849878SLoGin 5492849878SLoGin let (map_vaddr, _) = Self::map(phys, size, read_only)?; 5592849878SLoGin return Ok(map_vaddr + offset); 5692849878SLoGin } 5792849878SLoGin 5874ffde66SLoGin /// 把物理内存映射到虚拟内存中 5974ffde66SLoGin /// 6074ffde66SLoGin /// ## 说明 6174ffde66SLoGin /// 6274ffde66SLoGin /// 虚拟内存由early io remap机制自动分配。 6374ffde66SLoGin /// 6474ffde66SLoGin /// ## 参数 6574ffde66SLoGin /// 6674ffde66SLoGin /// - phys: 物理内存地址(需要按页对齐) 6774ffde66SLoGin /// - size: 映射的内存大小 687a29d4fcSLoGin /// - read_only: 映射区与是否只读 6974ffde66SLoGin /// 7074ffde66SLoGin /// ## 返回值 7174ffde66SLoGin /// 7274ffde66SLoGin /// - 成功: (虚拟内存地址, 映射的内存大小) 7374ffde66SLoGin /// - Err(SystemError::ENOMEM): 可用的slot不足 7474ffde66SLoGin /// - Err(SystemError::EINVAL): 传入的物理地址没有对齐 7574ffde66SLoGin #[allow(dead_code)] map( phys: PhysAddr, size: usize, read_only: bool, ) -> Result<(VirtAddr, usize), SystemError>767a29d4fcSLoGin pub fn map( 777a29d4fcSLoGin phys: PhysAddr, 787a29d4fcSLoGin size: usize, 797a29d4fcSLoGin read_only: bool, 807a29d4fcSLoGin ) -> Result<(VirtAddr, usize), SystemError> { 81b5b571e0SLoGin if !phys.check_aligned(MMArch::PAGE_SIZE) { 8274ffde66SLoGin return Err(SystemError::EINVAL); 8374ffde66SLoGin } 8474ffde66SLoGin 85*2eab6dd7S曾俊 // debug!("Early io remap:{phys:?}, size:{size}"); 867a29d4fcSLoGin 8774ffde66SLoGin let mut slot_guard = SLOTS.lock(); 8874ffde66SLoGin 8974ffde66SLoGin let slot_count = PageFrameCount::from_bytes(page_align_up(size)) 9074ffde66SLoGin .unwrap() 9174ffde66SLoGin .data(); 9274ffde66SLoGin // 寻找连续的slot 9374ffde66SLoGin let mut start_slot = None; 9474ffde66SLoGin for i in 0..(Self::SLOT_CNT - slot_count + 1) { 9574ffde66SLoGin let mut is_continuous = true; 9674ffde66SLoGin 9774ffde66SLoGin for j in 0..slot_count { 9874ffde66SLoGin let slot_idx = i + j; 9974ffde66SLoGin if slot_guard[slot_idx].start_idx.is_some() { 10074ffde66SLoGin is_continuous = false; 10174ffde66SLoGin break; 10274ffde66SLoGin } 10374ffde66SLoGin } 10474ffde66SLoGin 10574ffde66SLoGin if is_continuous { 10674ffde66SLoGin start_slot = Some(i); 10774ffde66SLoGin break; 10874ffde66SLoGin } 10974ffde66SLoGin } 11074ffde66SLoGin 11174ffde66SLoGin let start_slot = start_slot.ok_or(SystemError::ENOMEM)?; 11274ffde66SLoGin let vaddr = Self::idx_to_virt(start_slot); 1137a29d4fcSLoGin 114*2eab6dd7S曾俊 // debug!("start_slot:{start_slot}, vaddr: {vaddr:?}, slot_count: {slot_count:?}"); 1157a29d4fcSLoGin let page_count = PageFrameCount::new(slot_count); 11674ffde66SLoGin // 执行映射 1177a29d4fcSLoGin if read_only { 1187a29d4fcSLoGin unsafe { pseudo_map_phys_ro(vaddr, phys, page_count) } 1197a29d4fcSLoGin } else { 1207a29d4fcSLoGin unsafe { pseudo_map_phys(vaddr, phys, page_count) } 1217a29d4fcSLoGin } 1227a29d4fcSLoGin 123*2eab6dd7S曾俊 // debug!("map ok"); 12474ffde66SLoGin 12574ffde66SLoGin // 更新slot信息 12674ffde66SLoGin let map_size = slot_count * MMArch::PAGE_SIZE; 12774ffde66SLoGin for i in 0..slot_count { 12874ffde66SLoGin let slot_idx = start_slot + i; 12974ffde66SLoGin slot_guard[slot_idx].start_idx = Some(start_slot as u32); 13074ffde66SLoGin 13174ffde66SLoGin if i == 0 { 13274ffde66SLoGin slot_guard[slot_idx].size = map_size as u32; 13374ffde66SLoGin slot_guard[slot_idx].phys = phys; 13474ffde66SLoGin } 13574ffde66SLoGin } 13674ffde66SLoGin 13774ffde66SLoGin return Ok((vaddr, map_size)); 13874ffde66SLoGin } 13974ffde66SLoGin 14074ffde66SLoGin /// 取消映射 14174ffde66SLoGin /// 14274ffde66SLoGin /// ## 参数 14374ffde66SLoGin /// 14474ffde66SLoGin /// - virt: 映射范围内的任意虚拟地址 14574ffde66SLoGin /// 14674ffde66SLoGin /// ## 返回值 14774ffde66SLoGin /// 14874ffde66SLoGin /// - Ok: 成功 14974ffde66SLoGin /// - Err(SystemError::EINVAL): 传入的虚拟地址不在early io remap范围内, 15074ffde66SLoGin /// 或者虚拟地址未映射 15174ffde66SLoGin #[allow(dead_code)] unmap(virt: VirtAddr) -> Result<(), SystemError>15274ffde66SLoGin pub fn unmap(virt: VirtAddr) -> Result<(), SystemError> { 15374ffde66SLoGin if virt < MMArch::FIXMAP_START_VADDR || virt >= MMArch::FIXMAP_END_VADDR { 15474ffde66SLoGin return Err(SystemError::EINVAL); 15574ffde66SLoGin } 15674ffde66SLoGin 15774ffde66SLoGin let mut slot_guard = SLOTS.lock(); 15874ffde66SLoGin let mut idx = None; 15974ffde66SLoGin 16074ffde66SLoGin // 寻找虚拟地址对应的区域的第一个slot 16174ffde66SLoGin for slot_idx in 0..Self::SLOT_CNT { 16274ffde66SLoGin let slot = &mut slot_guard[slot_idx]; 16374ffde66SLoGin if let Some(start_idx) = slot.start_idx { 16474ffde66SLoGin if start_idx == slot_idx as u32 { 16574ffde66SLoGin let vaddr_start = Self::idx_to_virt(start_idx as usize); 16674ffde66SLoGin let vaddr_end = vaddr_start + slot.size as usize; 16774ffde66SLoGin if vaddr_start <= virt && virt < vaddr_end { 16874ffde66SLoGin // 找到区域了 16974ffde66SLoGin idx = Some(slot_idx); 17074ffde66SLoGin break; 17174ffde66SLoGin } 17274ffde66SLoGin } 17374ffde66SLoGin } 17474ffde66SLoGin } 17574ffde66SLoGin 17674ffde66SLoGin let idx = idx.ok_or(SystemError::EINVAL)?; 17774ffde66SLoGin 178b5b571e0SLoGin let vaddr = Self::idx_to_virt(idx); 17974ffde66SLoGin let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap(); 18074ffde66SLoGin 18174ffde66SLoGin // 取消映射 18274ffde66SLoGin unsafe { pseudo_unmap_phys(vaddr, count) }; 18374ffde66SLoGin 18474ffde66SLoGin for i in 0..count.data() { 18574ffde66SLoGin let slot_idx = idx + i; 18674ffde66SLoGin let slot = &mut slot_guard[slot_idx]; 18774ffde66SLoGin *slot = Slot::DEFAULT; 18874ffde66SLoGin } 18974ffde66SLoGin 1907a29d4fcSLoGin return Ok(()); 19174ffde66SLoGin } 19274ffde66SLoGin 19374ffde66SLoGin /// 把slot下标转换为这个slot对应的虚拟地址 idx_to_virt(idx: usize) -> VirtAddr19474ffde66SLoGin fn idx_to_virt(idx: usize) -> VirtAddr { 19574ffde66SLoGin MMArch::FIXMAP_START_VADDR + idx * MMArch::PAGE_SIZE 19674ffde66SLoGin } 19774ffde66SLoGin } 19874ffde66SLoGin 19974ffde66SLoGin #[derive(Debug, Clone, Copy)] 20074ffde66SLoGin struct Slot { 20174ffde66SLoGin /// 连续映射的起始槽位号 20274ffde66SLoGin start_idx: Option<u32>, 20374ffde66SLoGin /// 连续映射的区域大小(仅在起始槽位中设置) 20474ffde66SLoGin size: u32, 20574ffde66SLoGin /// 映射的起始物理地址 20674ffde66SLoGin phys: PhysAddr, 20774ffde66SLoGin } 20874ffde66SLoGin 20974ffde66SLoGin impl Slot { 21074ffde66SLoGin const DEFAULT: Self = Self { 21174ffde66SLoGin start_idx: None, 21274ffde66SLoGin size: 0, 21374ffde66SLoGin phys: PhysAddr::new(0), 21474ffde66SLoGin }; 21574ffde66SLoGin } 216