(
guest_mem: &GuestMemoryMmap,
cmdline: &str,
vcpu_mpidr: &[u64],
vcpu_topology: Option<(u16, u16, u16, u16)>,
device_info: &HashMap<(DeviceType, String), T, S>,
gic_device: &A
| 206 | /// Creates the flattened device tree for this aarch64 VM. |
| 207 | #[allow(clippy::too_many_arguments)] |
| 208 | pub fn create_fdt<T: DeviceInfoForFdt + Clone + Debug, S: ::std::hash::BuildHasher>( |
| 209 | guest_mem: &GuestMemoryMmap, |
| 210 | cmdline: &str, |
| 211 | vcpu_mpidr: &[u64], |
| 212 | vcpu_topology: Option<(u16, u16, u16, u16)>, |
| 213 | device_info: &HashMap<(DeviceType, String), T, S>, |
| 214 | gic_device: &Arc<Mutex<dyn Vgic>>, |
| 215 | initrd: &Option<InitramfsConfig>, |
| 216 | pci_space_info: &[PciSpaceInfo], |
| 217 | numa_nodes: &NumaNodes, |
| 218 | virtio_iommu_bdf: Option<u32>, |
| 219 | pmu_supported: bool, |
| 220 | ) -> FdtWriterResult<Vec<u8>> { |
| 221 | // Allocate stuff necessary for the holding the blob. |
| 222 | let mut fdt = FdtWriter::new().unwrap(); |
| 223 | |
| 224 | // For an explanation why these nodes were introduced in the blob take a look at |
| 225 | // the "Device Node Requirements" chapter of the Devicetree Specification. |
| 226 | // https://www.devicetree.org/specifications/ |
| 227 | |
| 228 | // Header or the root node as per above mentioned documentation. |
| 229 | let root_node = fdt.begin_node("")?; |
| 230 | fdt.property_string("compatible", "linux,dummy-virt")?; |
| 231 | // For info on #address-cells and size-cells read "Note about cells and address representation" |
| 232 | // from the above mentioned txt file. |
| 233 | fdt.property_u32("#address-cells", ADDRESS_CELLS)?; |
| 234 | fdt.property_u32("#size-cells", SIZE_CELLS)?; |
| 235 | // This is not mandatory but we use it to point the root node to the node |
| 236 | // containing description of the interrupt controller for this VM. |
| 237 | fdt.property_u32("interrupt-parent", GIC_PHANDLE)?; |
| 238 | create_cpu_nodes(&mut fdt, vcpu_mpidr, vcpu_topology, numa_nodes)?; |
| 239 | create_memory_node(&mut fdt, guest_mem, numa_nodes)?; |
| 240 | create_chosen_node(&mut fdt, cmdline, initrd)?; |
| 241 | create_gic_node(&mut fdt, gic_device)?; |
| 242 | create_timer_node(&mut fdt)?; |
| 243 | if pmu_supported { |
| 244 | create_pmu_node(&mut fdt)?; |
| 245 | } |
| 246 | create_clock_node(&mut fdt)?; |
| 247 | create_psci_node(&mut fdt)?; |
| 248 | create_devices_node(&mut fdt, device_info)?; |
| 249 | create_pci_nodes(&mut fdt, pci_space_info, virtio_iommu_bdf)?; |
| 250 | if numa_nodes.len() > 1 { |
| 251 | create_distance_map_node(&mut fdt, numa_nodes)?; |
| 252 | } |
| 253 | |
| 254 | // End Header node. |
| 255 | fdt.end_node(root_node)?; |
| 256 | |
| 257 | let fdt_final = fdt.finish()?; |
| 258 | |
| 259 | Ok(fdt_final) |
| 260 | } |
| 261 | |
| 262 | pub fn write_fdt_to_memory(fdt_final: &[u8], guest_mem: &GuestMemoryMmap) -> Result<()> { |
| 263 | // Write FDT to memory. |
no test coverage detected