11use core:: sync:: atomic:: { AtomicBool , AtomicUsize , Ordering } ;
2+ use std:: os:: arceos:: { api:: task:: AxCpuMask , modules:: axtask:: set_current_affinity} ;
23
34use super :: AddrSpace ;
45use alloc:: { collections:: BTreeMap , string:: String , vec:: Vec } ;
6+ use arm_vcpu:: Aarch64VCpuSetupConfig ;
57
68use crate :: {
7- GuestPhysAddr , HostPhysAddr , HostVirtAddr ,
9+ GuestPhysAddr , HostPhysAddr , HostVirtAddr , TASK_STACK_SIZE ,
810 arch:: cpu:: VCpu ,
911 config:: { AxVMConfig , MemoryKind } ,
10- region:: Region ,
12+ region:: GuestRegion ,
1113 vhal:: { ArchHal , cpu:: CpuId , phys_to_virt, virt_to_phys} ,
1214 vm:: { Status , VmId , VmOps } ,
1315} ;
@@ -115,12 +117,8 @@ impl ArchVm {
115117 ) ;
116118
117119 run_data. load_images ( & config) ?;
118- for vcpu in & mut run_data. vcpus {
119- vcpu. vcpu . set_entry ( run_data. kernel_entry ) . unwrap ( ) ;
120- vcpu. vcpu . set_dtb_addr ( run_data. dtb_addr ) . unwrap ( ) ;
121- }
122120
123- // // Add emulated devices
121+ // Add emulated devices
124122 // for emu_device in config.emu_devices() {
125123 // let device_info = DeviceInfo {
126124 // device_type: DeviceType::Emulated,
@@ -176,36 +174,27 @@ impl ArchVm {
176174 // })?;
177175 // }
178176
179- // // Setup vCPUs
180- // for (vcpu_id, vcpu) in &vcpus {
181- // let entry = if *vcpu_id == 0 {
182- // config.bsp_entry()
183- // } else {
184- // config.ap_entry()
185- // };
186-
187- // let setup_config = AxVCpuSetupConfig {
188- // passthrough_interrupt: config.interrupt_mode()
189- // == axvmconfig::VMInterruptMode::Passthrough,
190- // passthrough_timer: config.interrupt_mode()
191- // == axvmconfig::VMInterruptMode::Passthrough,
192- // };
177+ // Setup vCPUs
178+ for vcpu in & mut run_data. vcpus {
179+ vcpu. vcpu . set_entry ( run_data. kernel_entry ) . unwrap ( ) ;
180+ vcpu. vcpu . set_dtb_addr ( run_data. dtb_addr ) . unwrap ( ) ;
193181
194- // // Set entry point first
195- // vcpu.set_entry(entry).map_err(|e| {
196- // anyhow::anyhow!("Failed to set entry for vCPU {}: {:?}", vcpu_id, e)
197- // })?;
182+ let setup_config = Aarch64VCpuSetupConfig {
183+ passthrough_interrupt : config. interrupt_mode ( )
184+ == axvmconfig:: VMInterruptMode :: Passthrough ,
185+ passthrough_timer : config. interrupt_mode ( )
186+ == axvmconfig:: VMInterruptMode :: Passthrough ,
187+ } ;
198188
199- // // Set EPT root
200- // vcpu.set_ept_root(address_space.page_table_root())
201- // .map_err(|e| {
202- // anyhow::anyhow!("Failed to set EPT root for vCPU {}: {:?}", vcpu_id, e)
203- // })?;
189+ vcpu. vcpu
190+ . setup ( setup_config)
191+ . map_err ( |e| anyhow:: anyhow!( "Failed to setup vCPU : {e:?}" ) ) ?;
204192
205- // // Setup vCPU with configuration
206- // vcpu.setup(setup_config)
207- // .map_err(|e| anyhow::anyhow!("Failed to setup vCPU {}: {:?}", vcpu_id, e))?;
208- // }
193+ // Set EPT root
194+ vcpu. vcpu
195+ . set_ept_root ( run_data. address_space . page_table_root ( ) )
196+ . map_err ( |e| anyhow:: anyhow!( "Failed to set EPT root for vCPU : {e:?}" ) ) ?;
197+ }
209198
210199 self . state = StateMachine :: Inited ( run_data) ;
211200
@@ -318,29 +307,44 @@ impl VmOps for ArchVm {
318307 _ => return Err ( anyhow:: anyhow!( "VM is not in Inited state" ) ) ,
319308 } ;
320309
321- // Transition to Running state
322- // let new_data = RunData {
323- // // vcpus: BTreeMap::new(),
324- // // address_space: AddrSpace::new_empty(4, GuestPhysAddr::from(0), 0).unwrap(),
325- // devices: BTreeMap::new(),
326- // };
327- // let old_data = core::mem::replace(data, new_data);
328- // self.transition_state(StateMachine::Running(old_data))?;
329-
330- // // Start all vCPUs
331- // let vcpus = self.get_vcpus();
332- // for (vcpu_id, vcpu) in vcpus.iter().enumerate() {
333- // debug!("Starting vCPU {} for VM {}", vcpu_id, self.id);
334- // vcpu.bind()
335- // .map_err(|e| anyhow::anyhow!("Failed to bind vCPU {}: {:?}", vcpu_id, e))?;
336- // }
310+ let mut vcpus = vec ! [ ] ;
311+ vcpus. append ( & mut data. vcpus ) ;
312+ let mut vcpu_handles = vec ! [ ] ;
313+ let vm_id = self . id ;
314+ for mut vcpu in vcpus. into_iter ( ) {
315+ let vcpu_id = vcpu. id ;
316+ let bind_id = vcpu. binded_cpu_id ( ) ;
317+ let handle = std:: thread:: Builder :: new ( )
318+ . name ( format ! ( "{}-{vcpu_id}" , self . id, ) )
319+ . stack_size ( TASK_STACK_SIZE )
320+ . spawn ( move || {
321+ assert ! (
322+ set_current_affinity( AxCpuMask :: one_shot( bind_id. raw( ) ) ) ,
323+ "Initialize CPU affinity failed!"
324+ ) ;
325+ match vcpu. run ( ) {
326+ Ok ( ( ) ) => {
327+ info ! ( "vCPU {} of VM {} exited normally" , vcpu_id, vm_id) ;
328+ }
329+ Err ( e) => {
330+ error ! (
331+ "vCPU {} of VM {} exited with error: {:?}" ,
332+ vcpu_id, vm_id, e
333+ ) ;
334+ }
335+ }
336+ } )
337+ . map_err ( |e| anyhow ! ( "{e}" ) ) ?;
338+
339+ vcpu_handles. push ( handle) ;
340+ }
337341
338- // info!(
339- // "VM {} ({}) booted successfully with {} vCPUs ",
340- // self.id,
341- // self.name,
342- // vcpus .len()
343- // );
342+ info ! (
343+ "VM {} ({}) with {} cpus booted successfully. " ,
344+ self . id,
345+ self . name,
346+ vcpu_handles . len( )
347+ ) ;
344348
345349 Ok ( ( ) )
346350 }
@@ -523,7 +527,7 @@ enum StateMachine {
523527pub struct RunData {
524528 vcpus : Vec < VCpu > ,
525529 address_space : AddrSpace ,
526- regions : Vec < Region > ,
530+ regions : Vec < GuestRegion > ,
527531 devices : BTreeMap < String , DeviceInfo > ,
528532 kernel_entry : GuestPhysAddr ,
529533 dtb_addr : GuestPhysAddr ,
@@ -534,7 +538,7 @@ pub struct RunData {
534538
535539impl RunData {
536540 fn add_memory_region ( & mut self , config : & MemoryKind ) -> anyhow:: Result < ( ) > {
537- let region = Region :: new ( config) ;
541+ let region = GuestRegion :: new ( config) ;
538542 self . address_space
539543 . map_linear (
540544 region. gpa . as_usize ( ) . into ( ) ,
0 commit comments