Merge changes Iee55d611,I98e0173f,I4ed5bff2 into main am: 61066b0c54

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Virtualization/+/2977971

Change-Id: I8ce8c237b99bbb50c09bbeec9c04e1c11987368a
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 6e7c3c8..f50007f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -87,7 +87,7 @@
 genrule_defaults {
     name: "dts_to_dtb",
     tools: ["dtc"],
-    cmd: "FILES=($(in)) && $(location dtc) -I dts -O dtb $${FILES[-1]} -o $(out)",
+    cmd: "FILES=($(in)) && $(location dtc) -@ -I dts -O dtb $${FILES[-1]} -o $(out)",
 }
 
 // This is a temporary workaround until b/309090563 is implemented.
diff --git a/docs/device_assignment.md b/docs/device_assignment.md
index 4c5b477..1166cdf 100644
--- a/docs/device_assignment.md
+++ b/docs/device_assignment.md
@@ -165,10 +165,10 @@
 ```
 
 If you compile the above with `dtc -@`, then you'll get `__symbols__` for free.
-The generated `__symbols__` indicates that there are four assignable devices.
+`__symbol__` has label of nodes, and it's required for the next step.
 
 ```dts
-    // generated __symbols__. AVF will ignore non-overlayable nodes.
+    // generated __symbols__
     __symbols__ {
         iommu0 = "/host/iommu0";
         iommu1 = "/host/iommu1";
@@ -200,10 +200,10 @@
 
 * `<kind>`: Device kind. Currently only used for debugging purposes and not used
   for device assignment.
-* `<dtbo_label>`: Label in the VM DTBO (i.e. symbols in `__symbols__`). Must be
-  unique.
+* `<dtbo_label>`: Label in the VM DTBO (i.e. symbol in `__symbols__`). Must be
+  non-empty and unique in the XML.
 * `<sysfs_path>`: Sysfs path of the device in host, used to bind to the VFIO
-  driver. Must be unique in the XML.
+  driver. Must be non-empty and unique in the XML.
 
 ## Boot with VM DTBO
 
diff --git a/pvmfw/src/device_assignment.rs b/pvmfw/src/device_assignment.rs
index 2c47f9e..9c3e566 100644
--- a/pvmfw/src/device_assignment.rs
+++ b/pvmfw/src/device_assignment.rs
@@ -167,9 +167,7 @@
     //           rng { ... };      // Actual device node is here. If overlaid, path would be "/rng"
     //         };
     //       };
-    //       __symbols__ {         // List of assignable devices
-    //         // Each property describes an assigned device device information.
-    //         // property name is the device label, and property value is the path in the VM DTBO.
+    //       __symbols__ {         // Contains list of assignable devices
     //         rng = "/fragment@rng/__overlay__/rng";
     //       };
     //    };
@@ -581,10 +579,13 @@
 
         let Some(node) = fdt.node(&node_path)? else { return Ok(None) };
 
-        // Note: Currently can only assign devices backed by physical devices.
+        // Currently can only assign devices backed by physical devices.
         let phandle = dtbo_node.get_phandle()?.ok_or(DeviceAssignmentError::InvalidDtbo)?;
-        let physical_device =
-            physical_devices.get(&phandle).ok_or(DeviceAssignmentError::InvalidDtbo)?;
+        let Some(physical_device) = physical_devices.get(&phandle) else {
+            // If labeled DT node isn't backed by physical device node, then just return None.
+            // It's not an error because such node can be a dependency of assignable device nodes.
+            return Ok(None);
+        };
 
         let reg = parse_node_reg(&node)?;
         Self::validate_reg(&reg, &physical_device.reg, hypervisor)?;
@@ -705,7 +706,6 @@
 
         // Clean up any nodes that wouldn't be overlaid but may contain reference to filtered nodes.
         // Otherwise, `fdt_apply_overlay()` would fail because of missing phandle reference.
-        filtered_dtbo_paths.push(CString::new("/__symbols__").unwrap());
         // TODO(b/277993056): Also filter other unused nodes/props in __local_fixups__
         filtered_dtbo_paths.push(CString::new("/__local_fixups__/host").unwrap());
 
@@ -718,7 +718,6 @@
     /// Filters VM DTBO to only contain necessary information for booting pVM
     /// In detail, this will remove followings by setting nop node / nop property.
     ///   - Removes unassigned devices
-    ///   - Removes /__symbols__ node
     // TODO(b/277993056): remove unused dependencies in VM DTBO.
     // TODO(b/277993056): remove supernodes' properties.
     // TODO(b/277993056): remove unused alises.
@@ -731,7 +730,7 @@
             node.nop()?;
         }
 
