Add example using VirtIO console device.
Bug: 237250409
Test: atest vmbase_example.integration_test
Change-Id: I564c759ac3b43ea2e85110f053c2bcca002a559e
diff --git a/vmbase/example/src/pci.rs b/vmbase/example/src/pci.rs
index c0a2d2b..117cbc8 100644
--- a/vmbase/example/src/pci.rs
+++ b/vmbase/example/src/pci.rs
@@ -20,7 +20,7 @@
use fdtpci::PciInfo;
use log::{debug, info};
use virtio_drivers::{
- device::blk::VirtIOBlk,
+ device::{blk::VirtIOBlk, console::VirtIOConsole},
transport::{
pci::{bus::PciRoot, virtio_device_type, PciTransport},
DeviceType, Transport,
@@ -53,29 +53,41 @@
}
}
- assert_eq!(checked_virtio_device_count, 1);
+ assert_eq!(checked_virtio_device_count, 4);
}
/// Checks the given VirtIO device, if we know how to.
///
/// Returns true if the device was checked, or false if it was ignored.
fn check_virtio_device(transport: impl Transport, device_type: DeviceType) -> bool {
- if device_type == DeviceType::Block {
- let mut blk = VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
- info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
- assert_eq!(blk.capacity(), EXPECTED_SECTOR_COUNT as u64);
- let mut data = [0; SECTOR_SIZE_BYTES * EXPECTED_SECTOR_COUNT];
- for i in 0..EXPECTED_SECTOR_COUNT {
- blk.read_block(i, &mut data[i * SECTOR_SIZE_BYTES..(i + 1) * SECTOR_SIZE_BYTES])
- .expect("Failed to read block device.");
+ match device_type {
+ DeviceType::Block => {
+ let mut blk =
+ VirtIOBlk::<HalImpl, _>::new(transport).expect("failed to create blk driver");
+ info!("Found {} KiB block device.", blk.capacity() * SECTOR_SIZE_BYTES as u64 / 1024);
+ assert_eq!(blk.capacity(), EXPECTED_SECTOR_COUNT as u64);
+ let mut data = [0; SECTOR_SIZE_BYTES * EXPECTED_SECTOR_COUNT];
+ for i in 0..EXPECTED_SECTOR_COUNT {
+ blk.read_block(i, &mut data[i * SECTOR_SIZE_BYTES..(i + 1) * SECTOR_SIZE_BYTES])
+ .expect("Failed to read block device.");
+ }
+ for (i, chunk) in data.chunks(size_of::<u32>()).enumerate() {
+ assert_eq!(chunk, &(i as u32).to_le_bytes());
+ }
+ info!("Read expected data from block device.");
+ true
}
- for (i, chunk) in data.chunks(size_of::<u32>()).enumerate() {
- assert_eq!(chunk, &(i as u32).to_le_bytes());
+ DeviceType::Console => {
+ let mut console = VirtIOConsole::<HalImpl, _>::new(transport)
+ .expect("Failed to create VirtIO console driver");
+ info!("Found console device: {:?}", console.info());
+ for &c in b"Hello VirtIO console\n" {
+ console.send(c).expect("Failed to send character to VirtIO console device");
+ }
+ info!("Wrote to VirtIO console.");
+ true
}
- info!("Read expected data from block device.");
- true
- } else {
- false
+ _ => false,
}
}
diff --git a/vmbase/example/tests/test.rs b/vmbase/example/tests/test.rs
index 930e137..8f0eaa5 100644
--- a/vmbase/example/tests/test.rs
+++ b/vmbase/example/tests/test.rs
@@ -25,7 +25,7 @@
use log::info;
use std::{
fs::File,
- io::{self, BufRead, BufReader, Write},
+ io::{self, BufRead, BufReader, Read, Write},
os::unix::io::FromRawFd,
panic, thread,
};
@@ -90,8 +90,8 @@
gdbPort: 0, // no gdb
});
let console = android_log_fd()?;
- let log = android_log_fd()?;
- let vm = VmInstance::create(service.as_ref(), &config, Some(console), Some(log), None)
+ let (mut log_reader, log_writer) = pipe()?;
+ let vm = VmInstance::create(service.as_ref(), &config, Some(console), Some(log_writer), None)
.context("Failed to create VM")?;
vm.start().context("Failed to start VM")?;
info!("Started example VM.");
@@ -100,15 +100,17 @@
let death_reason = vm.wait_for_death();
assert_eq!(death_reason, DeathReason::Shutdown);
+ // Check that the expected string was written to the log VirtIO console device.
+ let expected = "Hello VirtIO console\n";
+ let mut log_output = String::new();
+ assert_eq!(log_reader.read_to_string(&mut log_output)?, expected.len());
+ assert_eq!(log_output, expected);
+
Ok(())
}
fn android_log_fd() -> io::Result<File> {
- let (reader_fd, writer_fd) = nix::unistd::pipe()?;
-
- // SAFETY: These are new FDs with no previous owner.
- let reader = unsafe { File::from_raw_fd(reader_fd) };
- let writer = unsafe { File::from_raw_fd(writer_fd) };
+ let (reader, writer) = pipe()?;
thread::spawn(|| {
for line in BufReader::new(reader).lines() {
@@ -117,3 +119,13 @@
});
Ok(writer)
}
+
+fn pipe() -> io::Result<(File, File)> {
+ let (reader_fd, writer_fd) = nix::unistd::pipe()?;
+
+ // SAFETY: These are new FDs with no previous owner.
+ let reader = unsafe { File::from_raw_fd(reader_fd) };
+ let writer = unsafe { File::from_raw_fd(writer_fd) };
+
+ Ok((reader, writer))
+}