Merge changes I9d684029,Iaedc0925,I8d4c8b4f,I93b17a87,I822116f5 into main
* changes:
pvmfw: Pre-populate pviommu nodes
libfdt: Add Fdt::node_mut_with_phandle()
libfdt: Fix bugs in comparing two list in tests
pvmfw: Call patch() in patch test
libfdt: Add FdtNode::get_phandle()
diff --git a/libs/libfdt/src/lib.rs b/libs/libfdt/src/lib.rs
index b811730..b369390 100644
--- a/libs/libfdt/src/lib.rs
+++ b/libs/libfdt/src/lib.rs
@@ -504,6 +504,18 @@
fdt_err_or_option(ret)?.map(|offset| FdtProperty::new(self.fdt, offset)).transpose()
}
+
+ /// Returns the phandle
+ pub fn get_phandle(&self) -> Result<Option<Phandle>> {
+ // This rewrites the fdt_get_phandle() because it doesn't return error code.
+ if let Some(prop) = self.getprop_u32(cstr!("phandle"))? {
+ Ok(Some(prop.try_into()?))
+ } else if let Some(prop) = self.getprop_u32(cstr!("linux,phandle"))? {
+ Ok(Some(prop.try_into()?))
+ } else {
+ Ok(None)
+ }
+ }
}
impl<'a> PartialEq for FdtNode<'a> {
@@ -1012,9 +1024,20 @@
/// Returns a node with the phandle
pub fn node_with_phandle(&self, phandle: Phandle) -> Result<Option<FdtNode>> {
- // SAFETY: Accesses (read-only) are constrained to the DT totalsize.
+ let offset = self.node_offset_with_phandle(phandle)?;
+ Ok(offset.map(|offset| FdtNode { fdt: self, offset }))
+ }
+
+ /// Returns a mutable node with the phandle
+ pub fn node_mut_with_phandle(&mut self, phandle: Phandle) -> Result<Option<FdtNodeMut>> {
+ let offset = self.node_offset_with_phandle(phandle)?;
+ Ok(offset.map(|offset| FdtNodeMut { fdt: self, offset }))
+ }
+
+ fn node_offset_with_phandle(&self, phandle: Phandle) -> Result<Option<c_int>> {
+ // SAFETY: Accesses are constrained to the DT totalsize.
let ret = unsafe { libfdt_bindgen::fdt_node_offset_by_phandle(self.as_ptr(), phandle.0) };
- Ok(fdt_err_or_option(ret)?.map(|offset| FdtNode { fdt: self, offset }))
+ fdt_err_or_option(ret)
}
/// Returns the mutable root node of the tree.
diff --git a/libs/libfdt/tests/api_test.rs b/libs/libfdt/tests/api_test.rs
index bc306ad..d76b1a4 100644
--- a/libs/libfdt/tests/api_test.rs
+++ b/libs/libfdt/tests/api_test.rs
@@ -16,6 +16,7 @@
//! Integration tests of the library libfdt.
+use core::ffi::CStr;
use libfdt::{Fdt, FdtError, FdtNodeMut, Phandle};
use std::ffi::CString;
use std::fs;
@@ -106,11 +107,11 @@
let data = fs::read(TEST_TREE_WITH_NO_MEMORY_NODE_PATH).unwrap();
let fdt = Fdt::from_slice(&data).unwrap();
let root = fdt.root().unwrap();
- let expected = [cstr!("cpus"), cstr!("randomnode"), cstr!("chosen")];
+ let expected = [Ok(cstr!("cpus")), Ok(cstr!("randomnode")), Ok(cstr!("chosen"))];
- for (node, name) in root.subnodes().unwrap().zip(expected) {
- assert_eq!(node.name(), Ok(name));
- }
+ let root_subnodes = root.subnodes().unwrap();
+ let subnode_names: Vec<_> = root_subnodes.map(|node| node.name()).collect();
+ assert_eq!(subnode_names, expected);
}
#[test]
@@ -119,18 +120,19 @@
let fdt = Fdt::from_slice(&data).unwrap();
let root = fdt.root().unwrap();
let one_be = 0x1_u32.to_be_bytes();
- let expected = [
- (cstr!("model"), b"MyBoardName\0".as_ref()),
- (cstr!("compatible"), b"MyBoardName\0MyBoardFamilyName\0".as_ref()),
- (cstr!("#address-cells"), &one_be),
- (cstr!("#size-cells"), &one_be),
- (cstr!("empty_prop"), &[]),
+ type Result<T> = core::result::Result<T, FdtError>;
+ let expected: Vec<(Result<&CStr>, Result<&[u8]>)> = vec![
+ (Ok(cstr!("model")), Ok(b"MyBoardName\0".as_ref())),
+ (Ok(cstr!("compatible")), Ok(b"MyBoardName\0MyBoardFamilyName\0".as_ref())),
+ (Ok(cstr!("#address-cells")), Ok(&one_be)),
+ (Ok(cstr!("#size-cells")), Ok(&one_be)),
+ (Ok(cstr!("empty_prop")), Ok(&[])),
];
let properties = root.properties().unwrap();
- for (prop, (name, value)) in properties.zip(expected.into_iter()) {
- assert_eq!((prop.name(), prop.value()), (Ok(name), Ok(value)));
- }
+ let subnode_properties: Vec<_> = properties.map(|prop| (prop.name(), prop.value())).collect();
+
+ assert_eq!(subnode_properties, expected);
}
#[test]
@@ -138,12 +140,16 @@
let data = fs::read(TEST_TREE_WITH_NO_MEMORY_NODE_PATH).unwrap();
let fdt = Fdt::from_slice(&data).unwrap();
let node = fdt.node(cstr!("/cpus/PowerPC,970@1")).unwrap().unwrap();
- let expected = [cstr!(""), cstr!("cpus"), cstr!("PowerPC,970@1")];
+ let expected = vec![Ok(cstr!("")), Ok(cstr!("cpus")), Ok(cstr!("PowerPC,970@1"))];
- for (depth, name) in expected.into_iter().enumerate() {
- let supernode = node.supernode_at_depth(depth).unwrap();
- assert_eq!(supernode.name(), Ok(name));
+ let mut supernode_names = vec![];
+ let mut depth = 0;
+ while let Ok(supernode) = node.supernode_at_depth(depth) {
+ supernode_names.push(supernode.name());
+ depth += 1;
}
+
+ assert_eq!(supernode_names, expected);
}
#[test]
@@ -200,6 +206,40 @@
}
#[test]
+fn node_mut_with_phandle() {
+ let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
+ let fdt = Fdt::from_mut_slice(&mut data).unwrap();
+
+ // Test linux,phandle
+ let phandle = Phandle::new(0xFF).unwrap();
+ let node: FdtNodeMut = fdt.node_mut_with_phandle(phandle).unwrap().unwrap();
+ assert_eq!(node.as_node().name(), Ok(cstr!("node_zz")));
+
+ // Test phandle
+ let phandle = Phandle::new(0x22).unwrap();
+ let node: FdtNodeMut = fdt.node_mut_with_phandle(phandle).unwrap().unwrap();
+ assert_eq!(node.as_node().name(), Ok(cstr!("node_abc")));
+}
+
+#[test]
+fn node_get_phandle() {
+ let data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
+ let fdt = Fdt::from_slice(&data).unwrap();
+
+ // Test linux,phandle
+ let node = fdt.node(cstr!("/node_z/node_zz")).unwrap().unwrap();
+ assert_eq!(node.get_phandle(), Ok(Phandle::new(0xFF)));
+
+ // Test phandle
+ let node = fdt.node(cstr!("/node_a/node_ab/node_abc")).unwrap().unwrap();
+ assert_eq!(node.get_phandle(), Ok(Phandle::new(0x22)));
+
+ // Test no phandle
+ let node = fdt.node(cstr!("/node_b")).unwrap().unwrap();
+ assert_eq!(node.get_phandle(), Ok(None));
+}
+
+#[test]
fn node_nop() {
let mut data = fs::read(TEST_TREE_PHANDLE_PATH).unwrap();
let fdt = Fdt::from_mut_slice(&mut data).unwrap();
diff --git a/pvmfw/Android.bp b/pvmfw/Android.bp
index 946ed85..b7b5900 100644
--- a/pvmfw/Android.bp
+++ b/pvmfw/Android.bp
@@ -224,7 +224,7 @@
srcs: [":pvmfw_platform.dts.preprocessed"],
out: ["lib.rs"],
tools: ["dtc"],
- cmd: "$(location dtc) -I dts -O dtb -o $(genDir)/compiled.dtbo $(in) && " +
+ cmd: "$(location dtc) -@ -I dts -O dtb -o $(genDir)/compiled.dtbo $(in) && " +
"(" +
" echo '#![no_std]';" +
" echo '#![allow(missing_docs)]';" +
diff --git a/pvmfw/platform.dts b/pvmfw/platform.dts
index cb8e30d..4a269c3 100644
--- a/pvmfw/platform.dts
+++ b/pvmfw/platform.dts
@@ -261,4 +261,64 @@
clock-frequency = <10>;
timeout-sec = <8>;
};
+
+ pviommu_0: pviommu0 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_1: pviommu1 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_2: pviommu2 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_3: pviommu3 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_4: pviommu4 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_5: pviommu5 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_6: pviommu6 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_7: pviommu7 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_8: pviommu8 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
+
+ pviommu_9: pviommu9 {
+ compatible = "pkvm,pviommu";
+ id = <PLACEHOLDER>;
+ #iommu-cells = <0>;
+ };
};
diff --git a/pvmfw/src/device_assignment.rs b/pvmfw/src/device_assignment.rs
index 7eae09f..a92b418 100644
--- a/pvmfw/src/device_assignment.rs
+++ b/pvmfw/src/device_assignment.rs
@@ -401,17 +401,28 @@
unsafe {
platform_dt.apply_overlay(vm_dtbo.as_mut()).unwrap();
}
+ device_info.patch(platform_dt).unwrap();
- let rng_node = platform_dt.node(cstr!("/rng")).unwrap().unwrap();
- let expected: Vec<(&CStr, Vec<u8>)> = vec![
- (cstr!("android,rng,ignore-gctrl-reset"), Vec::<u8>::new()),
- (cstr!("compatible"), b"android,rng\0".to_vec()),
- (cstr!("reg"), into_fdt_prop(vec![0x0, 0x9, 0x0, 0xFF])),
- (cstr!("interrupts"), into_fdt_prop(vec![0x0, 0xF, 0x4])),
+ type FdtResult<T> = libfdt::Result<T>;
+ let expected: Vec<(FdtResult<&CStr>, FdtResult<Vec<u8>>)> = vec![
+ (Ok(cstr!("android,rng,ignore-gctrl-reset")), Ok(Vec::new())),
+ (Ok(cstr!("compatible")), Ok(Vec::from(*b"android,rng\0"))),
+ (Ok(cstr!("interrupts")), Ok(into_fdt_prop(vec![0x0, 0xF, 0x4]))),
+ (Ok(cstr!("reg")), Ok(into_fdt_prop(vec![0x0, 0x9, 0x0, 0xFF]))),
];
- for (prop, (prop_name, prop_value)) in rng_node.properties().unwrap().zip(expected) {
- assert_eq!((prop.name(), prop.value()), (Ok(prop_name), Ok(prop_value.as_slice())));
- }
+ let rng_node = platform_dt.node(cstr!("/rng")).unwrap().unwrap();
+ let mut properties: Vec<_> = rng_node
+ .properties()
+ .unwrap()
+ .map(|prop| (prop.name(), prop.value().map(|x| x.into())))
+ .collect();
+ properties.sort_by(|a, b| {
+ let lhs = a.0.unwrap_or_default();
+ let rhs = b.0.unwrap_or_default();
+ lhs.partial_cmp(rhs).unwrap()
+ });
+
+ assert_eq!(properties, expected);
}
}