174ffde66SLoGin use system_error::SystemError; 274ffde66SLoGin 374ffde66SLoGin use crate::{ 474ffde66SLoGin arch::MMArch, 574ffde66SLoGin libs::{align::page_align_up, spinlock::SpinLock}, 6*7a29d4fcSLoGin mm::no_init::{pseudo_map_phys, pseudo_map_phys_ro, pseudo_unmap_phys}, 774ffde66SLoGin }; 874ffde66SLoGin 974ffde66SLoGin use super::{allocator::page_frame::PageFrameCount, MemoryManagementArch, PhysAddr, VirtAddr}; 1074ffde66SLoGin 1174ffde66SLoGin static SLOTS: SpinLock<[Slot; EarlyIoRemap::SLOT_CNT]> = 1274ffde66SLoGin SpinLock::new([Slot::DEFAULT; EarlyIoRemap::SLOT_CNT]); 1374ffde66SLoGin 1474ffde66SLoGin /// 早期IO映射机制 1574ffde66SLoGin /// 1674ffde66SLoGin /// 该机制在内存管理初始化之前,提供IO重映射的功能。 1774ffde66SLoGin /// 1874ffde66SLoGin /// ## 注意 1974ffde66SLoGin /// 2074ffde66SLoGin /// 该机制使用固定大小的slot来记录所有的映射, 2174ffde66SLoGin /// 而这些映射空间是有限的,由MMArch::FIXMAP_SIZE指定 2274ffde66SLoGin pub struct EarlyIoRemap; 2374ffde66SLoGin 2474ffde66SLoGin impl EarlyIoRemap { 2574ffde66SLoGin const SLOT_CNT: usize = MMArch::FIXMAP_SIZE / MMArch::PAGE_SIZE; 2674ffde66SLoGin 2774ffde66SLoGin /// 把物理内存映射到虚拟内存中 2874ffde66SLoGin /// 2974ffde66SLoGin /// ## 说明 3074ffde66SLoGin /// 3174ffde66SLoGin /// 虚拟内存由early io remap机制自动分配。 3274ffde66SLoGin /// 3374ffde66SLoGin /// ## 参数 3474ffde66SLoGin /// 3574ffde66SLoGin /// - phys: 物理内存地址(需要按页对齐) 3674ffde66SLoGin /// - size: 映射的内存大小 37*7a29d4fcSLoGin /// - read_only: 映射区与是否只读 3874ffde66SLoGin /// 3974ffde66SLoGin /// ## 返回值 4074ffde66SLoGin /// 4174ffde66SLoGin /// - 成功: (虚拟内存地址, 映射的内存大小) 4274ffde66SLoGin /// - Err(SystemError::ENOMEM): 可用的slot不足 4374ffde66SLoGin /// - Err(SystemError::EINVAL): 传入的物理地址没有对齐 4474ffde66SLoGin #[allow(dead_code)] 45*7a29d4fcSLoGin pub fn map( 46*7a29d4fcSLoGin phys: PhysAddr, 47*7a29d4fcSLoGin size: usize, 48*7a29d4fcSLoGin read_only: bool, 49*7a29d4fcSLoGin ) -> Result<(VirtAddr, usize), SystemError> { 5074ffde66SLoGin if phys.check_aligned(MMArch::PAGE_SIZE) == false { 5174ffde66SLoGin return Err(SystemError::EINVAL); 5274ffde66SLoGin } 5374ffde66SLoGin 54*7a29d4fcSLoGin // kdebug!("Early io remap:{phys:?}, size:{size}"); 55*7a29d4fcSLoGin 5674ffde66SLoGin let mut slot_guard = SLOTS.lock(); 5774ffde66SLoGin 5874ffde66SLoGin let slot_count = PageFrameCount::from_bytes(page_align_up(size)) 5974ffde66SLoGin .unwrap() 6074ffde66SLoGin .data(); 6174ffde66SLoGin // 寻找连续的slot 6274ffde66SLoGin let mut start_slot = None; 6374ffde66SLoGin for i in 0..(Self::SLOT_CNT - slot_count + 1) { 6474ffde66SLoGin let mut is_continuous = true; 6574ffde66SLoGin 6674ffde66SLoGin for j in 0..slot_count { 6774ffde66SLoGin let slot_idx = i + j; 6874ffde66SLoGin if slot_guard[slot_idx].start_idx.is_some() { 6974ffde66SLoGin is_continuous = false; 7074ffde66SLoGin break; 7174ffde66SLoGin } 7274ffde66SLoGin } 7374ffde66SLoGin 7474ffde66SLoGin if is_continuous { 7574ffde66SLoGin start_slot = Some(i); 7674ffde66SLoGin break; 7774ffde66SLoGin } 7874ffde66SLoGin } 7974ffde66SLoGin 8074ffde66SLoGin let start_slot = start_slot.ok_or(SystemError::ENOMEM)?; 8174ffde66SLoGin let vaddr = Self::idx_to_virt(start_slot); 82*7a29d4fcSLoGin 83*7a29d4fcSLoGin // kdebug!("start_slot:{start_slot}, vaddr: {vaddr:?}, slot_count: {slot_count:?}"); 84*7a29d4fcSLoGin let page_count = PageFrameCount::new(slot_count); 8574ffde66SLoGin // 执行映射 86*7a29d4fcSLoGin if read_only { 87*7a29d4fcSLoGin unsafe { pseudo_map_phys_ro(vaddr, phys, page_count) } 88*7a29d4fcSLoGin } else { 89*7a29d4fcSLoGin unsafe { pseudo_map_phys(vaddr, phys, page_count) } 90*7a29d4fcSLoGin } 91*7a29d4fcSLoGin 92*7a29d4fcSLoGin // kdebug!("map ok"); 9374ffde66SLoGin 9474ffde66SLoGin // 更新slot信息 9574ffde66SLoGin let map_size = slot_count * MMArch::PAGE_SIZE; 9674ffde66SLoGin for i in 0..slot_count { 9774ffde66SLoGin let slot_idx = start_slot + i; 9874ffde66SLoGin slot_guard[slot_idx].start_idx = Some(start_slot as u32); 9974ffde66SLoGin 10074ffde66SLoGin if i == 0 { 10174ffde66SLoGin slot_guard[slot_idx].size = map_size as u32; 10274ffde66SLoGin slot_guard[slot_idx].phys = phys; 10374ffde66SLoGin } 10474ffde66SLoGin } 10574ffde66SLoGin 10674ffde66SLoGin return Ok((vaddr, map_size)); 10774ffde66SLoGin } 10874ffde66SLoGin 10974ffde66SLoGin /// 取消映射 11074ffde66SLoGin /// 11174ffde66SLoGin /// ## 参数 11274ffde66SLoGin /// 11374ffde66SLoGin /// - virt: 映射范围内的任意虚拟地址 11474ffde66SLoGin /// 11574ffde66SLoGin /// ## 返回值 11674ffde66SLoGin /// 11774ffde66SLoGin /// - Ok: 成功 11874ffde66SLoGin /// - Err(SystemError::EINVAL): 传入的虚拟地址不在early io remap范围内, 11974ffde66SLoGin /// 或者虚拟地址未映射 12074ffde66SLoGin #[allow(dead_code)] 12174ffde66SLoGin pub fn unmap(virt: VirtAddr) -> Result<(), SystemError> { 12274ffde66SLoGin if virt < MMArch::FIXMAP_START_VADDR || virt >= MMArch::FIXMAP_END_VADDR { 12374ffde66SLoGin return Err(SystemError::EINVAL); 12474ffde66SLoGin } 12574ffde66SLoGin 12674ffde66SLoGin let mut slot_guard = SLOTS.lock(); 12774ffde66SLoGin let mut idx = None; 12874ffde66SLoGin 12974ffde66SLoGin // 寻找虚拟地址对应的区域的第一个slot 13074ffde66SLoGin for slot_idx in 0..Self::SLOT_CNT { 13174ffde66SLoGin let slot = &mut slot_guard[slot_idx]; 13274ffde66SLoGin if let Some(start_idx) = slot.start_idx { 13374ffde66SLoGin if start_idx == slot_idx as u32 { 13474ffde66SLoGin let vaddr_start = Self::idx_to_virt(start_idx as usize); 13574ffde66SLoGin let vaddr_end = vaddr_start + slot.size as usize; 13674ffde66SLoGin if vaddr_start <= virt && virt < vaddr_end { 13774ffde66SLoGin // 找到区域了 13874ffde66SLoGin idx = Some(slot_idx); 13974ffde66SLoGin break; 14074ffde66SLoGin } 14174ffde66SLoGin } 14274ffde66SLoGin } 14374ffde66SLoGin } 14474ffde66SLoGin 14574ffde66SLoGin let idx = idx.ok_or(SystemError::EINVAL)?; 14674ffde66SLoGin 14774ffde66SLoGin let vaddr = Self::idx_to_virt(idx as usize); 14874ffde66SLoGin let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap(); 14974ffde66SLoGin 15074ffde66SLoGin // 取消映射 15174ffde66SLoGin 15274ffde66SLoGin unsafe { pseudo_unmap_phys(vaddr, count) }; 15374ffde66SLoGin 15474ffde66SLoGin for i in 0..count.data() { 15574ffde66SLoGin let slot_idx = idx + i; 15674ffde66SLoGin let slot = &mut slot_guard[slot_idx]; 15774ffde66SLoGin *slot = Slot::DEFAULT; 15874ffde66SLoGin } 15974ffde66SLoGin 160*7a29d4fcSLoGin return Ok(()); 16174ffde66SLoGin } 16274ffde66SLoGin 16374ffde66SLoGin /// 把slot下标转换为这个slot对应的虚拟地址 16474ffde66SLoGin fn idx_to_virt(idx: usize) -> VirtAddr { 16574ffde66SLoGin MMArch::FIXMAP_START_VADDR + idx * MMArch::PAGE_SIZE 16674ffde66SLoGin } 16774ffde66SLoGin } 16874ffde66SLoGin 16974ffde66SLoGin #[derive(Debug, Clone, Copy)] 17074ffde66SLoGin struct Slot { 17174ffde66SLoGin /// 连续映射的起始槽位号 17274ffde66SLoGin start_idx: Option<u32>, 17374ffde66SLoGin /// 连续映射的区域大小(仅在起始槽位中设置) 17474ffde66SLoGin size: u32, 17574ffde66SLoGin /// 映射的起始物理地址 17674ffde66SLoGin phys: PhysAddr, 17774ffde66SLoGin } 17874ffde66SLoGin 17974ffde66SLoGin impl Slot { 18074ffde66SLoGin const DEFAULT: Self = Self { 18174ffde66SLoGin start_idx: None, 18274ffde66SLoGin size: 0, 18374ffde66SLoGin phys: PhysAddr::new(0), 18474ffde66SLoGin }; 18574ffde66SLoGin } 186