xref: /aosp_15_r20/external/crosvm/tests/plugins.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2017 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker #![cfg(feature = "plugin")]
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use std::env::current_exe;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::env::var_os;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::OsString;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::remove_file;
11*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Read;
12*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
13*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
14*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
15*bb4ee6a4SAndroid Build Coastguard Worker use std::process::Command;
16*bb4ee6a4SAndroid Build Coastguard Worker use std::process::Stdio;
17*bb4ee6a4SAndroid Build Coastguard Worker use std::thread::sleep;
18*bb4ee6a4SAndroid Build Coastguard Worker use std::time::Duration;
19*bb4ee6a4SAndroid Build Coastguard Worker 
20*bb4ee6a4SAndroid Build Coastguard Worker use base::ioctl;
21*bb4ee6a4SAndroid Build Coastguard Worker use base::AsRawDescriptor;
22*bb4ee6a4SAndroid Build Coastguard Worker use net_util::TapTCommon;
23*bb4ee6a4SAndroid Build Coastguard Worker use once_cell::sync::Lazy;
24*bb4ee6a4SAndroid Build Coastguard Worker use rand::random;
25*bb4ee6a4SAndroid Build Coastguard Worker use tempfile::tempfile;
26*bb4ee6a4SAndroid Build Coastguard Worker 
27*bb4ee6a4SAndroid Build Coastguard Worker static TAP_AVAILABLE: Lazy<bool> =
28*bb4ee6a4SAndroid Build Coastguard Worker     Lazy::new(|| net_util::sys::linux::Tap::new(true, false).is_ok());
29*bb4ee6a4SAndroid Build Coastguard Worker 
30*bb4ee6a4SAndroid Build Coastguard Worker struct RemovePath(PathBuf);
31*bb4ee6a4SAndroid Build Coastguard Worker impl Drop for RemovePath {
drop(&mut self)32*bb4ee6a4SAndroid Build Coastguard Worker     fn drop(&mut self) {
33*bb4ee6a4SAndroid Build Coastguard Worker         if let Err(e) = remove_file(&self.0) {
34*bb4ee6a4SAndroid Build Coastguard Worker             eprintln!("failed to remove path: {}", e);
35*bb4ee6a4SAndroid Build Coastguard Worker         }
36*bb4ee6a4SAndroid Build Coastguard Worker     }
37*bb4ee6a4SAndroid Build Coastguard Worker }
38*bb4ee6a4SAndroid Build Coastguard Worker 
get_target_path() -> PathBuf39*bb4ee6a4SAndroid Build Coastguard Worker fn get_target_path() -> PathBuf {
40*bb4ee6a4SAndroid Build Coastguard Worker     current_exe()
41*bb4ee6a4SAndroid Build Coastguard Worker         .ok()
42*bb4ee6a4SAndroid Build Coastguard Worker         .map(|mut path| {
43*bb4ee6a4SAndroid Build Coastguard Worker             path.pop();
44*bb4ee6a4SAndroid Build Coastguard Worker             path
45*bb4ee6a4SAndroid Build Coastguard Worker         })
46*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to get crosvm binary directory")
47*bb4ee6a4SAndroid Build Coastguard Worker }
48*bb4ee6a4SAndroid Build Coastguard Worker 
get_crosvm_path() -> PathBuf49*bb4ee6a4SAndroid Build Coastguard Worker fn get_crosvm_path() -> PathBuf {
50*bb4ee6a4SAndroid Build Coastguard Worker     current_exe()
51*bb4ee6a4SAndroid Build Coastguard Worker         .ok()
52*bb4ee6a4SAndroid Build Coastguard Worker         .map(|mut path| {
53*bb4ee6a4SAndroid Build Coastguard Worker             path.pop();
54*bb4ee6a4SAndroid Build Coastguard Worker             if path.ends_with("deps") {
55*bb4ee6a4SAndroid Build Coastguard Worker                 path.pop();
56*bb4ee6a4SAndroid Build Coastguard Worker             }
57*bb4ee6a4SAndroid Build Coastguard Worker             path
58*bb4ee6a4SAndroid Build Coastguard Worker         })
59*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to get crosvm binary directory")
60*bb4ee6a4SAndroid Build Coastguard Worker }
61*bb4ee6a4SAndroid Build Coastguard Worker 
build_plugin(src: &str) -> RemovePath62*bb4ee6a4SAndroid Build Coastguard Worker fn build_plugin(src: &str) -> RemovePath {
63*bb4ee6a4SAndroid Build Coastguard Worker     let libcrosvm_plugin_dir = get_target_path();
64*bb4ee6a4SAndroid Build Coastguard Worker     let mut out_bin = libcrosvm_plugin_dir.clone();
65*bb4ee6a4SAndroid Build Coastguard Worker     out_bin.push(format!("plugin-test-{:08X}", random::<u32>()));
66*bb4ee6a4SAndroid Build Coastguard Worker     let mut child = Command::new(var_os("CC").unwrap_or(OsString::from("cc")))
67*bb4ee6a4SAndroid Build Coastguard Worker         .args(["-Icrosvm_plugin", "-pthread", "-o"]) // crosvm.h location and set output path.
68*bb4ee6a4SAndroid Build Coastguard Worker         .arg(&out_bin)
69*bb4ee6a4SAndroid Build Coastguard Worker         .arg("-L") // Path of shared object to link to.
70*bb4ee6a4SAndroid Build Coastguard Worker         .arg(&libcrosvm_plugin_dir)
71*bb4ee6a4SAndroid Build Coastguard Worker         .arg("-Wl,-rpath") // Search for shared object in the same path when exec'd.
72*bb4ee6a4SAndroid Build Coastguard Worker         .arg(&libcrosvm_plugin_dir)
73*bb4ee6a4SAndroid Build Coastguard Worker         .args(["-Wl,-rpath", "."]) // Also check current directory in case of sandboxing.
74*bb4ee6a4SAndroid Build Coastguard Worker         .args(["-xc", "-"]) // Read source code from piped stdin.
75*bb4ee6a4SAndroid Build Coastguard Worker         .arg("-lcrosvm_plugin")
76*bb4ee6a4SAndroid Build Coastguard Worker         .stdin(Stdio::piped())
77*bb4ee6a4SAndroid Build Coastguard Worker         .spawn()
78*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to spawn compiler");
79*bb4ee6a4SAndroid Build Coastguard Worker     let stdin = child.stdin.as_mut().expect("failed to open stdin");
80*bb4ee6a4SAndroid Build Coastguard Worker     stdin
81*bb4ee6a4SAndroid Build Coastguard Worker         .write_all(src.as_bytes())
82*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to write source to stdin");
83*bb4ee6a4SAndroid Build Coastguard Worker 
84*bb4ee6a4SAndroid Build Coastguard Worker     let status = child.wait().expect("failed to wait for compiler");
85*bb4ee6a4SAndroid Build Coastguard Worker     assert!(status.success(), "failed to build plugin");
86*bb4ee6a4SAndroid Build Coastguard Worker 
87*bb4ee6a4SAndroid Build Coastguard Worker     RemovePath(out_bin)
88*bb4ee6a4SAndroid Build Coastguard Worker }
89*bb4ee6a4SAndroid Build Coastguard Worker 
run_plugin(bin_path: &Path, with_sandbox: bool)90*bb4ee6a4SAndroid Build Coastguard Worker fn run_plugin(bin_path: &Path, with_sandbox: bool) {
91*bb4ee6a4SAndroid Build Coastguard Worker     let mut crosvm_path = get_crosvm_path();
92*bb4ee6a4SAndroid Build Coastguard Worker     crosvm_path.push("crosvm");
93*bb4ee6a4SAndroid Build Coastguard Worker     let mut cmd = Command::new(crosvm_path);
94*bb4ee6a4SAndroid Build Coastguard Worker     cmd.args([
95*bb4ee6a4SAndroid Build Coastguard Worker         "run",
96*bb4ee6a4SAndroid Build Coastguard Worker         "-c",
97*bb4ee6a4SAndroid Build Coastguard Worker         "1",
98*bb4ee6a4SAndroid Build Coastguard Worker         "--seccomp-policy-dir",
99*bb4ee6a4SAndroid Build Coastguard Worker         "tests",
100*bb4ee6a4SAndroid Build Coastguard Worker         "--plugin",
101*bb4ee6a4SAndroid Build Coastguard Worker     ])
102*bb4ee6a4SAndroid Build Coastguard Worker     .arg(
103*bb4ee6a4SAndroid Build Coastguard Worker         bin_path
104*bb4ee6a4SAndroid Build Coastguard Worker             .canonicalize()
105*bb4ee6a4SAndroid Build Coastguard Worker             .expect("failed to canonicalize plugin path"),
106*bb4ee6a4SAndroid Build Coastguard Worker     );
107*bb4ee6a4SAndroid Build Coastguard Worker 
108*bb4ee6a4SAndroid Build Coastguard Worker     if *TAP_AVAILABLE {
109*bb4ee6a4SAndroid Build Coastguard Worker         cmd.args([
110*bb4ee6a4SAndroid Build Coastguard Worker             "--host-ip",
111*bb4ee6a4SAndroid Build Coastguard Worker             "100.115.92.5",
112*bb4ee6a4SAndroid Build Coastguard Worker             "--netmask",
113*bb4ee6a4SAndroid Build Coastguard Worker             "255.255.255.252",
114*bb4ee6a4SAndroid Build Coastguard Worker             "--mac",
115*bb4ee6a4SAndroid Build Coastguard Worker             "de:21:e8:47:6b:6a",
116*bb4ee6a4SAndroid Build Coastguard Worker         ]);
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker     if !with_sandbox {
119*bb4ee6a4SAndroid Build Coastguard Worker         cmd.arg("--disable-sandbox");
120*bb4ee6a4SAndroid Build Coastguard Worker     }
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker     let mut child = cmd.spawn().expect("failed to spawn crosvm");
123*bb4ee6a4SAndroid Build Coastguard Worker     for _ in 0..12 {
124*bb4ee6a4SAndroid Build Coastguard Worker         match child.try_wait().expect("failed to wait for crosvm") {
125*bb4ee6a4SAndroid Build Coastguard Worker             Some(status) => {
126*bb4ee6a4SAndroid Build Coastguard Worker                 assert!(status.success());
127*bb4ee6a4SAndroid Build Coastguard Worker                 return;
128*bb4ee6a4SAndroid Build Coastguard Worker             }
129*bb4ee6a4SAndroid Build Coastguard Worker             None => sleep(Duration::from_millis(100)),
130*bb4ee6a4SAndroid Build Coastguard Worker         }
131*bb4ee6a4SAndroid Build Coastguard Worker     }
132*bb4ee6a4SAndroid Build Coastguard Worker     child.kill().expect("failed to kill crosvm");
133*bb4ee6a4SAndroid Build Coastguard Worker     panic!("crosvm process has timed out");
134*bb4ee6a4SAndroid Build Coastguard Worker }
135*bb4ee6a4SAndroid Build Coastguard Worker 
test_plugin(src: &str)136*bb4ee6a4SAndroid Build Coastguard Worker fn test_plugin(src: &str) {
137*bb4ee6a4SAndroid Build Coastguard Worker     let bin_path = build_plugin(src);
138*bb4ee6a4SAndroid Build Coastguard Worker     // Run with and without the sandbox enabled.
139*bb4ee6a4SAndroid Build Coastguard Worker     run_plugin(&bin_path.0, false);
140*bb4ee6a4SAndroid Build Coastguard Worker     run_plugin(&bin_path.0, true);
141*bb4ee6a4SAndroid Build Coastguard Worker }
142*bb4ee6a4SAndroid Build Coastguard Worker 
keep_fd_on_exec<F: AsRawDescriptor>(f: &F)143*bb4ee6a4SAndroid Build Coastguard Worker fn keep_fd_on_exec<F: AsRawDescriptor>(f: &F) {
144*bb4ee6a4SAndroid Build Coastguard Worker     // SAFETY: safe because function doesn't modify memory and we don't care about the return
145*bb4ee6a4SAndroid Build Coastguard Worker     // value.
146*bb4ee6a4SAndroid Build Coastguard Worker     unsafe {
147*bb4ee6a4SAndroid Build Coastguard Worker         ioctl(f, 0x5450 /* FIONCLEX */);
148*bb4ee6a4SAndroid Build Coastguard Worker     }
149*bb4ee6a4SAndroid Build Coastguard Worker }
150*bb4ee6a4SAndroid Build Coastguard Worker 
151*bb4ee6a4SAndroid Build Coastguard Worker /// Takes assembly source code and returns the resulting assembly code.
build_assembly(src: &str) -> Vec<u8>152*bb4ee6a4SAndroid Build Coastguard Worker fn build_assembly(src: &str) -> Vec<u8> {
153*bb4ee6a4SAndroid Build Coastguard Worker     // Creates a file with the assembly source code in it.
154*bb4ee6a4SAndroid Build Coastguard Worker     let mut in_file = tempfile().expect("failed to create tempfile");
155*bb4ee6a4SAndroid Build Coastguard Worker     keep_fd_on_exec(&in_file);
156*bb4ee6a4SAndroid Build Coastguard Worker     in_file.write_all(src.as_bytes()).unwrap();
157*bb4ee6a4SAndroid Build Coastguard Worker 
158*bb4ee6a4SAndroid Build Coastguard Worker     // Creates a file that will hold the nasm output.
159*bb4ee6a4SAndroid Build Coastguard Worker     let mut out_file = tempfile().expect("failed to create tempfile");
160*bb4ee6a4SAndroid Build Coastguard Worker     keep_fd_on_exec(&out_file);
161*bb4ee6a4SAndroid Build Coastguard Worker 
162*bb4ee6a4SAndroid Build Coastguard Worker     // Runs nasm with the input and output files set to the FDs of the above shared memory regions,
163*bb4ee6a4SAndroid Build Coastguard Worker     // which we have preserved accross exec.
164*bb4ee6a4SAndroid Build Coastguard Worker     let status = Command::new("nasm")
165*bb4ee6a4SAndroid Build Coastguard Worker         .arg(format!("/proc/self/fd/{}", in_file.as_raw_descriptor()))
166*bb4ee6a4SAndroid Build Coastguard Worker         .args(["-f", "bin", "-o"])
167*bb4ee6a4SAndroid Build Coastguard Worker         .arg(format!("/proc/self/fd/{}", out_file.as_raw_descriptor()))
168*bb4ee6a4SAndroid Build Coastguard Worker         .status()
169*bb4ee6a4SAndroid Build Coastguard Worker         .expect("failed to spawn assembler");
170*bb4ee6a4SAndroid Build Coastguard Worker     assert!(status.success());
171*bb4ee6a4SAndroid Build Coastguard Worker 
172*bb4ee6a4SAndroid Build Coastguard Worker     let mut out_bytes = Vec::new();
173*bb4ee6a4SAndroid Build Coastguard Worker     out_file.read_to_end(&mut out_bytes).unwrap();
174*bb4ee6a4SAndroid Build Coastguard Worker     out_bytes
175*bb4ee6a4SAndroid Build Coastguard Worker }
176*bb4ee6a4SAndroid Build Coastguard Worker 
177*bb4ee6a4SAndroid Build Coastguard Worker // Converts the input bytes to an output string in the format "0x01,0x02,0x03...".
format_as_hex(data: &[u8]) -> String178*bb4ee6a4SAndroid Build Coastguard Worker fn format_as_hex(data: &[u8]) -> String {
179*bb4ee6a4SAndroid Build Coastguard Worker     let mut out = String::new();
180*bb4ee6a4SAndroid Build Coastguard Worker     for (i, d) in data.iter().enumerate() {
181*bb4ee6a4SAndroid Build Coastguard Worker         #[allow(clippy::format_push_string)]
182*bb4ee6a4SAndroid Build Coastguard Worker         out.push_str(&format!("0x{:02x}", d));
183*bb4ee6a4SAndroid Build Coastguard Worker         if i < data.len() - 1 {
184*bb4ee6a4SAndroid Build Coastguard Worker             out.push(',')
185*bb4ee6a4SAndroid Build Coastguard Worker         }
186*bb4ee6a4SAndroid Build Coastguard Worker     }
187*bb4ee6a4SAndroid Build Coastguard Worker     out
188*bb4ee6a4SAndroid Build Coastguard Worker }
189*bb4ee6a4SAndroid Build Coastguard Worker 
190*bb4ee6a4SAndroid Build Coastguard Worker // A testing framework for creating simple plugins.
191*bb4ee6a4SAndroid Build Coastguard Worker struct MiniPlugin {
192*bb4ee6a4SAndroid Build Coastguard Worker     // The size in bytes of the guest memory based at 0x0000.
193*bb4ee6a4SAndroid Build Coastguard Worker     mem_size: u64,
194*bb4ee6a4SAndroid Build Coastguard Worker     // The address in guest memory to load the assembly code.
195*bb4ee6a4SAndroid Build Coastguard Worker     load_address: u32,
196*bb4ee6a4SAndroid Build Coastguard Worker     // The nasm syntax 16-bit assembly code that will assembled and loaded into guest memory.
197*bb4ee6a4SAndroid Build Coastguard Worker     assembly_src: &'static str,
198*bb4ee6a4SAndroid Build Coastguard Worker     // The C source code that will be included in the mini_plugin_template.c file. This code must
199*bb4ee6a4SAndroid Build Coastguard Worker     // define the forward declarations above the {src} line so that the completed plugin source
200*bb4ee6a4SAndroid Build Coastguard Worker     // will compile.
201*bb4ee6a4SAndroid Build Coastguard Worker     src: &'static str,
202*bb4ee6a4SAndroid Build Coastguard Worker }
203*bb4ee6a4SAndroid Build Coastguard Worker 
204*bb4ee6a4SAndroid Build Coastguard Worker impl Default for MiniPlugin {
default() -> Self205*bb4ee6a4SAndroid Build Coastguard Worker     fn default() -> Self {
206*bb4ee6a4SAndroid Build Coastguard Worker         MiniPlugin {
207*bb4ee6a4SAndroid Build Coastguard Worker             mem_size: 0x2000,
208*bb4ee6a4SAndroid Build Coastguard Worker             load_address: 0x1000,
209*bb4ee6a4SAndroid Build Coastguard Worker             assembly_src: "hlt",
210*bb4ee6a4SAndroid Build Coastguard Worker             src: "",
211*bb4ee6a4SAndroid Build Coastguard Worker         }
212*bb4ee6a4SAndroid Build Coastguard Worker     }
213*bb4ee6a4SAndroid Build Coastguard Worker }
214*bb4ee6a4SAndroid Build Coastguard Worker 
215*bb4ee6a4SAndroid Build Coastguard Worker // Builds and tests the given MiniPlugin definiton.
test_mini_plugin(plugin: &MiniPlugin)216*bb4ee6a4SAndroid Build Coastguard Worker fn test_mini_plugin(plugin: &MiniPlugin) {
217*bb4ee6a4SAndroid Build Coastguard Worker     // Adds a preamble to ensure the output opcodes are 16-bit real mode and the lables start at the
218*bb4ee6a4SAndroid Build Coastguard Worker     // load address.
219*bb4ee6a4SAndroid Build Coastguard Worker     let assembly_src = format!(
220*bb4ee6a4SAndroid Build Coastguard Worker         "org 0x{:x}\nbits 16\n{}",
221*bb4ee6a4SAndroid Build Coastguard Worker         plugin.load_address, plugin.assembly_src
222*bb4ee6a4SAndroid Build Coastguard Worker     );
223*bb4ee6a4SAndroid Build Coastguard Worker 
224*bb4ee6a4SAndroid Build Coastguard Worker     // Builds the assembly and convert it to a C literal array format.
225*bb4ee6a4SAndroid Build Coastguard Worker     let assembly = build_assembly(&assembly_src);
226*bb4ee6a4SAndroid Build Coastguard Worker     let assembly_hex = format_as_hex(&assembly);
227*bb4ee6a4SAndroid Build Coastguard Worker 
228*bb4ee6a4SAndroid Build Coastguard Worker     // Glues the pieces of this plugin together and tests the completed plugin.
229*bb4ee6a4SAndroid Build Coastguard Worker     let generated_src = format!(
230*bb4ee6a4SAndroid Build Coastguard Worker         include_str!("mini_plugin_template.c"),
231*bb4ee6a4SAndroid Build Coastguard Worker         mem_size = plugin.mem_size,
232*bb4ee6a4SAndroid Build Coastguard Worker         load_address = plugin.load_address,
233*bb4ee6a4SAndroid Build Coastguard Worker         assembly_code = assembly_hex,
234*bb4ee6a4SAndroid Build Coastguard Worker         src = plugin.src
235*bb4ee6a4SAndroid Build Coastguard Worker     );
236*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(&generated_src);
237*bb4ee6a4SAndroid Build Coastguard Worker }
238*bb4ee6a4SAndroid Build Coastguard Worker 
239*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_adder()240*bb4ee6a4SAndroid Build Coastguard Worker fn test_adder() {
241*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_adder.c"));
242*bb4ee6a4SAndroid Build Coastguard Worker }
243*bb4ee6a4SAndroid Build Coastguard Worker 
244*bb4ee6a4SAndroid Build Coastguard Worker #[ignore] // TODO(b/239094055): fix the SIGSTOP usage that stops the cargo test runner
245*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_hint()246*bb4ee6a4SAndroid Build Coastguard Worker fn test_hint() {
247*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_hint.c"));
248*bb4ee6a4SAndroid Build Coastguard Worker }
249*bb4ee6a4SAndroid Build Coastguard Worker 
250*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_async_write()251*bb4ee6a4SAndroid Build Coastguard Worker fn test_async_write() {
252*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_async_write.c"));
253*bb4ee6a4SAndroid Build Coastguard Worker }
254*bb4ee6a4SAndroid Build Coastguard Worker 
255*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_dirty_log()256*bb4ee6a4SAndroid Build Coastguard Worker fn test_dirty_log() {
257*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_dirty_log.c"));
258*bb4ee6a4SAndroid Build Coastguard Worker }
259*bb4ee6a4SAndroid Build Coastguard Worker 
260*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_ioevent()261*bb4ee6a4SAndroid Build Coastguard Worker fn test_ioevent() {
262*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_ioevent.c"));
263*bb4ee6a4SAndroid Build Coastguard Worker }
264*bb4ee6a4SAndroid Build Coastguard Worker 
265*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_irqfd()266*bb4ee6a4SAndroid Build Coastguard Worker fn test_irqfd() {
267*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_irqfd.c"));
268*bb4ee6a4SAndroid Build Coastguard Worker }
269*bb4ee6a4SAndroid Build Coastguard Worker 
270*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_extensions()271*bb4ee6a4SAndroid Build Coastguard Worker fn test_extensions() {
272*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_extensions.c"));
273*bb4ee6a4SAndroid Build Coastguard Worker }
274*bb4ee6a4SAndroid Build Coastguard Worker 
275*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_supported_cpuid()276*bb4ee6a4SAndroid Build Coastguard Worker fn test_supported_cpuid() {
277*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_supported_cpuid.c"));
278*bb4ee6a4SAndroid Build Coastguard Worker }
279*bb4ee6a4SAndroid Build Coastguard Worker 
280*bb4ee6a4SAndroid Build Coastguard Worker // b:223675792
281*bb4ee6a4SAndroid Build Coastguard Worker #[ignore]
282*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_enable_cap()283*bb4ee6a4SAndroid Build Coastguard Worker fn test_enable_cap() {
284*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_enable_cap.c"));
285*bb4ee6a4SAndroid Build Coastguard Worker }
286*bb4ee6a4SAndroid Build Coastguard Worker 
287*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_msr_index_list()288*bb4ee6a4SAndroid Build Coastguard Worker fn test_msr_index_list() {
289*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_msr_index_list.c"));
290*bb4ee6a4SAndroid Build Coastguard Worker }
291*bb4ee6a4SAndroid Build Coastguard Worker 
292*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_vm_state_manipulation()293*bb4ee6a4SAndroid Build Coastguard Worker fn test_vm_state_manipulation() {
294*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_vm_state.c"));
295*bb4ee6a4SAndroid Build Coastguard Worker }
296*bb4ee6a4SAndroid Build Coastguard Worker 
297*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_vcpu_pause()298*bb4ee6a4SAndroid Build Coastguard Worker fn test_vcpu_pause() {
299*bb4ee6a4SAndroid Build Coastguard Worker     test_plugin(include_str!("plugin_vcpu_pause.c"));
300*bb4ee6a4SAndroid Build Coastguard Worker }
301*bb4ee6a4SAndroid Build Coastguard Worker 
302*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_net_config()303*bb4ee6a4SAndroid Build Coastguard Worker fn test_net_config() {
304*bb4ee6a4SAndroid Build Coastguard Worker     if *TAP_AVAILABLE {
305*bb4ee6a4SAndroid Build Coastguard Worker         test_plugin(include_str!("plugin_net_config.c"));
306*bb4ee6a4SAndroid Build Coastguard Worker     }
307*bb4ee6a4SAndroid Build Coastguard Worker }
308*bb4ee6a4SAndroid Build Coastguard Worker 
309*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_debugregs()310*bb4ee6a4SAndroid Build Coastguard Worker fn test_debugregs() {
311*bb4ee6a4SAndroid Build Coastguard Worker     let mini_plugin = MiniPlugin {
312*bb4ee6a4SAndroid Build Coastguard Worker         assembly_src: "org 0x1000
313*bb4ee6a4SAndroid Build Coastguard Worker              bits 16
314*bb4ee6a4SAndroid Build Coastguard Worker              mov dr0, ebx
315*bb4ee6a4SAndroid Build Coastguard Worker              mov eax, dr1
316*bb4ee6a4SAndroid Build Coastguard Worker              mov byte [0x3000], 1",
317*bb4ee6a4SAndroid Build Coastguard Worker         src: r#"
318*bb4ee6a4SAndroid Build Coastguard Worker             #define DR1_VALUE 0x12
319*bb4ee6a4SAndroid Build Coastguard Worker             #define RBX_VALUE 0xabcdef00
320*bb4ee6a4SAndroid Build Coastguard Worker             #define KILL_ADDRESS 0x3000
321*bb4ee6a4SAndroid Build Coastguard Worker 
322*bb4ee6a4SAndroid Build Coastguard Worker             int g_kill_evt;
323*bb4ee6a4SAndroid Build Coastguard Worker             struct kvm_regs g_regs;
324*bb4ee6a4SAndroid Build Coastguard Worker             struct kvm_debugregs g_dregs;
325*bb4ee6a4SAndroid Build Coastguard Worker 
326*bb4ee6a4SAndroid Build Coastguard Worker             int setup_vm(struct crosvm *crosvm, void *mem) {
327*bb4ee6a4SAndroid Build Coastguard Worker                 g_kill_evt = crosvm_get_shutdown_eventfd(crosvm);
328*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_reserve_range(crosvm, CROSVM_ADDRESS_SPACE_MMIO, KILL_ADDRESS, 1);
329*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
330*bb4ee6a4SAndroid Build Coastguard Worker             }
331*bb4ee6a4SAndroid Build Coastguard Worker 
332*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_init(struct crosvm_vcpu *vcpu, struct kvm_regs *regs,
333*bb4ee6a4SAndroid Build Coastguard Worker                                  struct kvm_sregs *sregs)
334*bb4ee6a4SAndroid Build Coastguard Worker             {
335*bb4ee6a4SAndroid Build Coastguard Worker                 regs->rbx = RBX_VALUE;
336*bb4ee6a4SAndroid Build Coastguard Worker                 struct kvm_debugregs dregs;
337*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_vcpu_get_debugregs(vcpu, &dregs);
338*bb4ee6a4SAndroid Build Coastguard Worker                 dregs.db[1] = DR1_VALUE;
339*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_vcpu_set_debugregs(vcpu, &dregs);
340*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
341*bb4ee6a4SAndroid Build Coastguard Worker             }
342*bb4ee6a4SAndroid Build Coastguard Worker 
343*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_evt(struct crosvm_vcpu *vcpu, struct crosvm_vcpu_event evt) {
344*bb4ee6a4SAndroid Build Coastguard Worker                 if (evt.kind == CROSVM_VCPU_EVENT_KIND_IO_ACCESS &&
345*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address_space == CROSVM_ADDRESS_SPACE_MMIO &&
346*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address == KILL_ADDRESS &&
347*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.is_write &&
348*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.length == 1 &&
349*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.data[0] == 1)
350*bb4ee6a4SAndroid Build Coastguard Worker                 {
351*bb4ee6a4SAndroid Build Coastguard Worker                     uint64_t dummy = 1;
352*bb4ee6a4SAndroid Build Coastguard Worker                     crosvm_vcpu_get_debugregs(vcpu, &g_dregs);
353*bb4ee6a4SAndroid Build Coastguard Worker                     crosvm_vcpu_get_regs(vcpu, &g_regs);
354*bb4ee6a4SAndroid Build Coastguard Worker                     write(g_kill_evt, &dummy, sizeof(dummy));
355*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
356*bb4ee6a4SAndroid Build Coastguard Worker                 }
357*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
358*bb4ee6a4SAndroid Build Coastguard Worker             }
359*bb4ee6a4SAndroid Build Coastguard Worker 
360*bb4ee6a4SAndroid Build Coastguard Worker             int check_result(struct crosvm *vcpu, void *mem) {
361*bb4ee6a4SAndroid Build Coastguard Worker                 if (g_dregs.db[1] != DR1_VALUE) {
362*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "dr1 register has unexpected value: 0x%x\n", g_dregs.db[1]);
363*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
364*bb4ee6a4SAndroid Build Coastguard Worker                 }
365*bb4ee6a4SAndroid Build Coastguard Worker                 if (g_dregs.db[0] != RBX_VALUE) {
366*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "dr0 register has unexpected value: 0x%x\n", g_dregs.db[0]);
367*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
368*bb4ee6a4SAndroid Build Coastguard Worker                 }
369*bb4ee6a4SAndroid Build Coastguard Worker                 if (g_regs.rax != DR1_VALUE) {
370*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "eax register has unexpected value: 0x%x\n", g_regs.rax);
371*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
372*bb4ee6a4SAndroid Build Coastguard Worker                 }
373*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
374*bb4ee6a4SAndroid Build Coastguard Worker             }"#,
375*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
376*bb4ee6a4SAndroid Build Coastguard Worker     };
377*bb4ee6a4SAndroid Build Coastguard Worker     test_mini_plugin(&mini_plugin);
378*bb4ee6a4SAndroid Build Coastguard Worker }
379*bb4ee6a4SAndroid Build Coastguard Worker 
380*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_xcrs()381*bb4ee6a4SAndroid Build Coastguard Worker fn test_xcrs() {
382*bb4ee6a4SAndroid Build Coastguard Worker     let mini_plugin = MiniPlugin {
383*bb4ee6a4SAndroid Build Coastguard Worker         assembly_src: "org 0x1000
384*bb4ee6a4SAndroid Build Coastguard Worker              bits 16
385*bb4ee6a4SAndroid Build Coastguard Worker              mov byte [0x3000], 1",
386*bb4ee6a4SAndroid Build Coastguard Worker         src: r#"
387*bb4ee6a4SAndroid Build Coastguard Worker             #define XCR0_VALUE 0x1
388*bb4ee6a4SAndroid Build Coastguard Worker             #define KILL_ADDRESS 0x3000
389*bb4ee6a4SAndroid Build Coastguard Worker 
390*bb4ee6a4SAndroid Build Coastguard Worker             int g_kill_evt;
391*bb4ee6a4SAndroid Build Coastguard Worker             struct kvm_xcrs g_xcrs;
392*bb4ee6a4SAndroid Build Coastguard Worker 
393*bb4ee6a4SAndroid Build Coastguard Worker             int setup_vm(struct crosvm *crosvm, void *mem) {
394*bb4ee6a4SAndroid Build Coastguard Worker                 g_kill_evt = crosvm_get_shutdown_eventfd(crosvm);
395*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_reserve_range(crosvm, CROSVM_ADDRESS_SPACE_MMIO, KILL_ADDRESS, 1);
396*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
397*bb4ee6a4SAndroid Build Coastguard Worker             }
398*bb4ee6a4SAndroid Build Coastguard Worker 
399*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_init(struct crosvm_vcpu *vcpu, struct kvm_regs *regs,
400*bb4ee6a4SAndroid Build Coastguard Worker                                  struct kvm_sregs *sregs)
401*bb4ee6a4SAndroid Build Coastguard Worker             {
402*bb4ee6a4SAndroid Build Coastguard Worker                 struct kvm_xcrs xcrs = {};
403*bb4ee6a4SAndroid Build Coastguard Worker                 xcrs.nr_xcrs = 1;
404*bb4ee6a4SAndroid Build Coastguard Worker                 xcrs.xcrs[0].value = XCR0_VALUE;
405*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_vcpu_set_xcrs(vcpu, &xcrs);
406*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
407*bb4ee6a4SAndroid Build Coastguard Worker             }
408*bb4ee6a4SAndroid Build Coastguard Worker 
409*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_evt(struct crosvm_vcpu *vcpu, struct crosvm_vcpu_event evt) {
410*bb4ee6a4SAndroid Build Coastguard Worker                 if (evt.kind == CROSVM_VCPU_EVENT_KIND_IO_ACCESS &&
411*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address_space == CROSVM_ADDRESS_SPACE_MMIO &&
412*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address == KILL_ADDRESS &&
413*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.is_write &&
414*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.length == 1 &&
415*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.data[0] == 1)
416*bb4ee6a4SAndroid Build Coastguard Worker                 {
417*bb4ee6a4SAndroid Build Coastguard Worker                     uint64_t dummy = 1;
418*bb4ee6a4SAndroid Build Coastguard Worker                     crosvm_vcpu_get_xcrs(vcpu, &g_xcrs);
419*bb4ee6a4SAndroid Build Coastguard Worker                     write(g_kill_evt, &dummy, sizeof(dummy));
420*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
421*bb4ee6a4SAndroid Build Coastguard Worker                 }
422*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
423*bb4ee6a4SAndroid Build Coastguard Worker             }
424*bb4ee6a4SAndroid Build Coastguard Worker 
425*bb4ee6a4SAndroid Build Coastguard Worker             int check_result(struct crosvm *vcpu, void *mem) {
426*bb4ee6a4SAndroid Build Coastguard Worker                 if (g_xcrs.xcrs[0].value != XCR0_VALUE) {
427*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "xcr0 register has unexpected value: 0x%x\n",
428*bb4ee6a4SAndroid Build Coastguard Worker                             g_xcrs.xcrs[0].value);
429*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
430*bb4ee6a4SAndroid Build Coastguard Worker                 }
431*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
432*bb4ee6a4SAndroid Build Coastguard Worker             }"#,
433*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
434*bb4ee6a4SAndroid Build Coastguard Worker     };
435*bb4ee6a4SAndroid Build Coastguard Worker     test_mini_plugin(&mini_plugin);
436*bb4ee6a4SAndroid Build Coastguard Worker }
437*bb4ee6a4SAndroid Build Coastguard Worker 
438*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_msrs()439*bb4ee6a4SAndroid Build Coastguard Worker fn test_msrs() {
440*bb4ee6a4SAndroid Build Coastguard Worker     let mini_plugin = MiniPlugin {
441*bb4ee6a4SAndroid Build Coastguard Worker         assembly_src: "org 0x1000
442*bb4ee6a4SAndroid Build Coastguard Worker              bits 16
443*bb4ee6a4SAndroid Build Coastguard Worker              rdmsr
444*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x0], eax
445*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x4], edx
446*bb4ee6a4SAndroid Build Coastguard Worker              mov ecx, ebx
447*bb4ee6a4SAndroid Build Coastguard Worker              mov eax, [0x8]
448*bb4ee6a4SAndroid Build Coastguard Worker              mov edx, [0xc]
449*bb4ee6a4SAndroid Build Coastguard Worker              wrmsr
450*bb4ee6a4SAndroid Build Coastguard Worker              mov byte [es:0], 1",
451*bb4ee6a4SAndroid Build Coastguard Worker         src: r#"
452*bb4ee6a4SAndroid Build Coastguard Worker             #define MSR1_INDEX 0x00000174
453*bb4ee6a4SAndroid Build Coastguard Worker             #define MSR1_DATA 1
454*bb4ee6a4SAndroid Build Coastguard Worker             #define MSR2_INDEX 0x00000175
455*bb4ee6a4SAndroid Build Coastguard Worker             #define MSR2_DATA 2
456*bb4ee6a4SAndroid Build Coastguard Worker             #define KILL_ADDRESS 0x3000
457*bb4ee6a4SAndroid Build Coastguard Worker 
458*bb4ee6a4SAndroid Build Coastguard Worker             int g_kill_evt;
459*bb4ee6a4SAndroid Build Coastguard Worker             uint32_t g_msr2_count;
460*bb4ee6a4SAndroid Build Coastguard Worker             struct kvm_msr_entry g_msr2;
461*bb4ee6a4SAndroid Build Coastguard Worker 
462*bb4ee6a4SAndroid Build Coastguard Worker             int setup_vm(struct crosvm *crosvm, void *mem) {
463*bb4ee6a4SAndroid Build Coastguard Worker                 g_kill_evt = crosvm_get_shutdown_eventfd(crosvm);
464*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_reserve_range(crosvm, CROSVM_ADDRESS_SPACE_MMIO, KILL_ADDRESS, 1);
465*bb4ee6a4SAndroid Build Coastguard Worker                 ((uint64_t*)mem)[1] = MSR2_DATA;
466*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
467*bb4ee6a4SAndroid Build Coastguard Worker             }
468*bb4ee6a4SAndroid Build Coastguard Worker 
469*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_init(struct crosvm_vcpu *vcpu, struct kvm_regs *regs,
470*bb4ee6a4SAndroid Build Coastguard Worker                                  struct kvm_sregs *sregs)
471*bb4ee6a4SAndroid Build Coastguard Worker             {
472*bb4ee6a4SAndroid Build Coastguard Worker                 regs->rcx = MSR1_INDEX;
473*bb4ee6a4SAndroid Build Coastguard Worker                 regs->rbx = MSR2_INDEX;
474*bb4ee6a4SAndroid Build Coastguard Worker                 sregs->es.base = KILL_ADDRESS;
475*bb4ee6a4SAndroid Build Coastguard Worker 
476*bb4ee6a4SAndroid Build Coastguard Worker                 struct kvm_msr_entry msr1 = {0};
477*bb4ee6a4SAndroid Build Coastguard Worker                 msr1.index = MSR1_INDEX;
478*bb4ee6a4SAndroid Build Coastguard Worker                 msr1.data = MSR1_DATA;
479*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_vcpu_set_msrs(vcpu, 1, &msr1);
480*bb4ee6a4SAndroid Build Coastguard Worker 
481*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
482*bb4ee6a4SAndroid Build Coastguard Worker             }
483*bb4ee6a4SAndroid Build Coastguard Worker 
484*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_evt(struct crosvm_vcpu *vcpu, struct crosvm_vcpu_event evt) {
485*bb4ee6a4SAndroid Build Coastguard Worker                 if (evt.kind == CROSVM_VCPU_EVENT_KIND_IO_ACCESS &&
486*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address_space == CROSVM_ADDRESS_SPACE_MMIO &&
487*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address == KILL_ADDRESS &&
488*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.is_write &&
489*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.length == 1 &&
490*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.data[0] == 1)
491*bb4ee6a4SAndroid Build Coastguard Worker                 {
492*bb4ee6a4SAndroid Build Coastguard Worker                     uint64_t dummy = 1;
493*bb4ee6a4SAndroid Build Coastguard Worker                     g_msr2.index = MSR2_INDEX;
494*bb4ee6a4SAndroid Build Coastguard Worker                     crosvm_vcpu_get_msrs(vcpu, 1, &g_msr2, &g_msr2_count);
495*bb4ee6a4SAndroid Build Coastguard Worker                     write(g_kill_evt, &dummy, sizeof(dummy));
496*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
497*bb4ee6a4SAndroid Build Coastguard Worker                 }
498*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
499*bb4ee6a4SAndroid Build Coastguard Worker             }
500*bb4ee6a4SAndroid Build Coastguard Worker 
501*bb4ee6a4SAndroid Build Coastguard Worker             int check_result(struct crosvm *vcpu, void *mem) {
502*bb4ee6a4SAndroid Build Coastguard Worker                 uint64_t msr1_data = ((uint64_t*)mem)[0];
503*bb4ee6a4SAndroid Build Coastguard Worker                 if (msr1_data != MSR1_DATA) {
504*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "msr1 has unexpected value: 0x%x\n", msr1_data);
505*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
506*bb4ee6a4SAndroid Build Coastguard Worker                 }
507*bb4ee6a4SAndroid Build Coastguard Worker                 if (g_msr2_count != 1) {
508*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "incorrect number of returned MSRSs: %d\n", g_msr2_count);
509*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
510*bb4ee6a4SAndroid Build Coastguard Worker                 }
511*bb4ee6a4SAndroid Build Coastguard Worker                 if (g_msr2.data != MSR2_DATA) {
512*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "msr2 has unexpected value: 0x%x\n", g_msr2.data);
513*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
514*bb4ee6a4SAndroid Build Coastguard Worker                 }
515*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
516*bb4ee6a4SAndroid Build Coastguard Worker             }"#,
517*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
518*bb4ee6a4SAndroid Build Coastguard Worker     };
519*bb4ee6a4SAndroid Build Coastguard Worker     test_mini_plugin(&mini_plugin);
520*bb4ee6a4SAndroid Build Coastguard Worker }
521*bb4ee6a4SAndroid Build Coastguard Worker 
522*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_cpuid()523*bb4ee6a4SAndroid Build Coastguard Worker fn test_cpuid() {
524*bb4ee6a4SAndroid Build Coastguard Worker     let mini_plugin = MiniPlugin {
525*bb4ee6a4SAndroid Build Coastguard Worker         assembly_src: "org 0x1000
526*bb4ee6a4SAndroid Build Coastguard Worker              bits 16
527*bb4ee6a4SAndroid Build Coastguard Worker              push eax
528*bb4ee6a4SAndroid Build Coastguard Worker              push ecx
529*bb4ee6a4SAndroid Build Coastguard Worker              cpuid
530*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x0], eax
531*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x4], ebx
532*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x8], ecx
533*bb4ee6a4SAndroid Build Coastguard Worker              mov [0xc], edx
534*bb4ee6a4SAndroid Build Coastguard Worker              pop ecx
535*bb4ee6a4SAndroid Build Coastguard Worker              pop eax
536*bb4ee6a4SAndroid Build Coastguard Worker              add ecx, 1
537*bb4ee6a4SAndroid Build Coastguard Worker              cpuid
538*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x10], eax
539*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x14], ebx
540*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x18], ecx
541*bb4ee6a4SAndroid Build Coastguard Worker              mov [0x1c], edx
542*bb4ee6a4SAndroid Build Coastguard Worker              mov byte [es:0], 1",
543*bb4ee6a4SAndroid Build Coastguard Worker         src: r#"
544*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY1_INDEX 0
545*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY1_EAX 0x40414243
546*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY1_EBX 0x50515253
547*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY1_ECX 0x60616263
548*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY1_EDX 0x71727374
549*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY2_INDEX 1
550*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY2_EAX 0xAABBCCDD
551*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY2_EBX 0xEEFF0011
552*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY2_ECX 0x22334455
553*bb4ee6a4SAndroid Build Coastguard Worker             #define ENTRY2_EDX 0x66778899
554*bb4ee6a4SAndroid Build Coastguard Worker             #define KILL_ADDRESS 0x3000
555*bb4ee6a4SAndroid Build Coastguard Worker 
556*bb4ee6a4SAndroid Build Coastguard Worker             int g_kill_evt;
557*bb4ee6a4SAndroid Build Coastguard Worker             struct kvm_msr_entry g_msr2;
558*bb4ee6a4SAndroid Build Coastguard Worker 
559*bb4ee6a4SAndroid Build Coastguard Worker             int setup_vm(struct crosvm *crosvm, void *mem) {
560*bb4ee6a4SAndroid Build Coastguard Worker                 g_kill_evt = crosvm_get_shutdown_eventfd(crosvm);
561*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_reserve_range(crosvm, CROSVM_ADDRESS_SPACE_MMIO, KILL_ADDRESS, 1);
562*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
563*bb4ee6a4SAndroid Build Coastguard Worker             }
564*bb4ee6a4SAndroid Build Coastguard Worker 
565*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_init(struct crosvm_vcpu *vcpu, struct kvm_regs *regs,
566*bb4ee6a4SAndroid Build Coastguard Worker                                  struct kvm_sregs *sregs)
567*bb4ee6a4SAndroid Build Coastguard Worker             {
568*bb4ee6a4SAndroid Build Coastguard Worker                 regs->rax = ENTRY1_INDEX;
569*bb4ee6a4SAndroid Build Coastguard Worker                 regs->rcx = 0;
570*bb4ee6a4SAndroid Build Coastguard Worker                 regs->rsp = 0x1000;
571*bb4ee6a4SAndroid Build Coastguard Worker                 sregs->es.base = KILL_ADDRESS;
572*bb4ee6a4SAndroid Build Coastguard Worker 
573*bb4ee6a4SAndroid Build Coastguard Worker                 struct kvm_cpuid_entry2 entries[2];
574*bb4ee6a4SAndroid Build Coastguard Worker                 entries[0].function = 0;
575*bb4ee6a4SAndroid Build Coastguard Worker                 entries[0].index = ENTRY1_INDEX;
576*bb4ee6a4SAndroid Build Coastguard Worker                 entries[0].flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
577*bb4ee6a4SAndroid Build Coastguard Worker                 entries[0].eax = ENTRY1_EAX;
578*bb4ee6a4SAndroid Build Coastguard Worker                 entries[0].ebx = ENTRY1_EBX;
579*bb4ee6a4SAndroid Build Coastguard Worker                 entries[0].ecx = ENTRY1_ECX;
580*bb4ee6a4SAndroid Build Coastguard Worker                 entries[0].edx = ENTRY1_EDX;
581*bb4ee6a4SAndroid Build Coastguard Worker                 entries[1].function = 0;
582*bb4ee6a4SAndroid Build Coastguard Worker                 entries[1].index = ENTRY2_INDEX;
583*bb4ee6a4SAndroid Build Coastguard Worker                 entries[1].flags = KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
584*bb4ee6a4SAndroid Build Coastguard Worker                 entries[1].eax = ENTRY2_EAX;
585*bb4ee6a4SAndroid Build Coastguard Worker                 entries[1].ebx = ENTRY2_EBX;
586*bb4ee6a4SAndroid Build Coastguard Worker                 entries[1].ecx = ENTRY2_ECX;
587*bb4ee6a4SAndroid Build Coastguard Worker                 entries[1].edx = ENTRY2_EDX;
588*bb4ee6a4SAndroid Build Coastguard Worker                 return crosvm_vcpu_set_cpuid(vcpu, 2, entries);
589*bb4ee6a4SAndroid Build Coastguard Worker             }
590*bb4ee6a4SAndroid Build Coastguard Worker 
591*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_evt(struct crosvm_vcpu *vcpu, struct crosvm_vcpu_event evt) {
592*bb4ee6a4SAndroid Build Coastguard Worker                 if (evt.kind == CROSVM_VCPU_EVENT_KIND_IO_ACCESS &&
593*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address_space == CROSVM_ADDRESS_SPACE_MMIO &&
594*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address == KILL_ADDRESS &&
595*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.is_write &&
596*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.length == 1 &&
597*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.data[0] == 1)
598*bb4ee6a4SAndroid Build Coastguard Worker                 {
599*bb4ee6a4SAndroid Build Coastguard Worker                     uint64_t dummy = 1;
600*bb4ee6a4SAndroid Build Coastguard Worker                     write(g_kill_evt, &dummy, sizeof(dummy));
601*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
602*bb4ee6a4SAndroid Build Coastguard Worker                 }
603*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
604*bb4ee6a4SAndroid Build Coastguard Worker             }
605*bb4ee6a4SAndroid Build Coastguard Worker 
606*bb4ee6a4SAndroid Build Coastguard Worker             int check_result(struct crosvm *vcpu, void *memory) {
607*bb4ee6a4SAndroid Build Coastguard Worker                 uint32_t *mem = (uint32_t*)memory;
608*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[0] != ENTRY1_EAX) {
609*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 1 eax has unexpected value: 0x%x\n", mem[0]);
610*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
611*bb4ee6a4SAndroid Build Coastguard Worker                 }
612*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[1] != ENTRY1_EBX) {
613*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 1 ebx has unexpected value: 0x%x\n", mem[1]);
614*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
615*bb4ee6a4SAndroid Build Coastguard Worker                 }
616*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[2] != ENTRY1_ECX) {
617*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 1 ecx has unexpected value: 0x%x\n", mem[2]);
618*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
619*bb4ee6a4SAndroid Build Coastguard Worker                 }
620*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[3] != ENTRY1_EDX) {
621*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 1 edx has unexpected value: 0x%x\n", mem[3]);
622*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
623*bb4ee6a4SAndroid Build Coastguard Worker                 }
624*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[4] != ENTRY2_EAX) {
625*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 2 eax has unexpected value: 0x%x\n", mem[4]);
626*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
627*bb4ee6a4SAndroid Build Coastguard Worker                 }
628*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[5] != ENTRY2_EBX) {
629*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 2 ebx has unexpected value: 0x%x\n", mem[5]);
630*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
631*bb4ee6a4SAndroid Build Coastguard Worker                 }
632*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[6] != ENTRY2_ECX) {
633*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 2 ecx has unexpected value: 0x%x\n", mem[6]);
634*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
635*bb4ee6a4SAndroid Build Coastguard Worker                 }
636*bb4ee6a4SAndroid Build Coastguard Worker                 if (mem[7] != ENTRY2_EDX) {
637*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "entry 2 edx has unexpected value: 0x%x\n", mem[7]);
638*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
639*bb4ee6a4SAndroid Build Coastguard Worker                 }
640*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
641*bb4ee6a4SAndroid Build Coastguard Worker             }"#,
642*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
643*bb4ee6a4SAndroid Build Coastguard Worker     };
644*bb4ee6a4SAndroid Build Coastguard Worker     test_mini_plugin(&mini_plugin);
645*bb4ee6a4SAndroid Build Coastguard Worker }
646*bb4ee6a4SAndroid Build Coastguard Worker 
647*bb4ee6a4SAndroid Build Coastguard Worker #[test]
test_vcpu_state_manipulation()648*bb4ee6a4SAndroid Build Coastguard Worker fn test_vcpu_state_manipulation() {
649*bb4ee6a4SAndroid Build Coastguard Worker     let mini_plugin = MiniPlugin {
650*bb4ee6a4SAndroid Build Coastguard Worker         assembly_src: "org 0x1000
651*bb4ee6a4SAndroid Build Coastguard Worker              bits 16
652*bb4ee6a4SAndroid Build Coastguard Worker              mov byte [0x3000], 1",
653*bb4ee6a4SAndroid Build Coastguard Worker         src: r#"
654*bb4ee6a4SAndroid Build Coastguard Worker             #define KILL_ADDRESS 0x3000
655*bb4ee6a4SAndroid Build Coastguard Worker 
656*bb4ee6a4SAndroid Build Coastguard Worker             int g_kill_evt;
657*bb4ee6a4SAndroid Build Coastguard Worker             bool success = false;
658*bb4ee6a4SAndroid Build Coastguard Worker 
659*bb4ee6a4SAndroid Build Coastguard Worker             int setup_vm(struct crosvm *crosvm, void *mem) {
660*bb4ee6a4SAndroid Build Coastguard Worker                 g_kill_evt = crosvm_get_shutdown_eventfd(crosvm);
661*bb4ee6a4SAndroid Build Coastguard Worker                 crosvm_reserve_range(crosvm, CROSVM_ADDRESS_SPACE_MMIO, KILL_ADDRESS, 1);
662*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
663*bb4ee6a4SAndroid Build Coastguard Worker             }
664*bb4ee6a4SAndroid Build Coastguard Worker 
665*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_init(struct crosvm_vcpu *vcpu, struct kvm_regs *regs,
666*bb4ee6a4SAndroid Build Coastguard Worker                                  struct kvm_sregs *sregs)
667*bb4ee6a4SAndroid Build Coastguard Worker             {
668*bb4ee6a4SAndroid Build Coastguard Worker                 int ret;
669*bb4ee6a4SAndroid Build Coastguard Worker 
670*bb4ee6a4SAndroid Build Coastguard Worker                 struct kvm_lapic_state lapic;
671*bb4ee6a4SAndroid Build Coastguard Worker                 ret = crosvm_vcpu_get_lapic_state(vcpu, &lapic);
672*bb4ee6a4SAndroid Build Coastguard Worker                 if (ret < 0) {
673*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "failed to get initial LAPIC state: %d\n", ret);
674*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
675*bb4ee6a4SAndroid Build Coastguard Worker                 }
676*bb4ee6a4SAndroid Build Coastguard Worker 
677*bb4ee6a4SAndroid Build Coastguard Worker                 ret = crosvm_vcpu_set_lapic_state(vcpu, &lapic);
678*bb4ee6a4SAndroid Build Coastguard Worker                 if (ret < 0) {
679*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "failed to update LAPIC state: %d\n", ret);
680*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
681*bb4ee6a4SAndroid Build Coastguard Worker                 }
682*bb4ee6a4SAndroid Build Coastguard Worker 
683*bb4ee6a4SAndroid Build Coastguard Worker                 ret = crosvm_vcpu_get_lapic_state(vcpu, &lapic);
684*bb4ee6a4SAndroid Build Coastguard Worker                 if (ret < 0) {
685*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "failed to get updated LAPIC state: %d\n", ret);
686*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
687*bb4ee6a4SAndroid Build Coastguard Worker                 }
688*bb4ee6a4SAndroid Build Coastguard Worker 
689*bb4ee6a4SAndroid Build Coastguard Worker                 struct kvm_mp_state mp_state;
690*bb4ee6a4SAndroid Build Coastguard Worker                 ret = crosvm_vcpu_get_mp_state(vcpu, &mp_state);
691*bb4ee6a4SAndroid Build Coastguard Worker                 if (ret < 0) {
692*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "failed to get initial MP state: %d\n", ret);
693*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
694*bb4ee6a4SAndroid Build Coastguard Worker                 }
695*bb4ee6a4SAndroid Build Coastguard Worker 
696*bb4ee6a4SAndroid Build Coastguard Worker                 ret = crosvm_vcpu_set_mp_state(vcpu, &mp_state);
697*bb4ee6a4SAndroid Build Coastguard Worker                 if (ret < 0) {
698*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "failed to update MP state: %d\n", ret);
699*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
700*bb4ee6a4SAndroid Build Coastguard Worker                 }
701*bb4ee6a4SAndroid Build Coastguard Worker 
702*bb4ee6a4SAndroid Build Coastguard Worker                 struct kvm_vcpu_events events;
703*bb4ee6a4SAndroid Build Coastguard Worker                 ret = crosvm_vcpu_get_vcpu_events(vcpu, &events);
704*bb4ee6a4SAndroid Build Coastguard Worker                 if (ret < 0) {
705*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "failed to get VCPU events: %d\n", ret);
706*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
707*bb4ee6a4SAndroid Build Coastguard Worker                 }
708*bb4ee6a4SAndroid Build Coastguard Worker 
709*bb4ee6a4SAndroid Build Coastguard Worker                 ret = crosvm_vcpu_set_vcpu_events(vcpu, &events);
710*bb4ee6a4SAndroid Build Coastguard Worker                 if (ret < 0) {
711*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "failed to set VCPU events: %d\n", ret);
712*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
713*bb4ee6a4SAndroid Build Coastguard Worker                 }
714*bb4ee6a4SAndroid Build Coastguard Worker 
715*bb4ee6a4SAndroid Build Coastguard Worker                 success = true;
716*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
717*bb4ee6a4SAndroid Build Coastguard Worker             }
718*bb4ee6a4SAndroid Build Coastguard Worker 
719*bb4ee6a4SAndroid Build Coastguard Worker             int handle_vpcu_evt(struct crosvm_vcpu *vcpu, struct crosvm_vcpu_event evt) {
720*bb4ee6a4SAndroid Build Coastguard Worker                 if (evt.kind == CROSVM_VCPU_EVENT_KIND_IO_ACCESS &&
721*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address_space == CROSVM_ADDRESS_SPACE_MMIO &&
722*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.address == KILL_ADDRESS &&
723*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.is_write &&
724*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.length == 1 &&
725*bb4ee6a4SAndroid Build Coastguard Worker                         evt.io_access.data[0] == 1)
726*bb4ee6a4SAndroid Build Coastguard Worker                 {
727*bb4ee6a4SAndroid Build Coastguard Worker                     uint64_t dummy = 1;
728*bb4ee6a4SAndroid Build Coastguard Worker                     write(g_kill_evt, &dummy, sizeof(dummy));
729*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
730*bb4ee6a4SAndroid Build Coastguard Worker                 }
731*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
732*bb4ee6a4SAndroid Build Coastguard Worker             }
733*bb4ee6a4SAndroid Build Coastguard Worker 
734*bb4ee6a4SAndroid Build Coastguard Worker             int check_result(struct crosvm *vcpu, void *mem) {
735*bb4ee6a4SAndroid Build Coastguard Worker                 if (!success) {
736*bb4ee6a4SAndroid Build Coastguard Worker                     fprintf(stderr, "test failed\n");
737*bb4ee6a4SAndroid Build Coastguard Worker                     return 1;
738*bb4ee6a4SAndroid Build Coastguard Worker                 }
739*bb4ee6a4SAndroid Build Coastguard Worker                 return 0;
740*bb4ee6a4SAndroid Build Coastguard Worker             }"#,
741*bb4ee6a4SAndroid Build Coastguard Worker         ..Default::default()
742*bb4ee6a4SAndroid Build Coastguard Worker     };
743*bb4ee6a4SAndroid Build Coastguard Worker     test_mini_plugin(&mini_plugin);
744*bb4ee6a4SAndroid Build Coastguard Worker }
745