@@ -181,6 +181,29 @@ pub(crate) trait Vm: Debug + Send {
181181
182182#[ cfg( test) ]
183183mod tests {
184+ use super :: * ;
185+ use crate :: hypervisor:: regs:: { CommonSegmentRegister , CommonTableRegister } ;
186+
187+ fn boxed_vm ( ) -> Box < dyn Vm > {
188+ let available_vm = get_available_hypervisor ( ) . as_ref ( ) . unwrap ( ) ;
189+ match available_vm {
190+ #[ cfg( kvm) ]
191+ HypervisorType :: Kvm => {
192+ use crate :: hypervisor:: vm:: kvm:: KvmVm ;
193+ Box :: new ( KvmVm :: new ( ) . unwrap ( ) )
194+ }
195+ #[ cfg( mshv3) ]
196+ HypervisorType :: Mshv => {
197+ use crate :: hypervisor:: vm:: mshv:: MshvVm ;
198+ Box :: new ( MshvVm :: new ( ) . unwrap ( ) )
199+ }
200+ #[ cfg( target_os = "windows" ) ]
201+ HypervisorType :: Whp => {
202+ use crate :: hypervisor:: vm:: whp:: WhpVm ;
203+ Box :: new ( WhpVm :: new ( ) . unwrap ( ) )
204+ }
205+ }
206+ }
184207
185208 #[ test]
186209 // TODO: add support for testing on WHP
@@ -200,4 +223,205 @@ mod tests {
200223 }
201224 }
202225 }
226+
227+ #[ test]
228+ fn regs ( ) {
229+ let vm = boxed_vm ( ) ;
230+
231+ let regs = CommonRegisters {
232+ rax : 1 ,
233+ rbx : 2 ,
234+ rcx : 3 ,
235+ rdx : 4 ,
236+ rsi : 5 ,
237+ rdi : 6 ,
238+ rsp : 7 ,
239+ rbp : 8 ,
240+ r8 : 9 ,
241+ r9 : 10 ,
242+ r10 : 11 ,
243+ r11 : 12 ,
244+ r12 : 13 ,
245+ r13 : 14 ,
246+ r14 : 15 ,
247+ r15 : 16 ,
248+ rip : 17 ,
249+ rflags : 0x2 ,
250+ } ;
251+
252+ vm. set_regs ( & regs) . unwrap ( ) ;
253+ let read_regs = vm. regs ( ) . unwrap ( ) ;
254+ assert_eq ! ( regs, read_regs) ;
255+ }
256+
257+ #[ test]
258+ fn fpu ( ) {
259+ let vm = boxed_vm ( ) ;
260+
261+ let fpu = CommonFpu {
262+ fpr : [ [ 1 ; 16 ] ; 8 ] ,
263+ fcw : 2 ,
264+ fsw : 3 ,
265+ ftwx : 4 ,
266+ last_opcode : 5 ,
267+ last_ip : 6 ,
268+ last_dp : 7 ,
269+ xmm : [ [ 8 ; 16 ] ; 16 ] ,
270+ mxcsr : 9 ,
271+ pad1 : 0 ,
272+ pad2 : 0 ,
273+ } ;
274+ vm. set_fpu ( & fpu) . unwrap ( ) ;
275+ #[ cfg_attr( kvm, allow( unused_mut) ) ]
276+ let mut read_fpu = vm. fpu ( ) . unwrap ( ) ;
277+ #[ cfg( kvm) ]
278+ {
279+ read_fpu. mxcsr = fpu. mxcsr ; // KVM get/set fpu does not preserve mxcsr
280+ }
281+ assert_eq ! ( fpu, read_fpu) ;
282+ }
283+
284+ #[ test]
285+ fn sregs ( ) {
286+ let vm = boxed_vm ( ) ;
287+
288+ let segment = CommonSegmentRegister {
289+ base : 1 ,
290+ limit : 2 ,
291+ selector : 3 ,
292+ type_ : 3 ,
293+ present : 1 ,
294+ dpl : 1 ,
295+ db : 0 ,
296+ s : 1 ,
297+ l : 1 ,
298+ g : 1 ,
299+ avl : 1 ,
300+ unusable : 0 ,
301+ padding : 0 ,
302+ } ;
303+
304+ let cs_segment = CommonSegmentRegister {
305+ base : 1 ,
306+ limit : 0xFFFF ,
307+ selector : 0x08 ,
308+ type_ : 0b1011 , // code segment, execute/read, accessed
309+ present : 1 ,
310+ dpl : 1 ,
311+ db : 0 , // must be 0 in 64-bit mode
312+ s : 1 ,
313+ l : 1 , // 64-bit mode
314+ g : 1 ,
315+ avl : 1 ,
316+ unusable : 0 ,
317+ padding : 0 ,
318+ } ;
319+ let table = CommonTableRegister {
320+ base : 12 ,
321+ limit : 13 ,
322+ } ;
323+ let sregs = CommonSpecialRegisters {
324+ cs : cs_segment,
325+ ds : segment,
326+ es : segment,
327+ fs : segment,
328+ gs : segment,
329+ ss : segment,
330+ tr : segment,
331+ ldt : segment,
332+ gdt : table,
333+ idt : table,
334+ cr0 : 0x80000001 ,
335+ cr2 : 2 ,
336+ cr3 : 3 ,
337+ cr4 : 0x20 ,
338+ cr8 : 5 ,
339+ efer : 0x500 ,
340+ apic_base : 0xFEE00900 ,
341+ interrupt_bitmap : [ 0 ; 4 ] ,
342+ } ;
343+ vm. set_sregs ( & sregs) . unwrap ( ) ;
344+ let read_sregs = vm. sregs ( ) . unwrap ( ) ;
345+ assert_eq ! ( sregs, read_sregs) ;
346+ }
347+
348+ /// Helper to create a page-aligned memory region for testing
349+ fn create_test_memory ( size : usize ) -> crate :: mem:: shared_mem:: ExclusiveSharedMemory {
350+ use hyperlight_common:: mem:: PAGE_SIZE_USIZE ;
351+ let aligned_size = size. div_ceil ( PAGE_SIZE_USIZE ) * PAGE_SIZE_USIZE ;
352+ crate :: mem:: shared_mem:: ExclusiveSharedMemory :: new ( aligned_size) . unwrap ( )
353+ }
354+
355+ /// Helper to create a MemoryRegion from ExclusiveSharedMemory
356+ fn region_for_test_memory (
357+ mem : & crate :: mem:: shared_mem:: ExclusiveSharedMemory ,
358+ guest_base : usize ,
359+ flags : crate :: mem:: memory_region:: MemoryRegionFlags ,
360+ ) -> MemoryRegion {
361+ use crate :: mem:: memory_region:: MemoryRegionType ;
362+ use crate :: mem:: shared_mem:: SharedMemory ;
363+ let ptr = mem. base_addr ( ) ;
364+ let len = mem. mem_size ( ) ;
365+ MemoryRegion {
366+ host_region : ptr..( ptr + len) ,
367+ guest_region : guest_base..( guest_base + len) ,
368+ flags,
369+ region_type : MemoryRegionType :: Heap ,
370+ }
371+ }
372+
373+ #[ test]
374+ fn map_memory ( ) {
375+ use crate :: mem:: memory_region:: MemoryRegionFlags ;
376+
377+ let mut vm = boxed_vm ( ) ;
378+
379+ let mem1 = create_test_memory ( 4096 ) ;
380+ let guest_addr: usize = 0x1000 ;
381+ let region = region_for_test_memory (
382+ & mem1,
383+ guest_addr,
384+ MemoryRegionFlags :: READ | MemoryRegionFlags :: WRITE ,
385+ ) ;
386+
387+ // SAFETY: The memory region points to valid memory allocated by ExclusiveSharedMemory,
388+ // and will live until we drop mem1 at the end of the test.
389+ // Slot 0 is not already mapped.
390+ unsafe {
391+ vm. map_memory ( ( 0 , & region) ) . unwrap ( ) ;
392+ }
393+
394+ // Unmap the region
395+ vm. unmap_memory ( ( 0 , & region) ) . unwrap ( ) ;
396+
397+ // Unmapping a region that was already unmapped should fail
398+ vm. unmap_memory ( ( 0 , & region) ) . unwrap_err ( ) ;
399+
400+ // Unmapping a region that was never mapped should fail
401+ vm. unmap_memory ( ( 99 , & region) ) . unwrap_err ( ) ;
402+
403+ // Re-map the same region to a different slot
404+ // SAFETY: Same as above - memory is still valid and slot 1 is not mapped.
405+ unsafe {
406+ vm. map_memory ( ( 1 , & region) ) . unwrap ( ) ;
407+ }
408+
409+ // Map a second region to a different slot
410+ let mem2 = create_test_memory ( 4096 ) ;
411+ let guest_addr2: usize = 0x2000 ;
412+ let region2 = region_for_test_memory (
413+ & mem2,
414+ guest_addr2,
415+ MemoryRegionFlags :: READ | MemoryRegionFlags :: WRITE ,
416+ ) ;
417+
418+ // SAFETY: Memory is valid from ExclusiveSharedMemory, slot 2 is not mapped.
419+ unsafe {
420+ vm. map_memory ( ( 2 , & region2) ) . unwrap ( ) ;
421+ }
422+
423+ // Clean up: unmap both regions
424+ vm. unmap_memory ( ( 1 , & region) ) . unwrap ( ) ;
425+ vm. unmap_memory ( ( 2 , & region2) ) . unwrap ( ) ;
426+ }
203427}
0 commit comments