Add option to dump device tree blob in VM config
As part of adding tests for backwards compatibility check, dumping the
device tree will be essential in validating the state of the VM.
Bug: 360388014
Test: m
Change-Id: I1f0835590d1e668c1737abe58e1cb7163aa6759f
diff --git a/android/virtmgr/src/aidl.rs b/android/virtmgr/src/aidl.rs
index 87fb611..4b203d6 100644
--- a/android/virtmgr/src/aidl.rs
+++ b/android/virtmgr/src/aidl.rs
@@ -221,6 +221,7 @@
console_out_fd: Option<&ParcelFileDescriptor>,
console_in_fd: Option<&ParcelFileDescriptor>,
log_fd: Option<&ParcelFileDescriptor>,
+ dump_dt_fd: Option<&ParcelFileDescriptor>,
) -> binder::Result<Strong<dyn IVirtualMachine>> {
let mut is_protected = false;
let ret = self.create_vm_internal(
@@ -229,6 +230,7 @@
console_in_fd,
log_fd,
&mut is_protected,
+ dump_dt_fd,
);
write_vm_creation_stats(config, is_protected, &ret);
ret
@@ -485,6 +487,7 @@
console_in_fd: Option<&ParcelFileDescriptor>,
log_fd: Option<&ParcelFileDescriptor>,
is_protected: &mut bool,
+ dump_dt_fd: Option<&ParcelFileDescriptor>,
) -> binder::Result<Strong<dyn IVirtualMachine>> {
let requester_uid = get_calling_uid();
let requester_debug_pid = get_calling_pid();
@@ -527,6 +530,7 @@
clone_or_prepare_logger_fd(console_out_fd, format!("Console({})", cid))?;
let console_in_fd = console_in_fd.map(clone_file).transpose()?;
let log_fd = clone_or_prepare_logger_fd(log_fd, format!("Log({})", cid))?;
+ let dump_dt_fd = dump_dt_fd.map(clone_file).transpose()?;
// Counter to generate unique IDs for temporary image files.
let mut next_temporary_image_id = 0;
@@ -744,6 +748,7 @@
audio_config,
no_balloon: config.noBalloon,
usb_config,
+ dump_dt_fd,
};
let instance = Arc::new(
VmInstance::new(
diff --git a/android/virtmgr/src/crosvm.rs b/android/virtmgr/src/crosvm.rs
index b2be736..25271f8 100644
--- a/android/virtmgr/src/crosvm.rs
+++ b/android/virtmgr/src/crosvm.rs
@@ -135,6 +135,7 @@
pub audio_config: Option<AudioConfig>,
pub no_balloon: bool,
pub usb_config: UsbConfig,
+ pub dump_dt_fd: Option<File>,
}
#[derive(Debug)]
@@ -985,6 +986,11 @@
// Keep track of what file descriptors should be mapped to the crosvm process.
let mut preserved_fds = config.indirect_files.into_iter().map(|f| f.into()).collect();
+ if let Some(dump_dt_fd) = config.dump_dt_fd {
+ let dump_dt_fd = add_preserved_fd(&mut preserved_fds, dump_dt_fd);
+ command.arg("--dump-device-tree-blob").arg(dump_dt_fd);
+ }
+
// Setup the serial devices.
// 1. uart device: used as the output device by bootloaders and as early console by linux
// 2. uart device: used to report the reason for the VM failing.
diff --git a/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl b/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
index 234d8d0..0c3f6b7 100644
--- a/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
+++ b/android/virtualizationservice/aidl/android/system/virtualizationservice/IVirtualizationService.aidl
@@ -35,11 +35,14 @@
* `consoleInFd` is provided then console input to the VM will be read from it. If `osLogFd` is
* provided then the OS-level logs will be sent to it. `osLogFd` is supported only when the OS
* running in the VM has the logging system. In case of Microdroid, the logging system is logd.
+ * `dumpDtFd` is the file where to dump the VM's device tree. It is only used in
+ * debugging/testing.
*/
IVirtualMachine createVm(in VirtualMachineConfig config,
in @nullable ParcelFileDescriptor consoleOutFd,
in @nullable ParcelFileDescriptor consoleInFd,
- in @nullable ParcelFileDescriptor osLogFd);
+ in @nullable ParcelFileDescriptor osLogFd,
+ in @nullable ParcelFileDescriptor dumpDtFd);
/**
* Allocate an instance_id to the (newly created) VM.
diff --git a/android/vm/src/main.rs b/android/vm/src/main.rs
index 609bbdf..81ca8fa 100644
--- a/android/vm/src/main.rs
+++ b/android/vm/src/main.rs
@@ -114,6 +114,10 @@
#[cfg(debuggable_vms_improvements)]
#[arg(long)]
enable_earlycon: bool,
+
+ /// Path to file to dump VM device tree.
+ #[arg(long)]
+ dump_device_tree: Option<PathBuf>,
}
impl DebugConfig {
diff --git a/android/vm/src/run.rs b/android/vm/src/run.rs
index 823546f..0e1f4cc 100644
--- a/android/vm/src/run.rs
+++ b/android/vm/src/run.rs
@@ -203,6 +203,7 @@
config.debug.console.as_ref().map(|p| p.as_ref()),
config.debug.console_in.as_ref().map(|p| p.as_ref()),
config.debug.log.as_ref().map(|p| p.as_ref()),
+ config.debug.dump_device_tree.as_ref().map(|p| p.as_ref()),
)
}
@@ -284,6 +285,7 @@
config.debug.console.as_ref().map(|p| p.as_ref()),
config.debug.console_in.as_ref().map(|p| p.as_ref()),
config.debug.log.as_ref().map(|p| p.as_ref()),
+ config.debug.dump_device_tree.as_ref().map(|p| p.as_ref()),
)
}
@@ -306,6 +308,7 @@
console_out_path: Option<&Path>,
console_in_path: Option<&Path>,
log_path: Option<&Path>,
+ dump_device_tree: Option<&Path>,
) -> Result<(), Error> {
let console_out = if let Some(console_out_path) = console_out_path {
Some(File::create(console_out_path).with_context(|| {
@@ -330,9 +333,17 @@
} else {
Some(duplicate_fd(io::stdout())?)
};
+ let dump_dt = if let Some(dump_device_tree) = dump_device_tree {
+ Some(File::create(dump_device_tree).with_context(|| {
+ format!("Failed to open file to dump device tree: {:?}", dump_device_tree)
+ })?)
+ } else {
+ None
+ };
let callback = Box::new(Callback {});
- let vm = VmInstance::create(service, config, console_out, console_in, log, Some(callback))
- .context("Failed to create VM")?;
+ let vm =
+ VmInstance::create(service, config, console_out, console_in, log, dump_dt, Some(callback))
+ .context("Failed to create VM")?;
vm.start().context("Failed to start VM")?;
let debug_level = get_debug_level(config).unwrap_or(DebugLevel::NONE);
diff --git a/android/vm_demo_native/main.cpp b/android/vm_demo_native/main.cpp
index bc42036..d7ff02e 100644
--- a/android/vm_demo_native/main.cpp
+++ b/android/vm_demo_native/main.cpp
@@ -226,8 +226,10 @@
ScopedFileDescriptor console_out_fd(fcntl(fileno(stdout), F_DUPFD_CLOEXEC));
ScopedFileDescriptor console_in_fd(fcntl(fileno(stdin), F_DUPFD_CLOEXEC));
ScopedFileDescriptor log_fd(fcntl(fileno(stdout), F_DUPFD_CLOEXEC));
+ ScopedFileDescriptor dump_dt_fd(-1);
- ScopedAStatus ret = service.createVm(config, console_out_fd, console_in_fd, log_fd, &vm);
+ ScopedAStatus ret =
+ service.createVm(config, console_out_fd, console_in_fd, log_fd, dump_dt_fd, &vm);
if (!ret.isOk()) {
return Error() << "Failed to create VM";
}