pvmfw: Clean pre-populated pvIOMMUs when unused
platform.dts has pre-populated pvIOMMU nodes for device assignment.
The nodes needs to be cleaned even when nothing is assigned.
Bug: 277993056
Test: atest libpvmfw.device_assignment.test, TH
Change-Id: Iac5af3609bcce5bdedcf1abd45c4d07c06415700
diff --git a/pvmfw/src/device_assignment.rs b/pvmfw/src/device_assignment.rs
index 86ad0f0..c732822 100644
--- a/pvmfw/src/device_assignment.rs
+++ b/pvmfw/src/device_assignment.rs
@@ -816,6 +816,18 @@
}
}
+/// Cleans device trees not to contain any pre-populated nodes/props for device assignment.
+pub fn clean(fdt: &mut Fdt) -> Result<()> {
+ let mut compatible = fdt.root_mut().next_compatible(cstr!("pkvm,pviommu"))?;
+ // Filters pre-populated
+ while let Some(filtered_pviommu) = compatible {
+ compatible = filtered_pviommu.delete_and_next_compatible(cstr!("pkvm,pviommu"))?;
+ }
+
+ // Removes any dangling references in __symbols__ (e.g. removed pvIOMMUs)
+ filter_dangling_symbols(fdt)
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -1378,4 +1390,18 @@
assert_eq!(device_info, Err(DeviceAssignmentError::InvalidIommus));
}
+
+ #[test]
+ fn device_assignment_clean() {
+ let mut platform_dt_data = pvmfw_fdt_template::RAW.to_vec();
+ let platform_dt = Fdt::from_mut_slice(&mut platform_dt_data).unwrap();
+
+ let compatible = platform_dt.root().next_compatible(cstr!("pkvm,pviommu"));
+ assert_ne!(None, compatible.unwrap());
+
+ clean(platform_dt).unwrap();
+
+ let compatible = platform_dt.root().next_compatible(cstr!("pkvm,pviommu"));
+ assert_eq!(Ok(None), compatible);
+ }
}
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index 51ba112..d847ca2 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -15,7 +15,7 @@
//! High-level FDT functions.
use crate::bootargs::BootArgsIterator;
-use crate::device_assignment::{DeviceAssignmentInfo, VmDtbo};
+use crate::device_assignment::{self, DeviceAssignmentInfo, VmDtbo};
use crate::helpers::GUEST_PAGE_SIZE;
use crate::Box;
use crate::RebootReason;
@@ -1158,6 +1158,11 @@
error!("Failed to patch device assignment info to DT: {e}");
RebootReason::InvalidFdt
})?;
+ } else {
+ device_assignment::clean(fdt).map_err(|e| {
+ error!("Failed to clean pre-polulated DT nodes for device assignment: {e}");
+ RebootReason::InvalidFdt
+ })?;
}
patch_untrusted_props(fdt, &info.untrusted_props).map_err(|e| {
error!("Failed to patch untrusted properties: {e}");