-        Ok(())
+        filter_dangling_symbols(vm_dtbo)
     }
 
     fn patch_pviommus(&self, fdt: &mut Fdt) -> Result<BTreeMap<PvIommu, Phandle>> {
@@ -923,7 +922,7 @@
 
         let expected = [AssignedDeviceInfo {
             node_path: CString::new("/bus0/backlight").unwrap(),
-            dtbo_node_path: cstr!("/fragment@backlight/__overlay__/bus0/backlight").into(),
+            dtbo_node_path: cstr!("/fragment@0/__overlay__/bus0/backlight").into(),
             reg: vec![[0x9, 0xFF].into()],
             interrupts: into_fdt_prop(vec![0x0, 0xF, 0x4]),
             iommus: vec![],
@@ -947,7 +946,7 @@
 
         let expected = [AssignedDeviceInfo {
             node_path: CString::new("/rng").unwrap(),
-            dtbo_node_path: cstr!("/fragment@rng/__overlay__/rng").into(),
+            dtbo_node_path: cstr!("/fragment@0/__overlay__/rng").into(),
             reg: vec![[0x9, 0xFF].into()],
             interrupts: into_fdt_prop(vec![0x0, 0xF, 0x4]),
             iommus: vec![(PvIommu { id: 0x4 }, Vsid(0xFF0))],
@@ -972,21 +971,27 @@
 
         let vm_dtbo = vm_dtbo.as_mut();
 
-        let rng = vm_dtbo.node(cstr!("/fragment@rng/__overlay__/rng")).unwrap();
+        let symbols = vm_dtbo.symbols().unwrap().unwrap();
+
+        let rng = vm_dtbo.node(cstr!("/fragment@0/__overlay__/rng")).unwrap();
         assert_ne!(rng, None);
+        let rng_symbol = symbols.getprop_str(cstr!("rng")).unwrap();
+        assert_eq!(Some(cstr!("/fragment@0/__overlay__/rng")), rng_symbol);
 
-        let light = vm_dtbo.node(cstr!("/fragment@rng/__overlay__/light")).unwrap();
+        let light = vm_dtbo.node(cstr!("/fragment@0/__overlay__/light")).unwrap();
         assert_eq!(light, None);
+        let light_symbol = symbols.getprop_str(cstr!("light")).unwrap();
+        assert_eq!(None, light_symbol);
 
-        let led = vm_dtbo.node(cstr!("/fragment@led/__overlay__/led")).unwrap();
+        let led = vm_dtbo.node(cstr!("/fragment@0/__overlay__/led")).unwrap();
         assert_eq!(led, None);
+        let led_symbol = symbols.getprop_str(cstr!("led")).unwrap();
+        assert_eq!(None, led_symbol);
 
-        let backlight =
-            vm_dtbo.node(cstr!("/fragment@backlight/__overlay__/bus0/backlight")).unwrap();
+        let backlight = vm_dtbo.node(cstr!("/fragment@0/__overlay__/bus0/backlight")).unwrap();
         assert_eq!(backlight, None);
-
-        let symbols_node = vm_dtbo.symbols().unwrap();
-        assert_eq!(symbols_node, None);
+        let backlight_symbol = symbols.getprop_str(cstr!("backlight")).unwrap();
+        assert_eq!(None, backlight_symbol);
     }
 
     #[test]
diff --git a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts
index 23bc3c0..daf8158 100644
--- a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts
+++ b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo.dts
@@ -1,4 +1,5 @@
 /dts-v1/;
+/plugin/;
 
 / {
     host {
@@ -6,113 +7,62 @@
         #size-cells = <0x1>;
         rng {
             reg = <0x0 0x12f00000 0xFF>;
-            iommus = <0x1 0x3>;
-            android,pvmfw,target = <0x2>;
+            iommus = <&iommu0 0x3>;
+            android,pvmfw,target = <&rng>;
         };
         light {
             reg = <0x0 0x00f00000 0x1000>, <0x0 0x00f10000 0x1000>;
-            iommus = <0x3 0x4>, <0x4 0x5>;
-            android,pvmfw,target = <0x5>;
+            iommus = <&iommu1 0x4>, <&iommu2 0x5>;
+            android,pvmfw,target = <&light>;
         };
         led {
             reg = <0x0 0x12000000 0x9>;
-            iommus = <0x1 0x9>;
-            android,pvmfw,target = <0x6>;
+            iommus = <&iommu0 0x9>;
+            android,pvmfw,target = <&led>;
         };
         bus0 {
             #address-cells = <0x1>;
             #size-cells = <0x1>;
             backlight {
                 reg = <0x300 0xFF>;
-                android,pvmfw,target = <0x7>;
+                android,pvmfw,target = <&backlight>;
             };
         };
-        iommu0 {
+        iommu0: iommu0 {
             #iommu-cells = <0x1>;
             android,pvmfw,token = <0x0 0x12e40000>;
-            phandle = <0x1>;
         };
-        iommu1 {
+        iommu1: iommu1 {
             #iommu-cells = <0x1>;
             android,pvmfw,token = <0x0 0x40000>;
-            phandle = <0x3>;
         };
-        iommu2 {
+        iommu2: iommu2 {
             #iommu-cells = <0x1>;
             android,pvmfw,token = <0x0 0x50000>;
-            phandle = <0x4>;
-        };
-    };
-    fragment@rng {
-        target-path = "/";
-        __overlay__ {
-            rng {
-                compatible = "android,rng";
-                android,rng,ignore-gctrl-reset;
-                phandle = <0x2>;
-            };
-        };
-    };
-    fragment@sensor {
-        target-path = "/";
-        __overlay__ {
-            light {
-                compatible = "android,light";
-                version = <0x1 0x2>;
-                phandle = <0x5>;
-            };
-        };
-    };
-    fragment@led {
-        target-path = "/";
-        __overlay__ {
-            led {
-                compatible = "android,led";
-                prop = <0x555>;
-                phandle = <0x6>;
-            };
-        };
-    };
-    fragment@backlight {
-        target-path = "/";
-        __overlay__ {
-            bus0 {
-                backlight {
-                    compatible = "android,backlight";
-                    android,backlight,ignore-gctrl-reset;
-                    phandle = <0x7>;
-                };
-            };
-        };
-    };
-    __symbols__ {
-        iommu0 = "/host/iommu0";
-        iommu1 = "/host/iommu1";
-        iommu2 = "/host/iommu2";
-        rng = "/fragment@rng/__overlay__/rng";
-        light = "/fragment@sensor/__overlay__/light";
-        led = "/fragment@led/__overlay__/led";
-        backlight = "/fragment@backlight/__overlay__/bus0/backlight";
-    };
-    __local_fixups__ {
-        host {
-            rng {
-                iommus = <0x0>;
-                android,pvmfw,target = <0x0>;
-            };
-            light {
-                iommus = <0x0 0x8>;
-                android,pvmfw,target = <0x0>;
-            };
-            led {
-                iommus = <0x0>;
-                android,pvmfw,target = <0x0>;
-            };
-            bus0 {
-                backlight {
-                    android,pvmfw,target = <0x0>;
-                };
-            };
         };
     };
 };
+
+&{/} {
+    rng: rng {
+        compatible = "android,rng";
+        android,rng,ignore-gctrl-reset;
+    };
+
+    light: light {
+        compatible = "android,light";
+        version = <0x1 0x2>;
+    };
+
+    led: led {
+        compatible = "android,led";
+        prop = <0x555>;
+    };
+
+    bus0 {
+        backlight: backlight {
+            compatible = "android,backlight";
+            android,backlight,ignore-gctrl-reset;
+        };
+    };
+};
\ No newline at end of file
diff --git a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_with_duplicated_iommus.dts b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_with_duplicated_iommus.dts
index 45b26e0..fb68320 100644
--- a/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_with_duplicated_iommus.dts
+++ b/pvmfw/testdata/test_pvmfw_devices_vm_dtbo_with_duplicated_iommus.dts
@@ -1,4 +1,5 @@
 /dts-v1/;
+/plugin/;
 
 / {
     host {
@@ -6,55 +7,29 @@
         #size-cells = <0x1>;
         rng {
             reg = <0x0 0x12f00000 0xFF>;
-            iommus = <0x1 0x3>;
-            android,pvmfw,target = <0x2>;
+            iommus = <&iommu0 0x3>;
+            android,pvmfw,target = <&rng>;
         };
         led {
             reg = <0x0 0x12000000 0x9>;
-            iommus = <0x1 0x3>;
-            android,pvmfw,target = <0x6>;
+            iommus = <&iommu0 0x3>;
+            android,pvmfw,target = <&led>;
         };
-        iommu0 {
+        iommu0: iommu0 {
             #iommu-cells = <0x1>;
             android,pvmfw,token = <0x0 0x12e40000>;
-            phandle = <0x1>;
         };
     };
-    fragment@rng {
-        target-path = "/";
-        __overlay__ {
-            rng {
-                compatible = "android,rng";
-                android,rng,ignore-gctrl-reset;
-                phandle = <0x2>;
-            };
-        };
+};
+
+&{/} {
+    rng: rng {
+        compatible = "android,rng";
+        android,rng,ignore-gctrl-reset;
     };
-    fragment@led {
-        target-path = "/";
-        __overlay__ {
-            led {
-                compatible = "android,led";
-                prop = <0x555>;
-                phandle = <0x6>;
-            };
-        };
-    };
-    __symbols__ {
-        iommu0 = "/host/iommu0";
-        rng = "/fragment@rng/__overlay__/rng";
-        led = "/fragment@led/__overlay__/led";
-    };
-    __local_fixups__ {
-        host {
-            rng {
-                iommus = <0x0>;
-                android,pvmfw,target = <0x0>;
-            };
-            led {
-                iommus = <0x0>;
-                android,pvmfw,target = <0x0>;
-            };
-        };
+
+    led: led {
+        compatible = "android,led";
+        prop = <0x555>;
     };
 };