Skip to content

Commit 736931e

Browse files
committed
feat(smp): support cross-core TLB flush
1 parent 4594a76 commit 736931e

File tree

7 files changed

+106
-35
lines changed

7 files changed

+106
-35
lines changed

Cargo.lock

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

page_table_multiarch/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ rust-version.workspace = true
1616
default = []
1717
axerrno = ["dep:axerrno"]
1818
copy-from = ["dep:bitmaps"]
19+
smp = []
1920

2021
[dependencies]
2122
axerrno = { version = "0.1", optional = true }
2223
arrayvec = { version = "0.7", default-features = false }
2324
bitmaps = { version = "3.2", default-features = false, optional = true }
25+
crate_interface = "0.1.4"
2426
log = "0.4"
2527
memory_addr.workspace = true
2628
page_table_entry.workspace = true

page_table_multiarch/src/arch/aarch64.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,17 @@ impl PagingMetaData for A64PagingMetaData {
2727
if let Some(vaddr) = vaddr {
2828
// TLB Invalidate by VA, All ASID, EL1, Inner Shareable
2929
const VA_MASK: usize = (1 << 44) - 1; // VA[55:12] => bits[43:0]
30-
asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) ((vaddr.as_usize() >> 12) & VA_MASK))
30+
let va = (vaddr.as_usize() >> 12) & VA_MASK;
31+
#[cfg(feature = "smp")]
32+
asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) va);
33+
#[cfg(not(feature = "smp"))]
34+
asm!("tlbi vaae1, {}; dsb sy; isb", in(reg) va);
3135
} else {
36+
#[cfg(feature = "smp")]
3237
// TLB Invalidate by VMID, All at stage 1, EL1
33-
asm!("tlbi vmalle1; dsb sy; isb")
38+
asm!("tlbi vmalle1is; dsb sy; isb");
39+
#[cfg(not(feature = "smp"))]
40+
asm!("tlbi vmalle1; dsb sy; isb");
3441
}
3542
}
3643
}

page_table_multiarch/src/arch/loongarch64.rs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,34 @@ use page_table_entry::loongarch64::LA64PTE;
77

88
use crate::{PageTable64, PageTable64Mut, PagingMetaData};
99

