Skip to content

Commit 15de230

Browse files
numpy1314numpy1314
andauthored
[feat] Add hypervisor support for aarch64 (#10)
--------- Co-authored-by: numpy1314 <xzj13@ustc.edu.cn>
1 parent fb1695d commit 15de230

2 files changed

Lines changed: 52 additions & 6 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ default = []
2525
fp-simd = []
2626
tls = []
2727
uspace = []
28+
arm-el2 = []
2829

2930
[dependencies]
3031
linkme = "0.3"

src/aarch64/asm.rs

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,26 @@ pub fn halt() {
4646

4747
/// Reads the current page table root register for kernel space (`TTBR1_EL1`).
4848
///
49+
/// When the "arm-el2" feature is enabled,
50+
/// TTBR0_EL2 is dedicated to the Hypervisor's Stage-2 page table base address.
51+
///
4952
/// Returns the physical address of the page table root.
5053
#[inline]
5154
pub fn read_kernel_page_table() -> PhysAddr {
55+
#[cfg(not(feature = "arm-el2"))]
5256
let root = TTBR1_EL1.get();
57+
58+
#[cfg(feature = "arm-el2")]
59+
let root = TTBR0_EL2.get();
60+
5361
pa!(root as usize)
5462
}
5563

5664
/// Reads the current page table root register for user space (`TTBR0_EL1`).
5765
///
66+
/// When the "arm-el2" feature is enabled, for user-mode programs,
67+
/// virtualization is completely transparent to them, so there is no need to modify
68+
///
5869
/// Returns the physical address of the page table root.
5970
#[inline]
6071
pub fn read_user_page_table() -> PhysAddr {
@@ -65,19 +76,33 @@ pub fn read_user_page_table() -> PhysAddr {
6576
/// Writes the register to update the current page table root for kernel space
6677
/// (`TTBR1_EL1`).
6778
///
79+
/// When the "arm-el2" feature is enabled,
80+
/// TTBR0_EL2 is dedicated to the Hypervisor's Stage-2 page table base address.
81+
///
6882
/// Note that the TLB is **NOT** flushed after this operation.
6983
///
7084
/// # Safety
7185
///
7286
/// This function is unsafe as it changes the virtual memory address space.
7387
#[inline]
7488
pub unsafe fn write_kernel_page_table(root_paddr: PhysAddr) {
75-
// kernel space page table use TTBR1 (0xffff_0000_0000_0000..0xffff_ffff_ffff_ffff)
76-
TTBR1_EL1.set(root_paddr.as_usize() as _);
89+
#[cfg(not(feature = "arm-el2"))]
90+
{
91+
// kernel space page table use TTBR1 (0xffff_0000_0000_0000..0xffff_ffff_ffff_ffff)
92+
TTBR1_EL1.set(root_paddr.as_usize() as _);
93+
}
94+
95+
#[cfg(feature = "arm-el2")]
96+
{
97+
// kernel space page table at EL2 use TTBR0_EL2 (0x0000_0000_0000_0000..0x0000_ffff_ffff_ffff)
98+
TTBR0_EL2.set(root_paddr.as_usize() as _);
99+
}
77100
}
78101

79102
/// Writes the register to update the current page table root for user space
80103
/// (`TTBR1_EL0`).
104+
/// When the "arm-el2" feature is enabled, for user-mode programs,
105+
/// virtualization is completely transparent to them, so there is no need to modify
81106
///
82107
/// Note that the TLB is **NOT** flushed after this operation.
83108
///
@@ -97,10 +122,27 @@ pub unsafe fn write_user_page_table(root_paddr: PhysAddr) {
97122
pub fn flush_tlb(vaddr: Option<VirtAddr>) {
98123
unsafe {
99124
if let Some(vaddr) = vaddr {
100-
asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) vaddr.as_usize())
125+
const VA_MASK: usize = (1 << 44) - 1; // 0xFFFF_FFFF_FFFF
126+
let operand = (vaddr.as_usize() >> 12) & VA_MASK;
127+
128+
#[cfg(not(feature = "arm-el2"))]
129+
{
130+
asm!("tlbi vaae1is, {}; dsb sy; isb", in(reg) operand)
131+
}
132+
#[cfg(feature = "arm-el2")]
133+
{
134+
asm!("tlbi vae2is, {}; dsb sy; isb", in(reg) operand)
135+
}
101136
} else {
102137
// flush the entire TLB
103-
asm!("tlbi vmalle1; dsb sy; isb")
138+
#[cfg(not(feature = "arm-el2"))]
139+
{
140+
asm!("tlbi vmalle1; dsb sy; isb")
141+
}
142+
#[cfg(feature = "arm-el2")]
143+
{
144+
asm!("tlbi alle2; dsb sy; isb")
145+
}
104146
}
105147
}
106148
}
@@ -124,8 +166,11 @@ pub fn flush_dcache_line(vaddr: VirtAddr) {
124166
/// This function is unsafe as it changes the exception handling behavior of the
125167
/// current CPU.
126168
#[inline]
127-
pub unsafe fn write_exception_vector_base(vbar_el1: usize) {
128-
VBAR_EL1.set(vbar_el1 as _);
169+
pub unsafe fn write_exception_vector_base(vbar: usize) {
170+
#[cfg(not(feature = "arm-el2"))]
171+
VBAR_EL1.set(vbar as _);
172+
#[cfg(feature = "arm-el2")]
173+
VBAR_EL2.set(vbar as _);
129174
}
130175

131176
/// Reads the thread pointer of the current CPU (`TPIDR_EL0`).

0 commit comments

Comments
 (0)