@@ -19,6 +19,9 @@ core::arch::global_asm!(include_str!("entry.S"));
1919#[ percpu:: def_percpu]
2020static 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.
2326unsafe 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