Skip to content

Commit 3f053f7

Browse files
committed
[wip] seperate return_run_guest and dispatch_irq
1 parent b2aa19c commit 3f053f7

File tree

5 files changed

+76
-8
lines changed

5 files changed

+76
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ edition = "2021"
66
[dependencies]
77
log = "0.4.21"
88

9-
cortex-a = "8.1.1"
109
aarch64-cpu = "9.3"
1110
smccc = "0.1.1"
1211
tock-registers = "0.8"
1312
numeric-enum-macro = "0.2"
1413

1514
axerrno = "0.1.0"
1615
percpu = "0.1.4"
16+
crate_interface = "0.1"
1717

1818
axaddrspace = { git = "https://github.com/arceos-hypervisor/axaddrspace.git" }
1919
axvcpu = { git = "https://github.com/arceos-hypervisor/axvcpu.git" }

src/exception.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,42 @@ fn handle_psci_call(ctx: &mut TrapFrame) -> Option<AxResult<AxVCpuExitReason>> {
235235
})
236236
}
237237

238-
/// A trampoline function for sp switching during handling VM exits.
238+
/// Dispatches IRQs to the appropriate handler provided by the underlying host OS.
239+
fn dispatch_irq() {
240+
crate_interface::call_interface!(crate::HalIf::irq_hanlder())
241+
}
242+
243+
/// A trampoline function for handling exceptions (VM exits) in EL2.
244+
///
245+
/// Functionality:
246+
///
247+
/// 1. **Check if VCPU is running:**
248+
/// - The `vcpu_running` function is called to check if the VCPU is currently running.
249+
/// If the VCPU is running, the control flow is transferred to the `return_run_guest` function.
250+
///
251+
/// 2. **Dispatch IRQ:**
252+
/// - If there is no active vcpu running, the `dispatch_irq` function is called to handle the IRQ,
253+
/// which will dispatch this irq routine to the underlining host OS.
254+
///
255+
#[naked]
256+
#[no_mangle]
257+
unsafe extern "C" fn vmexit_trampoline() {
258+
core::arch::asm!(
259+
"bl {vcpu_running}", // Check if vcpu is running.
260+
"cbnz x0, {return_run_guest}", // If vcpu_running returns true, jump to `return_run_guest`.
261+
"bl {dispatch_irq}",
262+
"ret", // Control flow is handed back to Aarch64VCpu.run(), simulating the normal return of the `run_guest` function.
263+
vcpu_running = sym crate::vcpu::vcpu_running,
264+
return_run_guest = sym return_run_guest,
265+
dispatch_irq = sym dispatch_irq,
266+
options(noreturn),
267+
)
268+
}
269+
270+
/// A trampoline function for sp switching during handling VM exits,
271+
/// when **there is a active VCPU running**, which means that the host context is stored
272+
/// into host stack in `run_guest` function.
273+
///
239274
/// # Functionality
240275
///
241276
/// 1. **Restore Previous Host Stack pointor:**
@@ -269,8 +304,7 @@ fn handle_psci_call(ctx: &mut TrapFrame) -> Option<AxResult<AxVCpuExitReason>> {
269304
/// invoked as part of the low-level hypervisor or VM exit handling routines.
270305
#[naked]
271306
#[no_mangle]
272-
unsafe extern "C" fn vmexit_trampoline() {
273-
// Note: Currently `sp` points to `&Aarch64VCpu.ctx`, which is just the base address of Aarch64VCpu struct.
307+
unsafe extern "C" fn return_run_guest() {
274308
core::arch::asm!(
275309
"add sp, sp, 34 * 8", // Skip the exception frame.
276310
"mov x9, sp", // Currently `sp` points to `&Aarch64VCpu.host_stack_top`, see `run_guest()` in vcpu.rs.

src/exception_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ macro_rules! save_regs_to_stack {
272272
///
273273
/// ## Note
274274
///
275-
/// This macro is called in `vmexit_trampoline()` in exception.rs,
275+
/// This macro is called in `return_run_guest()` in exception.rs,
276276
/// it should only be used after `save_regs_to_stack!` to correctly restore the control flow of `Aarch64VCpu.run()`.
277277
macro_rules! restore_regs_from_stack {
278278
() => {

src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@ pub fn has_hardware_support() -> bool {
3030
// Current just return true by default.
3131
true
3232
}
33+
34+
/// Low-level resource interfaces that must be implemented by the crate user.
35+
#[crate_interface::def_interface]
36+
pub trait HalIf {
37+
fn irq_hanlder();
38+
}

src/vcpu.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ core::arch::global_asm!(include_str!("entry.S"));
1919
#[percpu::def_percpu]
2020
static HOST_SP_EL0: u64 = 0;
2121

22+
#[percpu::def_percpu]
23+
static VCPU_RUNNING: bool = false;
24+
2225
/// Save host's `SP_EL0` to the current percpu region.
2326
unsafe fn save_host_sp_el0() {
2427
HOST_SP_EL0.write_current_raw(SP_EL0.get())
@@ -29,6 +32,21 @@ unsafe fn restore_host_sp_el0() {
2932
SP_EL0.set(HOST_SP_EL0.read_current_raw());
3033
}
3134

35+
#[no_mangle]
36+
unsafe fn set_vcpu_running() {
37+
VCPU_RUNNING.write_current_raw(true);
38+
}
39+
40+
#[no_mangle]
41+
pub(crate) unsafe fn clear_vcpu_running() {
42+
VCPU_RUNNING.write_current_raw(false);
43+
}
44+
45+
#[no_mangle]
46+
pub(crate) unsafe fn vcpu_running() -> bool {
47+
VCPU_RUNNING.read_current_raw()
48+
}
49+
3250
/// (v)CPU register state that must be saved or restored when entering/exiting a VM or switching
3351
/// between VMs.
3452
#[repr(C)]
@@ -104,6 +122,9 @@ impl<H: AxVCpuHal> axvcpu::AxArchVCpu for Aarch64VCpu<H> {
104122
self.restore_vm_system_regs();
105123
self.run_guest()
106124
};
125+
unsafe {
126+
clear_vcpu_running();
127+
}
107128

108129
let trap_kind = TrapKind::try_from(exit_reson as u8).expect("Invalid TrapKind");
109130
self.vmexit_handler(trap_kind)
@@ -128,18 +149,25 @@ impl<H: AxVCpuHal> Aarch64VCpu<H> {
128149
unsafe fn run_guest(&mut self) -> usize {
129150
// Save function call context.
130151
core::arch::asm!(
131-
save_regs_to_stack!(), // Save host context.
152+
// Save host context.
153+
save_regs_to_stack!(),
132154
"mov x9, sp",
133155
"mov x10, x11",
134-
"str x9, [x10]", // Save current host stack top in the `Aarch64VCpu` struct.
156+
// Save current host stack top in the `Aarch64VCpu` struct.
157+
"str x9, [x10]",
135158
"mov x0, x11",
159+
// Since now the host context is saved into host stack,
160+
// mark `VCPU_RUNNING` as true,
161+
// so that a exception's control flow can be redirected to the `return_run_guest`.
162+
"bl {set_vcpu_running}",
136163
"b context_vm_entry",
164+
set_vcpu_running = sym set_vcpu_running,
137165
// in(reg) here is dangerous, because the compiler may use the register we want to use, creating a conflict.
138166
in("x11") &self.host_stack_top as *const _ as usize,
139167
options(nostack)
140168
);
141169

142-
// the dummy return value, the real return value is in x0 when `vmexit_trampoline` returns
170+
// the dummy return value, the real return value is in x0 when `return_run_guest` returns
143171
0
144172
}
145173

0 commit comments

Comments
 (0)