Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/hypervisor/tests/real_run_addr.rs
5394 views
1
// Copyright 2017 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
// TODO(b/237714823): Currently, only kvm is enabled for this test once LUCI can run windows.
6
#![cfg(any(target_os = "android", target_os = "linux"))]
7
#![cfg(target_arch = "x86_64")]
8
9
use hypervisor::*;
10
use sync::Mutex;
11
use vm_memory::GuestAddress;
12
use vm_memory::GuestMemory;
13
14
#[test]
15
#[cfg(any(target_os = "android", target_os = "linux"))]
16
fn test_kvm_real_run_addr() {
17
use hypervisor::kvm::*;
18
test_real_run_addr(|guest_mem| {
19
let kvm = Kvm::new().expect("failed to create kvm");
20
let vm = KvmVm::new(&kvm, guest_mem, Default::default()).expect("failed to create vm");
21
(kvm, vm)
22
});
23
}
24
25
#[test]
26
#[cfg(all(windows, feature = "haxm"))]
27
fn test_haxm_real_run_addr() {
28
use hypervisor::haxm::*;
29
test_real_run_addr(|guest_mem| {
30
let haxm = Haxm::new().expect("failed to create haxm");
31
let vm = HaxmVm::new(&haxm, guest_mem).expect("failed to create vm");
32
(haxm, vm)
33
});
34
}
35
36
#[test]
37
#[cfg(feature = "gvm")]
38
fn test_gvm_real_run_addr() {
39
use hypervisor::gvm::*;
40
test_real_run_addr(|guest_mem| {
41
let gvm = Gvm::new().expect("failed to create gvm");
42
let vm = GvmVm::new(&gvm, guest_mem).expect("failed to create vm");
43
(gvm, vm)
44
});
45
}
46
47
#[test]
48
#[cfg(all(windows, feature = "whpx"))]
49
fn test_whpx_real_run_addr() {
50
use hypervisor::whpx::*;
51
if !Whpx::is_enabled() {
52
return;
53
}
54
test_real_run_addr(|guest_mem| {
55
let whpx = Whpx::new().expect("failed to create whpx");
56
let vm =
57
WhpxVm::new(&whpx, 1, guest_mem, CpuId::new(0), false).expect("failed to create vm");
58
(whpx, vm)
59
});
60
}
61
62
fn test_real_run_addr<CreateVm, HypervisorT, VmT>(create_vm: CreateVm)
63
where
64
CreateVm: FnOnce(GuestMemory) -> (HypervisorT, VmT),
65
HypervisorT: Hypervisor,
66
VmT: VmX86_64,
67
{
68
// This example based on https://lwn.net/Articles/658511/
69
let code = [
70
0xba, 0xf8, 0x03, /* mov $0x3f8, %dx */
71
0x00, 0xd8, /* add %bl, %al */
72
0x04, b'0', /* add $'0', %al */
73
0xee, /* out %al, (%dx) */
74
0xb0, b'\n', /* mov $'\n', %al */
75
0xee, /* out %al, (%dx) */
76
0x2e, 0xc6, 0x06, 0xf1, 0x10, 0x13, /* movb $0x13, %cs:0xf1 */
77
0xf4, /* hlt */
78
];
79
80
let mem_size = 0x1000;
81
let load_addr = GuestAddress(0x1000);
82
let mem = GuestMemory::new(&[(load_addr, mem_size)]).unwrap();
83
84
let (_hyp, vm) = create_vm(mem);
85
let mut vcpu = vm.create_vcpu(0).expect("new vcpu failed");
86
87
vm.get_memory()
88
.write_at_addr(&code, load_addr)
89
.expect("Writing code to memory failed.");
90
91
let mut vcpu_sregs = vcpu.get_sregs().expect("get sregs failed");
92
assert_ne!(vcpu_sregs.cs.base, 0);
93
assert_ne!(vcpu_sregs.cs.selector, 0);
94
vcpu_sregs.cs.base = 0;
95
vcpu_sregs.cs.selector = 0;
96
vcpu.set_sregs(&vcpu_sregs).expect("set sregs failed");
97
98
let vcpu_regs = Regs {
99
rip: 0x1000,
100
rax: 2,
101
rbx: 7,
102
rflags: 2,
103
..Default::default()
104
};
105
vcpu.set_regs(&vcpu_regs).expect("set regs failed");
106
107
let out = Mutex::new(String::new());
108
loop {
109
match vcpu.run().expect("run failed") {
110
VcpuExit::Io => {
111
vcpu.handle_io(&mut |IoParams { address, operation }| match operation {
112
IoOperation::Read(_) => {
113
panic!("unexpected io in call");
114
}
115
IoOperation::Write(data) => {
116
assert_eq!(address, 0x3f8);
117
assert_eq!(data.len(), 1);
118
out.lock().push(data[0] as char);
119
}
120
})
121
.expect("failed to set the data");
122
}
123
// Continue on external interrupt or signal
124
VcpuExit::Intr => continue,
125
VcpuExit::Hlt => break,
126
r => panic!("unexpected exit reason: {r:?}"),
127
}
128
}
129
130
assert_eq!(out.lock().as_str(), "9\n");
131
let result: u8 = vm
132
.get_memory()
133
.read_obj_from_addr(load_addr.checked_add(0xf1).unwrap())
134
.expect("Error reading the result.");
135
assert_eq!(result, 0x13);
136
}
137
138