1*74ffde66SLoGin use system_error::SystemError; 2*74ffde66SLoGin 3*74ffde66SLoGin use crate::{ 4*74ffde66SLoGin arch::MMArch, 5*74ffde66SLoGin libs::{align::page_align_up, spinlock::SpinLock}, 6*74ffde66SLoGin mm::no_init::{pseudo_map_phys, pseudo_unmap_phys}, 7*74ffde66SLoGin }; 8*74ffde66SLoGin 9*74ffde66SLoGin use super::{allocator::page_frame::PageFrameCount, MemoryManagementArch, PhysAddr, VirtAddr}; 10*74ffde66SLoGin 11*74ffde66SLoGin static SLOTS: SpinLock<[Slot; EarlyIoRemap::SLOT_CNT]> = 12*74ffde66SLoGin SpinLock::new([Slot::DEFAULT; EarlyIoRemap::SLOT_CNT]); 13*74ffde66SLoGin 14*74ffde66SLoGin /// 早期IO映射机制 15*74ffde66SLoGin /// 16*74ffde66SLoGin /// 该机制在内存管理初始化之前,提供IO重映射的功能。 17*74ffde66SLoGin /// 18*74ffde66SLoGin /// ## 注意 19*74ffde66SLoGin /// 20*74ffde66SLoGin /// 该机制使用固定大小的slot来记录所有的映射, 21*74ffde66SLoGin /// 而这些映射空间是有限的,由MMArch::FIXMAP_SIZE指定 22*74ffde66SLoGin pub struct EarlyIoRemap; 23*74ffde66SLoGin 24*74ffde66SLoGin impl EarlyIoRemap { 25*74ffde66SLoGin const SLOT_CNT: usize = MMArch::FIXMAP_SIZE / MMArch::PAGE_SIZE; 26*74ffde66SLoGin 27*74ffde66SLoGin /// 把物理内存映射到虚拟内存中 28*74ffde66SLoGin /// 29*74ffde66SLoGin /// ## 说明 30*74ffde66SLoGin /// 31*74ffde66SLoGin /// 虚拟内存由early io remap机制自动分配。 32*74ffde66SLoGin /// 33*74ffde66SLoGin /// ## 参数 34*74ffde66SLoGin /// 35*74ffde66SLoGin /// - phys: 物理内存地址(需要按页对齐) 36*74ffde66SLoGin /// - size: 映射的内存大小 37*74ffde66SLoGin /// 38*74ffde66SLoGin /// ## 返回值 39*74ffde66SLoGin /// 40*74ffde66SLoGin /// - 成功: (虚拟内存地址, 映射的内存大小) 41*74ffde66SLoGin /// - Err(SystemError::ENOMEM): 可用的slot不足 42*74ffde66SLoGin /// - Err(SystemError::EINVAL): 传入的物理地址没有对齐 43*74ffde66SLoGin #[allow(dead_code)] 44*74ffde66SLoGin pub fn map(phys: PhysAddr, size: usize) -> Result<(VirtAddr, usize), SystemError> { 45*74ffde66SLoGin if phys.check_aligned(MMArch::PAGE_SIZE) == false { 46*74ffde66SLoGin return Err(SystemError::EINVAL); 47*74ffde66SLoGin } 48*74ffde66SLoGin 49*74ffde66SLoGin let mut slot_guard = SLOTS.lock(); 50*74ffde66SLoGin 51*74ffde66SLoGin let slot_count = PageFrameCount::from_bytes(page_align_up(size)) 52*74ffde66SLoGin .unwrap() 53*74ffde66SLoGin .data(); 54*74ffde66SLoGin // 寻找连续的slot 55*74ffde66SLoGin let mut start_slot = None; 56*74ffde66SLoGin for i in 0..(Self::SLOT_CNT - slot_count + 1) { 57*74ffde66SLoGin let mut is_continuous = true; 58*74ffde66SLoGin 59*74ffde66SLoGin for j in 0..slot_count { 60*74ffde66SLoGin let slot_idx = i + j; 61*74ffde66SLoGin if slot_guard[slot_idx].start_idx.is_some() { 62*74ffde66SLoGin is_continuous = false; 63*74ffde66SLoGin break; 64*74ffde66SLoGin } 65*74ffde66SLoGin } 66*74ffde66SLoGin 67*74ffde66SLoGin if is_continuous { 68*74ffde66SLoGin start_slot = Some(i); 69*74ffde66SLoGin break; 70*74ffde66SLoGin } 71*74ffde66SLoGin } 72*74ffde66SLoGin 73*74ffde66SLoGin let start_slot = start_slot.ok_or(SystemError::ENOMEM)?; 74*74ffde66SLoGin let vaddr = Self::idx_to_virt(start_slot); 75*74ffde66SLoGin // 执行映射 76*74ffde66SLoGin unsafe { pseudo_map_phys(vaddr, phys, PageFrameCount::new(slot_count)) } 77*74ffde66SLoGin 78*74ffde66SLoGin // 更新slot信息 79*74ffde66SLoGin let map_size = slot_count * MMArch::PAGE_SIZE; 80*74ffde66SLoGin for i in 0..slot_count { 81*74ffde66SLoGin let slot_idx = start_slot + i; 82*74ffde66SLoGin slot_guard[slot_idx].start_idx = Some(start_slot as u32); 83*74ffde66SLoGin 84*74ffde66SLoGin if i == 0 { 85*74ffde66SLoGin slot_guard[slot_idx].size = map_size as u32; 86*74ffde66SLoGin slot_guard[slot_idx].phys = phys; 87*74ffde66SLoGin } 88*74ffde66SLoGin } 89*74ffde66SLoGin 90*74ffde66SLoGin return Ok((vaddr, map_size)); 91*74ffde66SLoGin } 92*74ffde66SLoGin 93*74ffde66SLoGin /// 取消映射 94*74ffde66SLoGin /// 95*74ffde66SLoGin /// ## 参数 96*74ffde66SLoGin /// 97*74ffde66SLoGin /// - virt: 映射范围内的任意虚拟地址 98*74ffde66SLoGin /// 99*74ffde66SLoGin /// ## 返回值 100*74ffde66SLoGin /// 101*74ffde66SLoGin /// - Ok: 成功 102*74ffde66SLoGin /// - Err(SystemError::EINVAL): 传入的虚拟地址不在early io remap范围内, 103*74ffde66SLoGin /// 或者虚拟地址未映射 104*74ffde66SLoGin #[allow(dead_code)] 105*74ffde66SLoGin pub fn unmap(virt: VirtAddr) -> Result<(), SystemError> { 106*74ffde66SLoGin if virt < MMArch::FIXMAP_START_VADDR || virt >= MMArch::FIXMAP_END_VADDR { 107*74ffde66SLoGin return Err(SystemError::EINVAL); 108*74ffde66SLoGin } 109*74ffde66SLoGin 110*74ffde66SLoGin let mut slot_guard = SLOTS.lock(); 111*74ffde66SLoGin let mut idx = None; 112*74ffde66SLoGin 113*74ffde66SLoGin // 寻找虚拟地址对应的区域的第一个slot 114*74ffde66SLoGin for slot_idx in 0..Self::SLOT_CNT { 115*74ffde66SLoGin let slot = &mut slot_guard[slot_idx]; 116*74ffde66SLoGin if let Some(start_idx) = slot.start_idx { 117*74ffde66SLoGin if start_idx == slot_idx as u32 { 118*74ffde66SLoGin let vaddr_start = Self::idx_to_virt(start_idx as usize); 119*74ffde66SLoGin let vaddr_end = vaddr_start + slot.size as usize; 120*74ffde66SLoGin if vaddr_start <= virt && virt < vaddr_end { 121*74ffde66SLoGin // 找到区域了 122*74ffde66SLoGin idx = Some(slot_idx); 123*74ffde66SLoGin break; 124*74ffde66SLoGin } 125*74ffde66SLoGin } 126*74ffde66SLoGin } 127*74ffde66SLoGin } 128*74ffde66SLoGin 129*74ffde66SLoGin let idx = idx.ok_or(SystemError::EINVAL)?; 130*74ffde66SLoGin 131*74ffde66SLoGin let vaddr = Self::idx_to_virt(idx as usize); 132*74ffde66SLoGin let count = PageFrameCount::from_bytes(slot_guard[idx].size as usize).unwrap(); 133*74ffde66SLoGin 134*74ffde66SLoGin // 取消映射 135*74ffde66SLoGin 136*74ffde66SLoGin unsafe { pseudo_unmap_phys(vaddr, count) }; 137*74ffde66SLoGin 138*74ffde66SLoGin for i in 0..count.data() { 139*74ffde66SLoGin let slot_idx = idx + i; 140*74ffde66SLoGin let slot = &mut slot_guard[slot_idx]; 141*74ffde66SLoGin *slot = Slot::DEFAULT; 142*74ffde66SLoGin } 143*74ffde66SLoGin 144*74ffde66SLoGin todo!() 145*74ffde66SLoGin } 146*74ffde66SLoGin 147*74ffde66SLoGin /// 把slot下标转换为这个slot对应的虚拟地址 148*74ffde66SLoGin fn idx_to_virt(idx: usize) -> VirtAddr { 149*74ffde66SLoGin MMArch::FIXMAP_START_VADDR + idx * MMArch::PAGE_SIZE 150*74ffde66SLoGin } 151*74ffde66SLoGin } 152*74ffde66SLoGin 153*74ffde66SLoGin #[derive(Debug, Clone, Copy)] 154*74ffde66SLoGin struct Slot { 155*74ffde66SLoGin /// 连续映射的起始槽位号 156*74ffde66SLoGin start_idx: Option<u32>, 157*74ffde66SLoGin /// 连续映射的区域大小(仅在起始槽位中设置) 158*74ffde66SLoGin size: u32, 159*74ffde66SLoGin /// 映射的起始物理地址 160*74ffde66SLoGin phys: PhysAddr, 161*74ffde66SLoGin } 162*74ffde66SLoGin 163*74ffde66SLoGin impl Slot { 164*74ffde66SLoGin const DEFAULT: Self = Self { 165*74ffde66SLoGin start_idx: None, 166*74ffde66SLoGin size: 0, 167*74ffde66SLoGin phys: PhysAddr::new(0), 168*74ffde66SLoGin }; 169*74ffde66SLoGin } 170