use crate::{
mm::{
Frame, FrameAllocOptions, PAGE_SIZE, Paddr,
frame::max_paddr,
kspace::{
LINEAR_MAPPING_BASE_VADDR, MappedItemRef, VMALLOC_VADDR_RANGE, kvirt_area::KVirtArea,
paddr_to_vaddr,
},
page_prop::{CachePolicy, PageFlags, PageProperty},
},
prelude::*,
task::disable_preempt,
};
fn default_prop() -> PageProperty {
PageProperty::new_user(PageFlags::RW, CachePolicy::Writeback)
}
#[ktest]
fn kvirt_area_tracked_map_pages() {
let size = 2 * PAGE_SIZE;
let frames = FrameAllocOptions::default()
.alloc_segment_with(2, |_| ())
.unwrap();
let paddr = frames.paddr();
let kvirt_area = KVirtArea::map_frames(size, 0, frames.into_iter(), default_prop());
assert_eq!(kvirt_area.size(), size);
assert!(kvirt_area.start() >= VMALLOC_VADDR_RANGE.start);
assert!(kvirt_area.end() <= VMALLOC_VADDR_RANGE.end);
let guard = disable_preempt();
for i in 0..2 {
let addr = kvirt_area.start() + i * PAGE_SIZE;
let MappedItemRef::Tracked(page, prop) = kvirt_area.query(&guard, addr).unwrap() else {
panic!("Expected a tracked page");
};
assert_eq!(page.paddr(), paddr + (i * PAGE_SIZE));
assert_eq!(prop.flags, default_prop().flags);
assert_eq!(prop.cache, default_prop().cache);
}
}
#[ktest]
fn kvirt_area_untracked_map_pages() {
let max_paddr = max_paddr();
let size = 2 * PAGE_SIZE;
let pa_range = max_paddr..max_paddr + 2 * PAGE_SIZE as Paddr;
let kvirt_area =
unsafe { KVirtArea::map_untracked_frames(size, 0, pa_range.clone(), default_prop()) };
assert_eq!(kvirt_area.size(), size);
assert!(kvirt_area.start() >= VMALLOC_VADDR_RANGE.start);
assert!(kvirt_area.end() <= VMALLOC_VADDR_RANGE.end);
let guard = disable_preempt();
for i in 0..2 {
let addr = kvirt_area.start() + i * PAGE_SIZE;
let MappedItemRef::Untracked(pa, level, prop) = kvirt_area.query(&guard, addr).unwrap()
else {
panic!("Expected a untracked page");
};
assert_eq!(pa, pa_range.start + (i * PAGE_SIZE) as Paddr);
assert_eq!(level, 1);
assert_eq!(prop, default_prop());
}
}
#[ktest]
fn kvirt_area_tracked_drop() {
let size = 2 * PAGE_SIZE;
let frames = FrameAllocOptions::default()
.alloc_segment_with(2, |_| ())
.unwrap();
let kvirt_area = KVirtArea::map_frames(size, 0, frames.into_iter(), default_prop());
drop(kvirt_area);
let kvirt_area =
KVirtArea::map_frames(size, 0, core::iter::empty::<Frame<()>>(), default_prop());
let guard = disable_preempt();
assert!(kvirt_area.query(&guard, kvirt_area.start()).is_none());
}
#[ktest]
fn kvirt_area_untracked_drop() {
let max_paddr = max_paddr();
let size = 2 * PAGE_SIZE;
let pa_range = max_paddr..max_paddr + 2 * PAGE_SIZE as Paddr;
let kvirt_area = unsafe { KVirtArea::map_untracked_frames(size, 0, pa_range, default_prop()) };
drop(kvirt_area);
let kvirt_area = unsafe { KVirtArea::map_untracked_frames(size, 0, 0..0, default_prop()) };
let guard = disable_preempt();
assert!(kvirt_area.query(&guard, kvirt_area.start()).is_none());
}
#[ktest]
fn manual_paddr_to_vaddr() {
let pa = 0x1000;
let va = paddr_to_vaddr(pa);
assert_eq!(va, LINEAR_MAPPING_BASE_VADDR + pa);
}