2024-06-07
最后编辑于:2024-09-15
映射
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
}
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替换旧值,返回新值