地址空间

2024-06-07

最后编辑于:2024-09-15

    #umi
    #OS
    #Rust

地址空间

数据结构

映射

struct Mapping {
    phys: Arc<Phys>,
    start_index: usize,
    attr: Attr,
}

虚拟地址空间

pub struct Virt {
    root: Mutex<Table>,
    map: Mutex<RangeMap<LAddr, Mapping>>,
    cpu_mask: AtomicUsize,

    _marker: PhantomPinned,
}
pub struct RangeMap<K, V> {
    range: Range<K>,
    map: BTreeMap<K, (K, V)>,
}

加载地址空间

#[thread_local]
static mut CUR_VIRT: *const Virt = ptr::null();

pub fn set_virt(virt: Pin<Arsc<Virt>>) -> Option<Arsc<Virt>> {
	// virt根页表指针 Pin<ptr>
    let addr = unsafe { ptr::addr_of_mut!(**virt.root.as_ptr()) };

    virt.cpu_mask.fetch_or(1 << hart_id::hart_id(), SeqCst);
    // Pin解包后的实际地址
    let new = Arsc::into_raw(unsafe { Pin::into_inner_unchecked(virt) });
    // 更新根页表
    let old = unsafe { mem::replace(&mut CUR_VIRT, new) };

    if old != new {
        let paddr = *LAddr::from(addr).to_paddr(ID_OFFSET);
        log::debug!("tlb::set_virt: {old:p} => {new:p}");
        unsafe {
	        // 更新satp,刷新vma
            satp::set(Sv39, 0, paddr >> PAGE_SHIFT);
            sfence_vma_all()
        }
        if !old.is_null() {
            let old = unsafe { Arsc::from_raw(old) };
            old.cpu_mask.fetch_and(!(1 << hart_id::hart_id()), SeqCst);
            return Some(old);
        }
    }
    None
}

Pin::into_inner_unchecked

pub async fn clear(&self) {
    let mut map = self.map.lock().await;
    let mut table = self.root.lock().await;

    let range = map.root_range();
    let range = *range.start..*range.end;
    // 使用旧的Range生成一个新的RangeMap
    let old = mem::replace(&mut *map, RangeMap::new(range.clone()));

    let count = (range.end.val() - range.start.val()) >> PAGE_SHIFT;
    let _ = table.user_unmap_npages(range.start, count, frames(), ID_OFFSET);

    for (addr, mapping) in old {
        let count: usize = (addr.end.val() - addr.start.val()) >> PAGE_SHIFT;
        for index in 0..count {
            let dirty = mapping.attr.contains(Attr::WRITABLE);
            let _ = mapping.phys.flush(index, Some(dirty), true).await;
        }
    }
}

mem::replace替换旧值,返回新值