@@ -17,15 +17,24 @@ limitations under the License.
1717// TODO(aarch64): implement arch-specific HyperlightVm methods
1818
1919use std:: sync:: Arc ;
20+ use std:: sync:: atomic:: { AtomicBool , AtomicU8 , AtomicU64 } ;
2021
2122use super :: {
2223 AccessPageTableError , CreateHyperlightVmError , DispatchGuestCallError , HyperlightVm ,
2324 InitializeError ,
2425} ;
2526#[ cfg( gdb) ]
2627use crate :: hypervisor:: gdb:: { DebugCommChannel , DebugMsg , DebugResponse } ;
27- use crate :: hypervisor:: regs:: CommonSpecialRegisters ;
28- use crate :: hypervisor:: virtual_machine:: RegisterError ;
28+ use crate :: hypervisor:: hyperlight_vm:: get_guest_log_filter;
29+ use crate :: hypervisor:: regs:: { CommonFpu , CommonRegisters , CommonSpecialRegisters } ;
30+ #[ cfg( kvm) ]
31+ use crate :: hypervisor:: virtual_machine:: kvm:: KvmVm ;
32+ #[ cfg( kvm) ]
33+ use crate :: hypervisor:: virtual_machine:: { HypervisorType , VmError } ;
34+ use crate :: hypervisor:: virtual_machine:: {
35+ ResetVcpuError , VirtualMachine , get_available_hypervisor,
36+ } ;
37+ use crate :: hypervisor:: { InterruptHandleImpl , LinuxInterruptHandle } ;
2938use crate :: mem:: mgr:: { SandboxMemoryManager , SnapshotSharedMemory } ;
3039use crate :: mem:: shared_mem:: { GuestSharedMemory , HostSharedMemory } ;
3140use crate :: sandbox:: SandboxConfiguration ;
@@ -39,61 +48,180 @@ use crate::sandbox::uninitialized::SandboxRuntimeConfig;
3948impl HyperlightVm {
4049 #[ allow( clippy:: too_many_arguments) ]
4150 pub ( crate ) fn new (
42- _snapshot_mem : SnapshotSharedMemory < GuestSharedMemory > ,
43- _scratch_mem : GuestSharedMemory ,
44- _root_pt_addr : u64 ,
45- _entrypoint : NextAction ,
46- _rsp_gva : u64 ,
47- _page_size : usize ,
48- _config : & SandboxConfiguration ,
51+ snapshot_mem : SnapshotSharedMemory < GuestSharedMemory > ,
52+ scratch_mem : GuestSharedMemory ,
53+ root_pt_addr : u64 ,
54+ entrypoint : NextAction ,
55+ rsp_gva : u64 ,
56+ page_size : usize ,
57+ config : & SandboxConfiguration ,
4958 #[ cfg( gdb) ] _gdb_conn : Option < DebugCommChannel < DebugResponse , DebugMsg > > ,
5059 #[ cfg( crashdump) ] _rt_cfg : SandboxRuntimeConfig ,
5160 #[ cfg( feature = "mem_profile" ) ] _trace_info : MemTraceInfo ,
5261 ) -> std:: result:: Result < Self , CreateHyperlightVmError > {
53- unimplemented ! ( "new" )
62+ // TODO: support gdb on aarch64
63+ type VmType = Box < dyn VirtualMachine > ;
64+ let vm: VmType = match get_available_hypervisor ( ) {
65+ #[ cfg( kvm) ]
66+ Some ( HypervisorType :: Kvm ) => Box :: new ( KvmVm :: new ( ) . map_err ( VmError :: CreateVm ) ?) ,
67+ // TODO: mshv support
68+ #[ cfg( mshv3) ]
69+ Some ( HypervisorType :: Mshv ) => return Err ( CreateHyperlightVmError :: NoHypervisorFound ) ,
70+ None => return Err ( CreateHyperlightVmError :: NoHypervisorFound ) ,
71+ } ;
72+ vm. set_sregs ( & CommonSpecialRegisters :: defaults ( root_pt_addr) )
73+ . map_err ( VmError :: Register ) ?;
74+ let interrupt_handle: Arc < dyn InterruptHandleImpl > = Arc :: new ( LinuxInterruptHandle {
75+ state : AtomicU8 :: new ( 0 ) ,
76+ tid : AtomicU64 :: new ( unsafe { libc:: pthread_self ( ) as u64 } ) ,
77+ retry_delay : config. get_interrupt_retry_delay ( ) ,
78+ sig_rt_min_offset : config. get_interrupt_vcpu_sigrtmin_offset ( ) ,
79+ dropped : AtomicBool :: new ( false ) ,
80+ } ) ;
81+
82+ let snapshot_slot = 0u32 ;
83+ let scratch_slot = 1u32 ;
84+ let vm_can_reset_vcpu = vm. can_reset_vcpu ( ) ;
85+ let mut ret = Self {
86+ vm,
87+ entrypoint,
88+ rsp_gva,
89+ interrupt_handle,
90+ page_size,
91+
92+ next_slot : scratch_slot + 1 ,
93+ freed_slots : Vec :: new ( ) ,
94+
95+ snapshot_slot,
96+ snapshot_memory : None ,
97+ scratch_slot,
98+ scratch_memory : None ,
99+
100+ mmap_regions : Vec :: new ( ) ,
101+
102+ vm_can_reset_vcpu,
103+ pending_tlb_flush : false ,
104+ } ;
105+ ret. update_snapshot_mapping ( snapshot_mem) ?;
106+ ret. update_scratch_mapping ( scratch_mem) ?;
107+ Ok ( ret)
54108 }
55109
56110 #[ allow( clippy:: too_many_arguments) ]
57111 pub ( crate ) fn initialise (
58112 & mut self ,
59- _peb_addr : crate :: mem:: ptr:: RawPtr ,
60- _seed : u64 ,
61- _mem_mgr : & mut SandboxMemoryManager < HostSharedMemory > ,
62- _host_funcs : & Arc < std:: sync:: Mutex < FunctionRegistry > > ,
63- _guest_max_log_level : Option < tracing_core:: LevelFilter > ,
64- #[ cfg( gdb) ] _dbg_mem_access_fn : Arc <
113+ peb_addr : crate :: mem:: ptr:: RawPtr ,
114+ seed : u64 ,
115+ mem_mgr : & mut SandboxMemoryManager < HostSharedMemory > ,
116+ host_funcs : & Arc < std:: sync:: Mutex < FunctionRegistry > > ,
117+ guest_max_log_level : Option < tracing_core:: LevelFilter > ,
118+ #[ cfg( gdb) ] dbg_mem_access_fn : Arc <
65119 std:: sync:: Mutex < SandboxMemoryManager < HostSharedMemory > > ,
66120 > ,
67121 ) -> Result < ( ) , InitializeError > {
68- unimplemented ! ( "initialise" )
122+ let NextAction :: Initialise ( initialise) = self . entrypoint else {
123+ return Ok ( ( ) ) ;
124+ } ;
125+ let mut x: [ u64 ; 31 ] = [ 0 ; 31 ] ;
126+ x[ 0 ] = peb_addr. into ( ) ;
127+ x[ 1 ] = seed;
128+ x[ 2 ] = self . page_size as u64 ;
129+ x[ 3 ] = get_guest_log_filter ( guest_max_log_level) ;
130+ let regs = CommonRegisters {
131+ pc : initialise,
132+ sp : self . rsp_gva ,
133+ x,
134+ // start up with interrupts disabled in EL1t
135+ pstate : 0b11 << 6 | 0b100 ,
136+ } ;
137+ self . vm . set_regs ( & regs) ?;
138+
139+ self . run (
140+ mem_mgr,
141+ host_funcs,
142+ #[ cfg( gdb) ]
143+ dbg_mem_access_fn,
144+ )
145+ . map_err ( InitializeError :: Run ) ?;
146+
147+ let regs = self . vm . regs ( ) ?;
148+ if !regs. sp . is_multiple_of ( 16 ) {
149+ return Err ( InitializeError :: InvalidStackPointer ( regs. sp ) ) ;
150+ }
151+ self . rsp_gva = regs. sp ;
152+ self . entrypoint = NextAction :: Call ( regs. x [ 0 ] ) ;
153+
154+ Ok ( ( ) )
69155 }
70156
71157 pub ( crate ) fn dispatch_call_from_host (
72158 & mut self ,
73- _mem_mgr : & mut SandboxMemoryManager < HostSharedMemory > ,
74- _host_funcs : & Arc < std:: sync:: Mutex < FunctionRegistry > > ,
159+ mem_mgr : & mut SandboxMemoryManager < HostSharedMemory > ,
160+ host_funcs : & Arc < std:: sync:: Mutex < FunctionRegistry > > ,
75161 #[ cfg( gdb) ] _dbg_mem_access_fn : Arc <
76162 std:: sync:: Mutex < SandboxMemoryManager < HostSharedMemory > > ,
77163 > ,
78164 ) -> Result < ( ) , DispatchGuestCallError > {
79- unimplemented ! ( "dispatch_call_from_host" )
165+ let NextAction :: Call ( dispatch_func_addr) = self . entrypoint else {
166+ return Err ( DispatchGuestCallError :: Uninitialized ) ;
167+ } ;
168+ let mut regs = CommonRegisters {
169+ pc : dispatch_func_addr,
170+ sp : self . rsp_gva ,
171+ // start with interrupts disabled in EL1t
172+ pstate : 0b1 << 21 | 0b11 << 6 | 0b100 ,
173+ ..Default :: default ( )
174+ } ;
175+ if self . pending_tlb_flush {
176+ regs. pc += 4 ;
177+ }
178+ self . vm
179+ . set_regs ( & regs)
180+ . map_err ( DispatchGuestCallError :: SetupRegs ) ?;
181+ self . vm
182+ . set_fpu ( & CommonFpu :: default ( ) )
183+ . map_err ( DispatchGuestCallError :: SetupRegs ) ?;
184+ let result = self
185+ . run (
186+ mem_mgr,
187+ host_funcs,
188+ #[ cfg( gdb) ]
189+ mem_access_fn,
190+ )
191+ . map_err ( DispatchGuestCallError :: Run ) ;
192+ self . pending_tlb_flush = false ;
193+ result
80194 }
81195
82196 pub ( crate ) fn get_root_pt ( & self ) -> Result < u64 , AccessPageTableError > {
83- unimplemented ! ( "get_root_pt" )
197+ let sregs = self . vm . sregs ( ) ?;
198+ Ok ( sregs. ttbr0_el1 & ( ( 1 << 48 ) - 2 ) )
84199 }
85200
86201 pub ( crate ) fn get_snapshot_sregs (
87202 & mut self ,
88203 ) -> Result < CommonSpecialRegisters , AccessPageTableError > {
89- unimplemented ! ( "get_snapshot_sregs" )
204+ let x = self . vm . sregs ( ) ?;
205+ Ok ( x)
90206 }
91207
92208 pub ( crate ) fn reset_vcpu (
93209 & mut self ,
94- _cr3 : u64 ,
95- _sregs : & CommonSpecialRegisters ,
96- ) -> std:: result:: Result < ( ) , RegisterError > {
97- unimplemented ! ( "reset_vcpu" )
210+ cr3 : u64 ,
211+ sregs : & CommonSpecialRegisters ,
212+ ) -> std:: result:: Result < ( ) , ResetVcpuError > {
213+ self . pending_tlb_flush = true ;
214+ debug_assert ! (
215+ self . vm_can_reset_vcpu,
216+ "No fallback path for vcpu reset on aarch64"
217+ ) ;
218+ self . vm . reset_vcpu ( ) ?;
219+ let mut sregs = * sregs;
220+ sregs. ttbr0_el1 = cr3 & ( ( 1 << 48 ) - 2 ) ;
221+
222+ self . vm
223+ . set_sregs ( & sregs)
224+ . map_err ( ResetVcpuError :: Register ) ?;
225+ Ok ( ( ) )
98226 }
99227}
0 commit comments