Skip to content

Commit a9cc616

Browse files
MRNIUclaude
andcommitted
test(tlb): integrate aarch64-cpu TLBI wrappers and add smoke test
Replace hand-written inline assembly in the tlb crate with type-safe TLBI wrappers (tlbi::Addr, tlbi::Asid) from the MRNIU/aarch64-cpu feat/add-tlbi-instructions branch (rust-embedded/aarch64-cpu#77). Add explicit TLBI instruction smoke test in phase3: - vmalle1 / vmalle1is global invalidation - vae1 / vale1 per-VA invalidation - aside1 per-ASID invalidation - Addr / Asid encoding correctness assertions Verified on QEMU aarch64 (cortex-a72, 2 cores). Signed-off-by: MRNIU <nzh@nzhnb.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Niu Zhihong <zhihong@nzhnb.com>
1 parent 254a69a commit a9cc616

File tree

5 files changed

+77
-23
lines changed

5 files changed

+77
-23
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ riscv = { version = "0.16", features = ["s-mode"] }
9191
# AArch64
9292
# TODO: aarch64-cpu 使用 git 依赖以获取 DAIFSet/DAIFClr 支持,待包含此功能的新版本
9393
# 发布到 crates.io 后切换回版本依赖
94-
aarch64-cpu = { git = "https://github.com/rust-embedded/aarch64-cpu", branch = "main" }
94+
# 当前使用 fork 分支以测试 TLBI 指令封装(PR: rust-embedded/aarch64-cpu#77)
95+
aarch64-cpu = { git = "https://github.com/MRNIU/aarch64-cpu", branch = "feat/add-tlbi-instructions" }
9596
tock-registers = "0.10"
9697
arm-gic = "0.8"
9798
arm-psci = "0.2"

crates/tlb/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ spin.workspace = true
1414
# RISC-V sfence.vma 指令
1515
[target.'cfg(target_arch = "riscv64")'.dependencies]
1616
riscv.workspace = true
17+
18+
# AArch64 TLBI/DSB/ISB 指令封装
19+
[target.'cfg(target_arch = "aarch64")'.dependencies]
20+
aarch64-cpu.workspace = true

crates/tlb/src/arch/aarch64.rs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
//! AArch64 TLB 刷新——`tlbi` / `dsb` / `isb` 指令
1+
//! AArch64 TLB 刷新——使用 `aarch64-cpu` crate 的 TLBI / barrier 封装
22
//!
33
//! [Arm ARM §D8.3](https://developer.arm.com/documentation/ddi0487/latest)
4-
//
5-
// TODO: `aarch64-cpu` crate 未提供 TLBI 指令封装(仅有 DSB/ISB barrier),
6-
// 因此此处使用内联汇编。后续应向上游提交 PR 添加 `tlbi_vmalle1()` 和
7-
// `tlbi_vae1(vaddr)` 封装,替换手写汇编。
8-
// 上游仓库:https://github.com/rust-embedded/aarch64-cpu
4+
5+
use aarch64_cpu::asm::{barrier, tlbi};
96

107
use super::TlbArch;
118

@@ -14,24 +11,22 @@ pub(crate) struct Aarch64;
1411
impl TlbArch for Aarch64 {
1512
#[inline(always)]
1613
fn flush_all() {
17-
// SAFETY: tlbi/dsb/isb 是 EL1 特权指令。
18-
unsafe {
19-
core::arch::asm!("tlbi vmalle1", "dsb sy", "isb");
20-
}
14+
// SAFETY: TLBI VMALLE1 + DSB + ISB 是 EL1 特权指令,
15+
// 调用方在内核态(EL1)执行。
16+
barrier::dsb(barrier::SY);
17+
tlbi::vmalle1();
18+
barrier::dsb(barrier::SY);
19+
barrier::isb(barrier::SY);
2120
}
2221

2322
#[inline(always)]
2423
fn flush_page(vaddr: usize) {
25-
// SAFETY: tlbi/dsb/isb 是 EL1 特权指令。
26-
// TLBI VAE1 操作数格式:虚拟地址右移 PAGE_SHIFT 位(页号)。
27-
let page = vaddr >> config::PAGE_SIZE.trailing_zeros();
28-
unsafe {
29-
core::arch::asm!(
30-
"tlbi vae1, {page}",
31-
"dsb sy",
32-
"isb",
33-
page = in(reg) page,
34-
);
35-
}
24+
// SAFETY: TLBI VAE1 + DSB + ISB 是 EL1 特权指令。
25+
// Addr::new 负责将虚拟地址右移 12 位并编码到正确的位域。
26+
// ASID 传 0——当前为单地址空间,不区分 ASID。
27+
barrier::dsb(barrier::SY);
28+
tlbi::vae1(tlbi::Addr::new(vaddr as u64, 0));
29+
barrier::dsb(barrier::SY);
30+
barrier::isb(barrier::SY);
3631
}
3732
}

src/smoke_test.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,59 @@ pub fn phase3() {
4444
log::info!("HeapTest: Box::new(42) = {}", *val);
4545
assert_eq!(*val, 42);
4646

47+
// 显式测试 aarch64-cpu TLBI 封装(rust-embedded/aarch64-cpu#77)
48+
#[cfg(target_arch = "aarch64")]
49+
{
50+
use aarch64_cpu::asm::{barrier, tlbi};
51+
52+
log::info!("TLBI: testing aarch64-cpu tlbi wrappers...");
53+
54+
// 1. vmalle1: 全局 TLB 无效化
55+
barrier::dsb(barrier::SY);
56+
tlbi::vmalle1();
57+
barrier::dsb(barrier::SY);
58+
barrier::isb(barrier::SY);
59+
log::info!("TLBI: vmalle1 OK");
60+
61+
// 2. vae1: 按 VA + ASID 无效化(使用内核栈地址作为测试 VA)
62+
let test_va: u64 = &val as *const _ as u64;
63+
barrier::dsb(barrier::SY);
64+
tlbi::vae1(tlbi::Addr::new(test_va, 0));
65+
barrier::dsb(barrier::SY);
66+
barrier::isb(barrier::SY);
67+
log::info!("TLBI: vae1(va={:#x}, asid=0) OK", test_va);
68+
69+
// 3. vale1: 按 VA 无效化(仅末级页表项)
70+
barrier::dsb(barrier::SY);
71+
tlbi::vale1(tlbi::Addr::new(test_va, 0));
72+
barrier::dsb(barrier::SY);
73+
barrier::isb(barrier::SY);
74+
log::info!("TLBI: vale1 OK");
75+
76+
// 4. aside1: 按 ASID 无效化
77+
barrier::dsb(barrier::SY);
78+
tlbi::aside1(tlbi::Asid::new(0));
79+
barrier::dsb(barrier::SY);
80+
barrier::isb(barrier::SY);
81+
log::info!("TLBI: aside1 OK");
82+
83+
// 5. vmalle1is: Inner Shareable 域全局无效化
84+
barrier::dsb(barrier::SY);
85+
tlbi::vmalle1is();
86+
barrier::dsb(barrier::SY);
87+
barrier::isb(barrier::SY);
88+
log::info!("TLBI: vmalle1is OK");
89+
90+
// 6. 验证 Addr 编码正确性
91+
let addr = tlbi::Addr::new(0x8000_0000, 1);
92+
assert_eq!(addr.as_raw(), 0x0001_0000_0008_0000);
93+
let asid = tlbi::Asid::new(42);
94+
assert_eq!(asid.as_raw(), 0x002A_0000_0000_0000);
95+
log::info!("TLBI: Addr/Asid encoding verified");
96+
97+
log::info!("=== TLBI TEST PASSED ===");
98+
}
99+
47100
log::info!("Phase 3 complete");
48101
}
49102

0 commit comments

Comments
 (0)