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