use page_table_generic::*;
mod mocks;
use mocks::*;
#[test]
fn test_pte() {
let pte = PteImpl::new();
println!("PTE: {:?}", pte);
assert!(!pte.to_config(false).valid);
assert!(!pte.to_config(false).huge);
println!("✓ Empty PTE test passed");
}
#[test]
fn test_pte_read_only() {
let pte = PteImpl::read_only();
assert!(pte.to_config(false).valid);
assert!(pte.is_readable());
assert!(!pte.is_writable());
assert!(!pte.is_user_executable());
assert!(!pte.is_user_accessible());
assert!(!pte.is_privilege_executable());
assert_eq!(pte.cache_mode(), 1); assert!(!pte.to_config(false).huge);
println!("✓ ReadOnly PTE test passed");
}
#[test]
fn test_pte_user_mode() {
let pte = PteImpl::user_mode();
assert!(pte.to_config(false).valid);
assert!(pte.is_readable());
assert!(pte.is_writable());
assert!(pte.is_user_executable());
assert!(pte.is_user_accessible());
assert!(!pte.is_privilege_executable());
assert_eq!(pte.cache_mode(), 1); assert!(!pte.to_config(false).huge);
println!("✓ UserMode PTE test passed");
}
#[test]
fn test_pte_kernel_mode() {
let pte = PteImpl::kernel_mode();
assert!(pte.to_config(false).valid);
assert!(pte.is_readable());
assert!(pte.is_writable());
assert!(!pte.is_user_executable());
assert!(!pte.is_user_accessible());
assert!(pte.is_privilege_executable());
assert_eq!(pte.cache_mode(), 1); assert!(!pte.to_config(false).huge);
println!("✓ KernelMode PTE test passed");
}
#[test]
fn test_pte_device_memory() {
let pte = PteImpl::device_memory();
assert!(pte.to_config(false).valid);
assert!(pte.is_readable());
assert!(pte.is_writable());
assert!(!pte.is_user_executable());
assert!(!pte.is_user_accessible());
assert!(!pte.is_privilege_executable());
assert_eq!(pte.cache_mode(), 2); assert!(pte.to_config(false).huge);
println!("✓ DeviceMemory PTE test passed");
}
#[test]
fn test_pte_complex_mapping() {
let mut pg = PageTable::<T4kL3, Fram4k>::new(Fram4k).unwrap();
pg.map(&MapConfig {
vaddr: 0usize.into(),
paddr: 0usize.into(), size: 2 * MB,
pte: PteImpl::complex_user_mapping_config(),
allow_huge: true,
flush: false,
})
.unwrap();
assert!(pg.is_mapped(0usize.into()));
assert_eq!(
pg.translate_phys(0usize.into()).unwrap(),
0usize.into() );
let (_, pte) = pg.translate(0usize.into()).unwrap();
assert!(pte.to_config(false).valid);
if pte.to_config(false).huge {
println!("✓ 创建了大页映射");
} else {
println!("✓ 创建了普通页映射");
}
println!("✓ Complex mapping test passed");
}
fn assert_pte_flags(
pte: &PteImpl,
expected_readable: bool,
expected_writable: bool,
expected_user_executable: bool,
expected_user_accessible: bool,
expected_privilege_executable: bool,
expected_cache_mode: u64,
expected_huge: bool,
test_name: &str,
) {
assert_eq!(
pte.is_readable(),
expected_readable,
"{} 读取权限不匹配,期望 {},实际 {}",
test_name,
expected_readable,
pte.is_readable()
);
assert_eq!(
pte.is_writable(),
expected_writable,
"{} 写入权限不匹配,期望 {},实际 {}",
test_name,
expected_writable,
pte.is_writable()
);
assert_eq!(
pte.is_user_executable(),
expected_user_executable,
"{} 用户执行权限不匹配,期望 {},实际 {}",
test_name,
expected_user_executable,
pte.is_user_executable()
);
assert_eq!(
pte.is_user_accessible(),
expected_user_accessible,
"{} 用户访问权限不匹配,期望 {},实际 {}",
test_name,
expected_user_accessible,
pte.is_user_accessible()
);
assert_eq!(
pte.is_privilege_executable(),
expected_privilege_executable,
"{} 特权执行权限不匹配,期望 {},实际 {}",
test_name,
expected_privilege_executable,
pte.is_privilege_executable()
);
assert_eq!(
pte.cache_mode(),
expected_cache_mode,
"{} 缓存模式不匹配,期望 {},实际 {}",
test_name,
expected_cache_mode,
pte.cache_mode()
);
assert_eq!(
pte.to_config(false).huge,
expected_huge,
"{} 大页属性不匹配,期望 {},实际 {}",
test_name,
expected_huge,
pte.to_config(false).huge
);
}
fn print_pte_flags(pte: &PteImpl, test_name: &str) {
println!(
"{} PTE Flags: R={}, W={}, UX={}, UA={}, PX={}, Cache={}, Huge={}, Valid={}",
test_name,
pte.is_readable(),
pte.is_writable(),
pte.is_user_executable(),
pte.is_user_accessible(),
pte.is_privilege_executable(),
pte.cache_mode(),
pte.to_config(false).huge,
pte.to_config(false).valid
);
}
fn test_high_with_flags<T: TableMeta, A: FrameAllocator>(
pte: PteConfig,
alloc: A,
test_vaddr: VirtAddr,
expected_leaf_level: usize,
test_name: &str,
expected_readable: bool,
expected_writable: bool,
expected_user_executable: bool,
expected_user_accessible: bool,
expected_privilege_executable: bool,
expected_cache_mode: u64,
expected_huge: bool,
) where
T: TableMeta<P = PteImpl>,
{
let mut pg = unsafe { PageTableRef::<T, A>::new(alloc).unwrap() };
println!("table page size: {:#x}", T::PAGE_SIZE);
println!("valid bits: {}", PageTableRef::<T, A>::valid_bits());
let pte_impl = T::P::from_config(pte);
print_pte_flags(&pte_impl, &format!("{} - 输入PTE", test_name));
println!("\n=== {test_name} 映前状态 - walk_all (遍历所有项) ===");
for p in pg.walk(VirtAddr::new(0), VirtAddr::new(usize::MAX)) {
println!(
"l: {}, va: {:?}, pte: {:?}, final: {}",
p.level, p.vaddr, p.pte, p.is_final_mapping
);
}
pg.map(&MapConfig {
vaddr: test_vaddr,
paddr: 0x0000usize.into(),
size: 0x2000,
pte,
allow_huge: false,
flush: false,
})
.unwrap();
println!("\n=== {} 映后状态 - walk_valid结果 ===", test_name);
let mut count = 0;
let mut valid_entries = Vec::new();
for p in pg.walk_valid() {
println!("l: {}, va: {:?}, pte: {:?}", p.level, p.vaddr, p.pte);
valid_entries.push((p.vaddr, p.pte, p.level));
count += 1;
}
println!("walk_valid() 返回 {count} 个叶子级别条目");
println!(
"\n=== {} 映后状态 - 显示完整层次(所有有效项) ===",
test_name
);
for p in pg.walk(VirtAddr::new(0), VirtAddr::new(usize::MAX)) {
println!(
"l: {}, va: {:?}, c: PTE PA: {:?} Block: {}, Final: {}",
p.level,
p.vaddr,
p.pte.to_config(false).paddr,
p.pte.to_config(false).huge,
p.is_final_mapping
);
}
assert_eq!(count, 2);
let expected_vaddrs = [test_vaddr, VirtAddr::new(test_vaddr.raw() + 0x1000)];
for (i, (vaddr, pte, level)) in valid_entries.iter().enumerate() {
assert_eq!(
*vaddr, expected_vaddrs[i],
"{} 第{}个条目的虚拟地址不匹配,期望 {:?},实际 {:?}",
test_name, i, expected_vaddrs[i], vaddr
);
assert_eq!(
*level, expected_leaf_level,
"{} 叶子级别页表项应该在level {},实际在level {level}",
test_name, expected_leaf_level
);
assert!(
pte.to_config(false).valid,
"{} 页表项应该是有效的",
test_name
);
assert!(
!pte.to_config(false).huge,
"{} 页表项不应该是大页",
test_name
);
let actual_paddr = pte.to_config(false).paddr;
let actual_offset = actual_paddr.raw() % 0x1000; assert_eq!(
actual_offset, 0,
"{} 页内偏移应该是0,实际是 {actual_offset:?}",
test_name
);
if i > 0 {
let prev_pte = &valid_entries[i - 1].1;
let prev_paddr = prev_pte.to_config(false).paddr;
let addr_diff = actual_paddr.raw().saturating_sub(prev_paddr.raw());
assert_eq!(
addr_diff, 0x1000,
"{} 相邻页面物理地址应该相差0x1000,实际相差 {addr_diff:?}",
test_name
);
}
println!(
"✓ {} 页面{}地址验证通过: VA={:?}, PA={:?}, Level={}",
test_name, i, vaddr, actual_paddr, level
);
}
println!("\n=== {} Flag属性验证 ===", test_name);
for (i, (_vaddr, pte, _level)) in valid_entries.iter().enumerate() {
let entry_test_name = format!("{}-PTE{}", test_name, i);
let pte_impl: PteImpl = unsafe { std::mem::transmute_copy(pte) };
print_pte_flags(&pte_impl, &entry_test_name);
assert_pte_flags(
&pte_impl,
expected_readable,
expected_writable,
expected_user_executable,
expected_user_accessible,
expected_privilege_executable,
expected_cache_mode,
expected_huge,
&entry_test_name,
);
println!("✓ {} 页面{} Flag验证通过", test_name, i);
}
println!("🎉 {} 所有地址和Flag属性验证通过!", test_name);
}