@@ -23,12 +23,13 @@ use crate::Result;
2323use crate :: hypervisor:: regs:: { CommonFpu , CommonRegisters , CommonSpecialRegisters } ;
2424use crate :: mem:: memory_region:: MemoryRegion ;
2525
26+ /// KVM (Kernel-based Virtual Machine) functionality (linux)
2627#[ cfg( kvm) ]
27- /// Functionality to manipulate KVM-based virtual machines
2828pub ( crate ) mod kvm;
29- /// HyperV-on-linux functionality
29+ /// MSHV (Microsoft Hypervisor) functionality (linux)
3030#[ cfg( mshv3) ]
3131pub ( crate ) mod mshv;
32+ /// WHP (Windows Hypervisor Platform) functionality (windows)
3233#[ cfg( target_os = "windows" ) ]
3334pub ( crate ) mod whp;
3435
@@ -180,6 +181,30 @@ pub(crate) trait Vm: Debug + Send {
180181
181182#[ cfg( test) ]
182183mod tests {
184+ use crate :: hypervisor:: regs:: { CommonSegmentRegister , CommonTableRegister } ;
185+
186+ use super :: * ;
187+
188+ fn boxed_vm ( ) -> Box < dyn Vm > {
189+ let available_vm = get_available_hypervisor ( ) . as_ref ( ) . unwrap ( ) ;
190+ match available_vm {
191+ #[ cfg( kvm) ]
192+ HypervisorType :: Kvm => {
193+ use crate :: hypervisor:: vm:: kvm:: KvmVm ;
194+ Box :: new ( KvmVm :: new ( ) . unwrap ( ) )
195+ }
196+ #[ cfg( mshv3) ]
197+ HypervisorType :: Mshv => {
198+ use crate :: hypervisor:: vm:: mshv:: MshvVm ;
199+ Box :: new ( MshvVm :: new ( ) . unwrap ( ) )
200+ }
201+ #[ cfg( target_os = "windows" ) ]
202+ HypervisorType :: Whp => {
203+ use crate :: hypervisor:: vm:: whp:: WhpVm ;
204+ Box :: new ( WhpVm :: new ( ) . unwrap ( ) )
205+ }
206+ }
207+ }
183208
184209 #[ test]
185210 // TODO: add support for testing on WHP
@@ -199,4 +224,126 @@ mod tests {
199224 }
200225 }
201226 }
227+
228+ #[ test]
229+ fn regs ( ) {
230+ let vm = boxed_vm ( ) ;
231+
232+ let regs = CommonRegisters {
233+ rax : 1 ,
234+ rbx : 2 ,
235+ rcx : 3 ,
236+ rdx : 4 ,
237+ rsi : 5 ,
238+ rdi : 6 ,
239+ rsp : 7 ,
240+ rbp : 8 ,
241+ r8 : 9 ,
242+ r9 : 10 ,
243+ r10 : 11 ,
244+ r11 : 12 ,
245+ r12 : 13 ,
246+ r13 : 14 ,
247+ r14 : 15 ,
248+ r15 : 16 ,
249+ rip : 17 ,
250+ rflags : 0x2 ,
251+ } ;
252+
253+ vm. set_regs ( & regs) . unwrap ( ) ;
254+ let read_regs = vm. regs ( ) . unwrap ( ) ;
255+ assert_eq ! ( regs, read_regs) ;
256+ }
257+
258+ #[ test]
259+ fn fpu ( ) {
260+ let vm = boxed_vm ( ) ;
261+
262+ let fpu = CommonFpu {
263+ fpr : [ [ 1 ; 16 ] ; 8 ] ,
264+ fcw : 2 ,
265+ fsw : 3 ,
266+ ftwx : 4 ,
267+ last_opcode : 5 ,
268+ last_ip : 6 ,
269+ last_dp : 7 ,
270+ xmm : [ [ 8 ; 16 ] ; 16 ] ,
271+ mxcsr : 9 ,
272+ pad1 : 0 ,
273+ pad2 : 0 ,
274+ } ;
275+ vm. set_fpu ( & fpu) . unwrap ( ) ;
276+ #[ cfg_attr( kvm, allow( unused_mut) ) ]
277+ let mut read_fpu = vm. fpu ( ) . unwrap ( ) ;
278+ #[ cfg( kvm) ]
279+ {
280+ read_fpu. mxcsr = fpu. mxcsr ; // KVM get/set fpu does not preserve mxcsr
281+ }
282+ assert_eq ! ( fpu, read_fpu) ;
283+ }
284+
285+ #[ test]
286+ fn sregs ( ) {
287+ let vm = boxed_vm ( ) ;
288+
289+ let segment = CommonSegmentRegister {
290+ base : 1 ,
291+ limit : 2 ,
292+ selector : 3 ,
293+ type_ : 3 ,
294+ present : 1 ,
295+ dpl : 1 ,
296+ db : 0 ,
297+ s : 1 ,
298+ l : 1 ,
299+ g : 1 ,
300+ avl : 1 ,
301+ unusable : 0 ,
302+ padding : 0 ,
303+ } ;
304+
305+ let cs_segment = CommonSegmentRegister {
306+ base : 1 ,
307+ limit : 0xFFFF ,
308+ selector : 0x08 ,
309+ type_ : 0b1011 , // code segment, execute/read, accessed
310+ present : 1 ,
311+ dpl : 1 ,
312+ db : 0 , // must be 0 in 64-bit mode
313+ s : 1 ,
314+ l : 1 , // 64-bit mode
315+ g : 1 ,
316+ avl : 1 ,
317+ unusable : 0 ,
318+ padding : 0 ,
319+ } ;
320+ let table = CommonTableRegister {
321+ base : 12 ,
322+ limit : 13 ,
323+ } ;
324+ let sregs = CommonSpecialRegisters {
325+ cs : cs_segment,
326+ ds : segment,
327+ es : segment,
328+ fs : segment,
329+ gs : segment,
330+ ss : segment,
331+ tr : segment,
332+ ldt : segment,
333+ gdt : table,
334+ idt : table,
335+ cr0 : 0x80000001 ,
336+ cr2 : 2 ,
337+ cr3 : 3 ,
338+ cr4 : 0x20 ,
339+ cr8 : 5 ,
340+ efer : 0x500 ,
341+ apic_base : 0xFEE00900 ,
342+ interrupt_bitmap : [ 0 ; 4 ] ,
343+ ..Default :: default ( )
344+ } ;
345+ vm. set_sregs ( & sregs) . unwrap ( ) ;
346+ let read_sregs = vm. sregs ( ) . unwrap ( ) ;
347+ assert_eq ! ( sregs, read_sregs) ;
348+ }
202349}
0 commit comments