Use regular file for VM DTBO
Bug: 287379025
Test: adb shell /apex/com.android.virt/bin/vm run-microdroid \
--protected --mem 512 --devices \
/sys/bus/platform/devices/16d00000.eh
Change-Id: Iad237c86ff2d1eca89c03d1b399f52877f24fa9a
diff --git a/virtualizationmanager/src/aidl.rs b/virtualizationmanager/src/aidl.rs
index 15e5407..91bd60b 100644
--- a/virtualizationmanager/src/aidl.rs
+++ b/virtualizationmanager/src/aidl.rs
@@ -474,7 +474,27 @@
));
}
}
- Some(clone_file(&GLOBAL_SERVICE.bindDevicesToVfioDriver(&config.devices)?)?)
+ let dtbo_path = temporary_directory.join("dtbo");
+ // open a writable file descriptor for vfio_handler
+ let dtbo = File::create(&dtbo_path).map_err(|e| {
+ error!("Failed to create VM DTBO file {dtbo_path:?}: {e:?}");
+ Status::new_service_specific_error_str(
+ -1,
+ Some(format!("Failed to create VM DTBO file {dtbo_path:?}: {e:?}")),
+ )
+ })?;
+ GLOBAL_SERVICE
+ .bindDevicesToVfioDriver(&config.devices, &ParcelFileDescriptor::new(dtbo))?;
+
+ // open (again) a readable file descriptor for crosvm
+ let dtbo = File::open(&dtbo_path).map_err(|e| {
+ error!("Failed to open VM DTBO file {dtbo_path:?}: {e:?}");
+ Status::new_service_specific_error_str(
+ -1,
+ Some(format!("Failed to open VM DTBO file {dtbo_path:?}: {e:?}")),
+ )
+ })?;
+ Some(dtbo)
} else {
None
};
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl
index 516b7a1..cb3ed0b 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVfioHandler.aidl
@@ -28,7 +28,7 @@
* Bind given devices to vfio driver.
*
* @param devices paths of sysfs nodes of devices to assign.
- * @return a file descriptor containing DTBO for VM.
+ * @param dtbo writable file descriptor to store VM DTBO.
*/
- ParcelFileDescriptor bindDevicesToVfioDriver(in String[] devices);
+ void bindDevicesToVfioDriver(in String[] devices, in ParcelFileDescriptor dtbo);
}
diff --git a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
index 3546355..4c7164a 100644
--- a/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
+++ b/virtualizationservice/aidl/android/system/virtualizationservice_internal/IVirtualizationServiceInternal.aidl
@@ -70,7 +70,7 @@
* Bind given devices to vfio driver.
*
* @param devices paths of sysfs nodes of devices to assign.
- * @return a file descriptor containing DTBO for VM.
+ * @param dtbo writable file descriptor to store VM DTBO.
*/
- ParcelFileDescriptor bindDevicesToVfioDriver(in String[] devices);
+ void bindDevicesToVfioDriver(in String[] devices, in ParcelFileDescriptor dtbo);
}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 384915c..2e667d4 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -183,12 +183,18 @@
}])
}
- fn bindDevicesToVfioDriver(&self, devices: &[String]) -> binder::Result<ParcelFileDescriptor> {
+ fn bindDevicesToVfioDriver(
+ &self,
+ devices: &[String],
+ dtbo: &ParcelFileDescriptor,
+ ) -> binder::Result<()> {
check_use_custom_virtual_machine()?;
let vfio_service: Strong<dyn IVfioHandler> =
wait_for_interface(<BpVfioHandler as IVfioHandler>::get_descriptor())?;
- vfio_service.bindDevicesToVfioDriver(devices)
+
+ vfio_service.bindDevicesToVfioDriver(devices, dtbo)?;
+ Ok(())
}
}
diff --git a/virtualizationservice/vfio_handler/src/aidl.rs b/virtualizationservice/vfio_handler/src/aidl.rs
index 9a50fd3..f082aba 100644
--- a/virtualizationservice/vfio_handler/src/aidl.rs
+++ b/virtualizationservice/vfio_handler/src/aidl.rs
@@ -18,11 +18,9 @@
use android_system_virtualizationservice_internal::binder::ParcelFileDescriptor;
use binder::{self, ExceptionCode, Interface, Status};
use lazy_static::lazy_static;
-use std::fs::{read_link, write, File};
-use std::os::fd::FromRawFd;
+use std::fs::{read_link, write};
+use std::io::Write;
use std::path::Path;
-use nix::fcntl::OFlag;
-use nix::unistd::pipe2;
#[derive(Debug, Default)]
pub struct VfioHandler {}
@@ -36,7 +34,11 @@
impl Interface for VfioHandler {}
impl IVfioHandler for VfioHandler {
- fn bindDevicesToVfioDriver(&self, devices: &[String]) -> binder::Result<ParcelFileDescriptor> {
+ fn bindDevicesToVfioDriver(
+ &self,
+ devices: &[String],
+ dtbo: &ParcelFileDescriptor,
+ ) -> binder::Result<()> {
// permission check is already done by IVirtualizationServiceInternal.
if !*IS_VFIO_SUPPORTED {
return Err(Status::new_exception_str(
@@ -47,19 +49,20 @@
devices.iter().try_for_each(|x| bind_device(Path::new(x)))?;
- // TODO(b/278008182): create a file descriptor containing DTBO for devices.
- let (raw_read, raw_write) = pipe2(OFlag::O_CLOEXEC).map_err(|e| {
+ let mut dtbo = dtbo.as_ref().try_clone().map_err(|e| {
Status::new_exception_str(
- ExceptionCode::SERVICE_SPECIFIC,
- Some(format!("can't create fd for DTBO: {e:?}")),
+ ExceptionCode::BAD_PARCELABLE,
+ Some(format!("Failed to clone File from ParcelFileDescriptor: {e:?}")),
)
})?;
- // SAFETY: We are the sole owner of this FD as we just created it, and it is valid and open.
- let read_fd = unsafe { File::from_raw_fd(raw_read) };
- // SAFETY: We are the sole owner of this FD as we just created it, and it is valid and open.
- let _write_fd = unsafe { File::from_raw_fd(raw_write) };
-
- Ok(ParcelFileDescriptor::new(read_fd))
+ // TODO(b/291191362): write DTBO for devices to dtbo.
+ dtbo.write(b"\n").map_err(|e| {
+ Status::new_exception_str(
+ ExceptionCode::BAD_PARCELABLE,
+ Some(format!("Can't write to ParcelFileDescriptor: {e:?}")),
+ )
+ })?;
+ Ok(())
}
}
@@ -120,13 +123,13 @@
let Some(device) = path.file_name() else {
return Err(Status::new_exception_str(
ExceptionCode::ILLEGAL_ARGUMENT,
- Some(format!("can't get device name from {path:?}"))
+ Some(format!("can't get device name from {path:?}")),
));
};
let Some(device_str) = device.to_str() else {
return Err(Status::new_exception_str(
ExceptionCode::ILLEGAL_ARGUMENT,
- Some(format!("invalid filename {device:?}"))
+ Some(format!("invalid filename {device:?}")),
));
};
write(path.join("driver/unbind"), device_str.as_bytes()).map_err(|e| {