10+
#[inline]
11+
fn local_flush_tlb(vaddr: Option<memory_addr::VirtAddr>) {
12+
unsafe {
13+
if let Some(vaddr) = vaddr {
14+
// <https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_dbar>
15+
//
16+
// Only after all previous load/store access operations are completely
17+
// executed, the DBAR 0 instruction can be executed; and only after the
18+
// execution of DBAR 0 is completed, all subsequent load/store access
19+
// operations can be executed.
20+
//
21+
// <https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_invtlb>
22+
//
23+
// formats: invtlb op, asid, addr
24+
//
25+
// op 0x5: Clear all page table entries with G=0 and ASID equal to the
26+
// register specified ASID, and VA equal to the register specified VA.
27+
//
28+
// When the operation indicated by op does not require an ASID, the
29+
// general register rj should be set to r0.
30+
asm!("dbar 0; invtlb 0x05, $r0, {reg}", reg = in(reg) vaddr.as_usize());
31+
} else {
32+
// op 0x0: Clear all page table entries
33+
asm!("dbar 0; invtlb 0x00, $r0, $r0");
34+
}
35+
}
36+
}
37+
1038
/// Metadata of LoongArch64 page tables.
1139
#[derive(Copy, Clone, Debug)]
1240
pub struct LA64MetaData;
@@ -51,30 +79,14 @@ impl PagingMetaData for LA64MetaData {
5179

5280
#[inline]
5381
fn flush_tlb(vaddr: Option<VirtAddr>) {
54-
unsafe {
55-
if let Some(vaddr) = vaddr {
56-
// <https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_dbar>
57-
//
58-
// Only after all previous load/store access operations are completely
59-
// executed, the DBAR 0 instruction can be executed; and only after the
60-
// execution of DBAR 0 is completed, all subsequent load/store access
61-
// operations can be executed.
62-
//
63-
// <https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_invtlb>
64-
//
65-
// formats: invtlb op, asid, addr
66-
//
67-
// op 0x5: Clear all page table entries with G=0 and ASID equal to the
68-
// register specified ASID, and VA equal to the register specified VA.
69-
//
70-
// When the operation indicated by op does not require an ASID, the
71-
// general register rj should be set to r0.
72-
asm!("dbar 0; invtlb 0x05, $r0, {reg}", reg = in(reg) vaddr.as_usize());
73-
} else {
74-
// op 0x0: Clear all page table entries
75-
asm!("dbar 0; invtlb 0x00, $r0, $r0");
76-
}
82+
#[cfg(feature = "smp")]
83+
{
84+
use crate::__TlbFlushIf_mod;
85+
use crate_interface::call_interface;
86+
87+
call_interface!(TlbFlushIf::flush_all(vaddr));
7788
}
89+
local_flush_tlb(vaddr);
7890
}
7991
}
8092

page_table_multiarch/src/arch/riscv.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ use page_table_entry::riscv::Rv64PTE;
55

66
use crate::{PageTable64, PageTable64Mut, PagingMetaData};
77

8+
fn local_flush_tlb(vaddr: Option<memory_addr::VirtAddr>) {
9+
if let Some(vaddr) = vaddr {
10+
riscv::asm::sfence_vma(0, vaddr.as_usize())
11+
} else {
12+
riscv::asm::sfence_vma_all();
13+
}
14+
}
15+
816
/// A virtual address that can be used in RISC-V Sv39 and Sv48 page tables.
917
pub trait SvVirtAddr: memory_addr::MemoryAddr + Send + Sync {
1018
/// Flush the TLB.
@@ -14,11 +22,14 @@ pub trait SvVirtAddr: memory_addr::MemoryAddr + Send + Sync {
1422
impl SvVirtAddr for VirtAddr {
1523
#[inline]
1624
fn flush_tlb(vaddr: Option<Self>) {
17-
if let Some(vaddr) = vaddr {
18-
riscv::asm::sfence_vma(0, vaddr.as_usize())
19-
} else {
20-
riscv::asm::sfence_vma_all();
25+
#[cfg(feature = "smp")]
26+
{
27+
use crate::__TlbFlushIf_mod;
28+
use crate_interface::call_interface;
29+
30+
call_interface!(TlbFlushIf::flush_all(vaddr));
2131
}
32+
local_flush_tlb(vaddr);
2233
}
2334
}
2435

page_table_multiarch/src/arch/x86_64.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@ use page_table_entry::x86_64::X64PTE;
55

66
use crate::{PageTable64, PageTable64Mut, PagingMetaData};
77

8+
#[inline]
9+
fn local_flush_tlb(vaddr: Option<memory_addr::VirtAddr>) {
10+
unsafe {
11+
if let Some(vaddr) = vaddr {
12+
x86::tlb::flush(vaddr.into());
13+
} else {
14+
x86::tlb::flush_all();
15+
}
16+
}
17+
}
18+
819
/// metadata of x86_64 page tables.
920
pub struct X64PagingMetaData;
1021

@@ -16,13 +27,14 @@ impl PagingMetaData for X64PagingMetaData {
1627

1728
#[inline]
1829
fn flush_tlb(vaddr: Option<VirtAddr>) {
19-
unsafe {
20-
if let Some(vaddr) = vaddr {
21-
x86::tlb::flush(vaddr.into());
22-
} else {
23-
x86::tlb::flush_all();
24-
}
30+
#[cfg(feature = "smp")]
31+
{
32+
use crate::__TlbFlushIf_mod;
33+
use crate_interface::call_interface;
34+
35+
call_interface!(TlbFlushIf::flush_all(vaddr));
2536
}
37+
local_flush_tlb(vaddr);
2638
}
2739
}
2840

page_table_multiarch/src/lib.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,18 @@ impl From<PageSize> for usize {
138138
size as usize
139139
}
140140
}
141+
142+
/// Interface for performing TLB flush operations on SMP systems.
143+
///
144+
/// This trait is used by the page table subsystem to request
145+
/// architecture- or platform-specific TLB invalidation.
146+
#[cfg(feature = "smp")]
147+
#[crate_interface::def_interface]
148+
pub trait TlbFlushIf {
149+
/// Flush TLB entries.
150+
///
151+
/// If `vaddr` is `None`, flush all TLB entries.
152+
/// If `Some(vaddr)` is provided, flush the TLB entry corresponding
153+
/// to the given virtual address.
154+
fn flush_all(vaddr: Option<VirtAddr>);
155+
}

0 commit comments

Comments
 (0)