• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #![cfg(target_arch = "x86_64")]
6 #![cfg(any(feature = "whpx", feature = "gvm", feature = "haxm", unix))]
7 
8 use hypervisor::*;
9 use vm_memory::GuestAddress;
10 use vm_memory::GuestMemory;
11 
12 #[test]
13 #[cfg(any(target_os = "android", target_os = "linux"))]
test_kvm_minimal_virtualization()14 fn test_kvm_minimal_virtualization() {
15     use hypervisor::kvm::*;
16     test_minimal_virtualization(|guest_mem| {
17         let kvm = Kvm::new().expect("failed to create kvm");
18         let vm = KvmVm::new(&kvm, guest_mem, Default::default()).expect("failed to create vm");
19         (kvm, vm)
20     });
21 }
22 
23 #[test]
24 #[cfg(all(windows, feature = "haxm"))]
test_haxm_minimal_virtualization()25 fn test_haxm_minimal_virtualization() {
26     use hypervisor::haxm::*;
27     test_minimal_virtualization(|guest_mem| {
28         let haxm = Haxm::new().expect("failed to create haxm");
29         let vm = HaxmVm::new(&haxm, guest_mem).expect("failed to create vm");
30         (haxm, vm)
31     });
32 }
33 
34 #[test]
35 #[cfg(feature = "gvm")]
test_gvm_minimal_virtualization()36 fn test_gvm_minimal_virtualization() {
37     use hypervisor::gvm::*;
38     test_minimal_virtualization(|guest_mem| {
39         let gvm = Gvm::new().expect("failed to create gvm");
40         let vm = GvmVm::new(&gvm, guest_mem).expect("failed to create vm");
41         (gvm, vm)
42     });
43 }
44 
45 #[test]
46 #[cfg(all(windows, feature = "whpx"))]
test_whpx_minimal_virtualization()47 fn test_whpx_minimal_virtualization() {
48     use hypervisor::whpx::*;
49     test_minimal_virtualization(|guest_mem| {
50         let whpx = Whpx::new().expect("failed to create whpx");
51         let vm = WhpxVm::new(&whpx, 1, guest_mem, CpuId::new(0), false, None)
52             .expect("failed to create vm");
53         (whpx, vm)
54     });
55 }
56 
57 // This runs a minimal program under virtualization.
58 // It should require only the ability to execute instructions under virtualization, physical
59 // memory, the ability to get and set some guest VM registers, and intercepting HLT.
test_minimal_virtualization<CreateVm, HypervisorT, VmT>(create_vm: CreateVm) where CreateVm: FnOnce(GuestMemory) -> (HypervisorT, VmT), HypervisorT: Hypervisor, VmT: VmX86_64,60 fn test_minimal_virtualization<CreateVm, HypervisorT, VmT>(create_vm: CreateVm)
61 where
62     CreateVm: FnOnce(GuestMemory) -> (HypervisorT, VmT),
63     HypervisorT: Hypervisor,
64     VmT: VmX86_64,
65 {
66     /*
67     0x0000000000000002:  01 D8       add ax, bx
68     0x0000000000000002:  F4          hlt
69     */
70 
71     let code: [u8; 3] = [0x01, 0xd8, 0xf4];
72     let mem_size = 0x2000;
73     let load_addr = GuestAddress(0x1000);
74 
75     let guest_mem =
76         GuestMemory::new(&[(GuestAddress(0), mem_size)]).expect("failed to create guest mem");
77     guest_mem
78         .write_at_addr(&code[..], load_addr)
79         .expect("failed to write to guest memory");
80 
81     let (_, vm) = create_vm(guest_mem);
82     let mut vcpu = vm.create_vcpu(0).expect("new vcpu failed");
83     let mut vcpu_sregs = vcpu.get_sregs().expect("get sregs failed");
84     vcpu_sregs.cs.base = 0;
85     vcpu_sregs.cs.selector = 0;
86 
87     vcpu.set_sregs(&vcpu_sregs).expect("set sregs failed");
88 
89     let vcpu_regs = Regs {
90         rip: load_addr.offset(),
91         rflags: 2,
92         rax: 1,
93         rbx: 2,
94         ..Default::default()
95     };
96     vcpu.set_regs(&vcpu_regs).expect("set regs failed");
97 
98     loop {
99         match vcpu.run().expect("run failed") {
100             VcpuExit::Hlt => {
101                 break;
102             }
103             // Continue on external interrupt or signal
104             VcpuExit::Intr => continue,
105             r => panic!("unexpected exit reason: {:?}", r),
106         }
107     }
108 
109     let regs: Regs = vcpu.get_regs().expect("failed to get regs");
110     assert_eq!(regs.rax, 3);
111 }
112