xref: /aosp_15_r20/external/crosvm/aarch64/src/fdt.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::HashSet;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::File;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::fs::OpenOptions;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::io::Write;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker use arch::apply_device_tree_overlays;
13*bb4ee6a4SAndroid Build Coastguard Worker use arch::serial::SerialDeviceInfo;
14*bb4ee6a4SAndroid Build Coastguard Worker use arch::CpuSet;
15*bb4ee6a4SAndroid Build Coastguard Worker use arch::DtbOverlay;
16*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
17*bb4ee6a4SAndroid Build Coastguard Worker use arch::PlatformBusResources;
18*bb4ee6a4SAndroid Build Coastguard Worker use base::open_file_or_duplicate;
19*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Error;
20*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Fdt;
21*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Result;
22*bb4ee6a4SAndroid Build Coastguard Worker // This is a Battery related constant
23*bb4ee6a4SAndroid Build Coastguard Worker use devices::bat::GOLDFISHBAT_MMIO_LEN;
24*bb4ee6a4SAndroid Build Coastguard Worker use devices::pl030::PL030_AMBA_ID;
25*bb4ee6a4SAndroid Build Coastguard Worker use devices::IommuDevType;
26*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciAddress;
27*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciInterruptPin;
28*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PsciVersion;
29*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::VmAArch64;
30*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PSCI_0_2;
31*bb4ee6a4SAndroid Build Coastguard Worker use hypervisor::PSCI_1_0;
32*bb4ee6a4SAndroid Build Coastguard Worker use rand::rngs::OsRng;
33*bb4ee6a4SAndroid Build Coastguard Worker use rand::RngCore;
34*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
35*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
36*bb4ee6a4SAndroid Build Coastguard Worker 
37*bb4ee6a4SAndroid Build Coastguard Worker // These are GIC address-space location constants.
38*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_GIC_CPUI_BASE;
39*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_GIC_CPUI_SIZE;
40*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_GIC_DIST_BASE;
41*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_GIC_DIST_SIZE;
42*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_GIC_REDIST_SIZE;
43*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_PMU_IRQ;
44*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_PROTECTED_VM_FW_START;
45*bb4ee6a4SAndroid Build Coastguard Worker // These are RTC related constants
46*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_RTC_ADDR;
47*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_RTC_IRQ;
48*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_RTC_SIZE;
49*bb4ee6a4SAndroid Build Coastguard Worker // These are serial device related constants.
50*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_SERIAL_SPEED;
51*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_VIRTFREQ_BASE;
52*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_VIRTFREQ_SIZE;
53*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_VIRTFREQ_V2_SIZE;
54*bb4ee6a4SAndroid Build Coastguard Worker use crate::AARCH64_VMWDT_IRQ;
55*bb4ee6a4SAndroid Build Coastguard Worker 
56*bb4ee6a4SAndroid Build Coastguard Worker // This is an arbitrary number to specify the node for the GIC.
57*bb4ee6a4SAndroid Build Coastguard Worker // If we had a more complex interrupt architecture, then we'd need an enum for
58*bb4ee6a4SAndroid Build Coastguard Worker // these.
59*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_GIC: u32 = 1;
60*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_RESTRICTED_DMA_POOL: u32 = 2;
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker // CPUs are assigned phandles starting with this number.
63*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_CPU0: u32 = 0x100;
64*bb4ee6a4SAndroid Build Coastguard Worker 
65*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_OPP_DOMAIN_BASE: u32 = 0x1000;
66*bb4ee6a4SAndroid Build Coastguard Worker 
67*bb4ee6a4SAndroid Build Coastguard Worker // pKVM pvIOMMUs are assigned phandles starting with this number.
68*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_PKVM_PVIOMMU: u32 = 0x2000;
69*bb4ee6a4SAndroid Build Coastguard Worker 
70*bb4ee6a4SAndroid Build Coastguard Worker // These are specified by the Linux GIC bindings
71*bb4ee6a4SAndroid Build Coastguard Worker const GIC_FDT_IRQ_NUM_CELLS: u32 = 3;
72*bb4ee6a4SAndroid Build Coastguard Worker const GIC_FDT_IRQ_TYPE_SPI: u32 = 0;
73*bb4ee6a4SAndroid Build Coastguard Worker const GIC_FDT_IRQ_TYPE_PPI: u32 = 1;
74*bb4ee6a4SAndroid Build Coastguard Worker const GIC_FDT_IRQ_PPI_CPU_SHIFT: u32 = 8;
75*bb4ee6a4SAndroid Build Coastguard Worker const GIC_FDT_IRQ_PPI_CPU_MASK: u32 = 0xff << GIC_FDT_IRQ_PPI_CPU_SHIFT;
76*bb4ee6a4SAndroid Build Coastguard Worker const IRQ_TYPE_EDGE_RISING: u32 = 0x00000001;
77*bb4ee6a4SAndroid Build Coastguard Worker const IRQ_TYPE_LEVEL_HIGH: u32 = 0x00000004;
78*bb4ee6a4SAndroid Build Coastguard Worker const IRQ_TYPE_LEVEL_LOW: u32 = 0x00000008;
79*bb4ee6a4SAndroid Build Coastguard Worker 
create_memory_node(fdt: &mut Fdt, guest_mem: &GuestMemory) -> Result<()>80*bb4ee6a4SAndroid Build Coastguard Worker fn create_memory_node(fdt: &mut Fdt, guest_mem: &GuestMemory) -> Result<()> {
81*bb4ee6a4SAndroid Build Coastguard Worker     let mut mem_reg_prop = Vec::new();
82*bb4ee6a4SAndroid Build Coastguard Worker     let mut previous_memory_region_end = None;
83*bb4ee6a4SAndroid Build Coastguard Worker     let mut regions = guest_mem.guest_memory_regions();
84*bb4ee6a4SAndroid Build Coastguard Worker     regions.sort();
85*bb4ee6a4SAndroid Build Coastguard Worker     for region in regions {
86*bb4ee6a4SAndroid Build Coastguard Worker         if region.0.offset() == AARCH64_PROTECTED_VM_FW_START {
87*bb4ee6a4SAndroid Build Coastguard Worker             continue;
88*bb4ee6a4SAndroid Build Coastguard Worker         }
89*bb4ee6a4SAndroid Build Coastguard Worker         // Merge with the previous region if possible.
90*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(previous_end) = previous_memory_region_end {
91*bb4ee6a4SAndroid Build Coastguard Worker             if region.0 == previous_end {
92*bb4ee6a4SAndroid Build Coastguard Worker                 *mem_reg_prop.last_mut().unwrap() += region.1 as u64;
93*bb4ee6a4SAndroid Build Coastguard Worker                 previous_memory_region_end =
94*bb4ee6a4SAndroid Build Coastguard Worker                     Some(previous_end.checked_add(region.1 as u64).unwrap());
95*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
96*bb4ee6a4SAndroid Build Coastguard Worker             }
97*bb4ee6a4SAndroid Build Coastguard Worker             assert!(region.0 > previous_end, "Memory regions overlap");
98*bb4ee6a4SAndroid Build Coastguard Worker         }
99*bb4ee6a4SAndroid Build Coastguard Worker 
100*bb4ee6a4SAndroid Build Coastguard Worker         mem_reg_prop.push(region.0.offset());
101*bb4ee6a4SAndroid Build Coastguard Worker         mem_reg_prop.push(region.1 as u64);
102*bb4ee6a4SAndroid Build Coastguard Worker         previous_memory_region_end = Some(region.0.checked_add(region.1 as u64).unwrap());
103*bb4ee6a4SAndroid Build Coastguard Worker     }
104*bb4ee6a4SAndroid Build Coastguard Worker 
105*bb4ee6a4SAndroid Build Coastguard Worker     let memory_node = fdt.root_mut().subnode_mut("memory")?;
106*bb4ee6a4SAndroid Build Coastguard Worker     memory_node.set_prop("device_type", "memory")?;
107*bb4ee6a4SAndroid Build Coastguard Worker     memory_node.set_prop("reg", mem_reg_prop)?;
108*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
109*bb4ee6a4SAndroid Build Coastguard Worker }
110*bb4ee6a4SAndroid Build Coastguard Worker 
create_resv_memory_node( fdt: &mut Fdt, resv_addr_and_size: (Option<GuestAddress>, u64), ) -> Result<u32>111*bb4ee6a4SAndroid Build Coastguard Worker fn create_resv_memory_node(
112*bb4ee6a4SAndroid Build Coastguard Worker     fdt: &mut Fdt,
113*bb4ee6a4SAndroid Build Coastguard Worker     resv_addr_and_size: (Option<GuestAddress>, u64),
114*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<u32> {
115*bb4ee6a4SAndroid Build Coastguard Worker     let (resv_addr, resv_size) = resv_addr_and_size;
116*bb4ee6a4SAndroid Build Coastguard Worker 
117*bb4ee6a4SAndroid Build Coastguard Worker     let resv_memory_node = fdt.root_mut().subnode_mut("reserved-memory")?;
118*bb4ee6a4SAndroid Build Coastguard Worker     resv_memory_node.set_prop("#address-cells", 0x2u32)?;
119*bb4ee6a4SAndroid Build Coastguard Worker     resv_memory_node.set_prop("#size-cells", 0x2u32)?;
120*bb4ee6a4SAndroid Build Coastguard Worker     resv_memory_node.set_prop("ranges", ())?;
121*bb4ee6a4SAndroid Build Coastguard Worker 
122*bb4ee6a4SAndroid Build Coastguard Worker     let restricted_dma_pool_node = if let Some(resv_addr) = resv_addr {
123*bb4ee6a4SAndroid Build Coastguard Worker         let node =
124*bb4ee6a4SAndroid Build Coastguard Worker             resv_memory_node.subnode_mut(&format!("restricted_dma_reserved@{:x}", resv_addr.0))?;
125*bb4ee6a4SAndroid Build Coastguard Worker         node.set_prop("reg", &[resv_addr.0, resv_size])?;
126*bb4ee6a4SAndroid Build Coastguard Worker         node
127*bb4ee6a4SAndroid Build Coastguard Worker     } else {
128*bb4ee6a4SAndroid Build Coastguard Worker         let node = resv_memory_node.subnode_mut("restricted_dma_reserved")?;
129*bb4ee6a4SAndroid Build Coastguard Worker         node.set_prop("size", resv_size)?;
130*bb4ee6a4SAndroid Build Coastguard Worker         node
131*bb4ee6a4SAndroid Build Coastguard Worker     };
132*bb4ee6a4SAndroid Build Coastguard Worker     restricted_dma_pool_node.set_prop("phandle", PHANDLE_RESTRICTED_DMA_POOL)?;
133*bb4ee6a4SAndroid Build Coastguard Worker     restricted_dma_pool_node.set_prop("compatible", "restricted-dma-pool")?;
134*bb4ee6a4SAndroid Build Coastguard Worker     restricted_dma_pool_node.set_prop("alignment", base::pagesize() as u64)?;
135*bb4ee6a4SAndroid Build Coastguard Worker     Ok(PHANDLE_RESTRICTED_DMA_POOL)
136*bb4ee6a4SAndroid Build Coastguard Worker }
137*bb4ee6a4SAndroid Build Coastguard Worker 
create_cpu_nodes( fdt: &mut Fdt, num_cpus: u32, cpu_mpidr_generator: &impl Fn(usize) -> Option<u64>, cpu_clusters: Vec<CpuSet>, cpu_capacity: BTreeMap<usize, u32>, dynamic_power_coefficient: BTreeMap<usize, u32>, cpu_frequencies: BTreeMap<usize, Vec<u32>>, ) -> Result<()>138*bb4ee6a4SAndroid Build Coastguard Worker fn create_cpu_nodes(
139*bb4ee6a4SAndroid Build Coastguard Worker     fdt: &mut Fdt,
140*bb4ee6a4SAndroid Build Coastguard Worker     num_cpus: u32,
141*bb4ee6a4SAndroid Build Coastguard Worker     cpu_mpidr_generator: &impl Fn(usize) -> Option<u64>,
142*bb4ee6a4SAndroid Build Coastguard Worker     cpu_clusters: Vec<CpuSet>,
143*bb4ee6a4SAndroid Build Coastguard Worker     cpu_capacity: BTreeMap<usize, u32>,
144*bb4ee6a4SAndroid Build Coastguard Worker     dynamic_power_coefficient: BTreeMap<usize, u32>,
145*bb4ee6a4SAndroid Build Coastguard Worker     cpu_frequencies: BTreeMap<usize, Vec<u32>>,
146*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
147*bb4ee6a4SAndroid Build Coastguard Worker     let root_node = fdt.root_mut();
148*bb4ee6a4SAndroid Build Coastguard Worker     let cpus_node = root_node.subnode_mut("cpus")?;
149*bb4ee6a4SAndroid Build Coastguard Worker     cpus_node.set_prop("#address-cells", 0x1u32)?;
150*bb4ee6a4SAndroid Build Coastguard Worker     cpus_node.set_prop("#size-cells", 0x0u32)?;
151*bb4ee6a4SAndroid Build Coastguard Worker 
152*bb4ee6a4SAndroid Build Coastguard Worker     for cpu_id in 0..num_cpus {
153*bb4ee6a4SAndroid Build Coastguard Worker         let reg = u32::try_from(
154*bb4ee6a4SAndroid Build Coastguard Worker             cpu_mpidr_generator(cpu_id.try_into().unwrap()).ok_or(Error::PropertyValueInvalid)?,
155*bb4ee6a4SAndroid Build Coastguard Worker         )
156*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| Error::PropertyValueTooLarge)?;
157*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_name = format!("cpu@{:x}", reg);
158*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_node = cpus_node.subnode_mut(&cpu_name)?;
159*bb4ee6a4SAndroid Build Coastguard Worker         cpu_node.set_prop("device_type", "cpu")?;
160*bb4ee6a4SAndroid Build Coastguard Worker         cpu_node.set_prop("compatible", "arm,armv8")?;
161*bb4ee6a4SAndroid Build Coastguard Worker         if num_cpus > 1 {
162*bb4ee6a4SAndroid Build Coastguard Worker             cpu_node.set_prop("enable-method", "psci")?;
163*bb4ee6a4SAndroid Build Coastguard Worker         }
164*bb4ee6a4SAndroid Build Coastguard Worker         cpu_node.set_prop("reg", reg)?;
165*bb4ee6a4SAndroid Build Coastguard Worker         cpu_node.set_prop("phandle", PHANDLE_CPU0 + cpu_id)?;
166*bb4ee6a4SAndroid Build Coastguard Worker 
167*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(pwr_coefficient) = dynamic_power_coefficient.get(&(cpu_id as usize)) {
168*bb4ee6a4SAndroid Build Coastguard Worker             cpu_node.set_prop("dynamic-power-coefficient", *pwr_coefficient)?;
169*bb4ee6a4SAndroid Build Coastguard Worker         }
170*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(capacity) = cpu_capacity.get(&(cpu_id as usize)) {
171*bb4ee6a4SAndroid Build Coastguard Worker             cpu_node.set_prop("capacity-dmips-mhz", *capacity)?;
172*bb4ee6a4SAndroid Build Coastguard Worker         }
173*bb4ee6a4SAndroid Build Coastguard Worker         // Placed inside cpu nodes for ease of parsing for some secure firmwares(PvmFw).
174*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(frequencies) = cpu_frequencies.get(&(cpu_id as usize)) {
175*bb4ee6a4SAndroid Build Coastguard Worker             cpu_node.set_prop("operating-points-v2", PHANDLE_OPP_DOMAIN_BASE + cpu_id)?;
176*bb4ee6a4SAndroid Build Coastguard Worker             let opp_table_node = cpu_node.subnode_mut(&format!("opp_table{}", cpu_id))?;
177*bb4ee6a4SAndroid Build Coastguard Worker             opp_table_node.set_prop("phandle", PHANDLE_OPP_DOMAIN_BASE + cpu_id)?;
178*bb4ee6a4SAndroid Build Coastguard Worker             opp_table_node.set_prop("compatible", "operating-points-v2")?;
179*bb4ee6a4SAndroid Build Coastguard Worker             for freq in frequencies.iter() {
180*bb4ee6a4SAndroid Build Coastguard Worker                 let opp_hz = (*freq) as u64 * 1000;
181*bb4ee6a4SAndroid Build Coastguard Worker                 let opp_node = opp_table_node.subnode_mut(&format!("opp{}", opp_hz))?;
182*bb4ee6a4SAndroid Build Coastguard Worker                 opp_node.set_prop("opp-hz", opp_hz)?;
183*bb4ee6a4SAndroid Build Coastguard Worker             }
184*bb4ee6a4SAndroid Build Coastguard Worker         }
185*bb4ee6a4SAndroid Build Coastguard Worker     }
186*bb4ee6a4SAndroid Build Coastguard Worker 
187*bb4ee6a4SAndroid Build Coastguard Worker     if !cpu_clusters.is_empty() {
188*bb4ee6a4SAndroid Build Coastguard Worker         let cpu_map_node = cpus_node.subnode_mut("cpu-map")?;
189*bb4ee6a4SAndroid Build Coastguard Worker         for (cluster_idx, cpus) in cpu_clusters.iter().enumerate() {
190*bb4ee6a4SAndroid Build Coastguard Worker             let cluster_node = cpu_map_node.subnode_mut(&format!("cluster{}", cluster_idx))?;
191*bb4ee6a4SAndroid Build Coastguard Worker             for (core_idx, cpu_id) in cpus.iter().enumerate() {
192*bb4ee6a4SAndroid Build Coastguard Worker                 let core_node = cluster_node.subnode_mut(&format!("core{}", core_idx))?;
193*bb4ee6a4SAndroid Build Coastguard Worker                 core_node.set_prop("cpu", PHANDLE_CPU0 + *cpu_id as u32)?;
194*bb4ee6a4SAndroid Build Coastguard Worker             }
195*bb4ee6a4SAndroid Build Coastguard Worker         }
196*bb4ee6a4SAndroid Build Coastguard Worker     }
197*bb4ee6a4SAndroid Build Coastguard Worker 
198*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
199*bb4ee6a4SAndroid Build Coastguard Worker }
200*bb4ee6a4SAndroid Build Coastguard Worker 
create_gic_node(fdt: &mut Fdt, is_gicv3: bool, num_cpus: u64) -> Result<()>201*bb4ee6a4SAndroid Build Coastguard Worker fn create_gic_node(fdt: &mut Fdt, is_gicv3: bool, num_cpus: u64) -> Result<()> {
202*bb4ee6a4SAndroid Build Coastguard Worker     let mut gic_reg_prop = [AARCH64_GIC_DIST_BASE, AARCH64_GIC_DIST_SIZE, 0, 0];
203*bb4ee6a4SAndroid Build Coastguard Worker 
204*bb4ee6a4SAndroid Build Coastguard Worker     let intc_node = fdt.root_mut().subnode_mut("intc")?;
205*bb4ee6a4SAndroid Build Coastguard Worker     if is_gicv3 {
206*bb4ee6a4SAndroid Build Coastguard Worker         intc_node.set_prop("compatible", "arm,gic-v3")?;
207*bb4ee6a4SAndroid Build Coastguard Worker         gic_reg_prop[2] = AARCH64_GIC_DIST_BASE - (AARCH64_GIC_REDIST_SIZE * num_cpus);
208*bb4ee6a4SAndroid Build Coastguard Worker         gic_reg_prop[3] = AARCH64_GIC_REDIST_SIZE * num_cpus;
209*bb4ee6a4SAndroid Build Coastguard Worker     } else {
210*bb4ee6a4SAndroid Build Coastguard Worker         intc_node.set_prop("compatible", "arm,cortex-a15-gic")?;
211*bb4ee6a4SAndroid Build Coastguard Worker         gic_reg_prop[2] = AARCH64_GIC_CPUI_BASE;
212*bb4ee6a4SAndroid Build Coastguard Worker         gic_reg_prop[3] = AARCH64_GIC_CPUI_SIZE;
213*bb4ee6a4SAndroid Build Coastguard Worker     }
214*bb4ee6a4SAndroid Build Coastguard Worker     intc_node.set_prop("#interrupt-cells", GIC_FDT_IRQ_NUM_CELLS)?;
215*bb4ee6a4SAndroid Build Coastguard Worker     intc_node.set_prop("interrupt-controller", ())?;
216*bb4ee6a4SAndroid Build Coastguard Worker     intc_node.set_prop("reg", &gic_reg_prop)?;
217*bb4ee6a4SAndroid Build Coastguard Worker     intc_node.set_prop("phandle", PHANDLE_GIC)?;
218*bb4ee6a4SAndroid Build Coastguard Worker     intc_node.set_prop("#address-cells", 2u32)?;
219*bb4ee6a4SAndroid Build Coastguard Worker     intc_node.set_prop("#size-cells", 2u32)?;
220*bb4ee6a4SAndroid Build Coastguard Worker     add_symbols_entry(fdt, "intc", "/intc")?;
221*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
222*bb4ee6a4SAndroid Build Coastguard Worker }
223*bb4ee6a4SAndroid Build Coastguard Worker 
create_timer_node(fdt: &mut Fdt, num_cpus: u32) -> Result<()>224*bb4ee6a4SAndroid Build Coastguard Worker fn create_timer_node(fdt: &mut Fdt, num_cpus: u32) -> Result<()> {
225*bb4ee6a4SAndroid Build Coastguard Worker     // These are fixed interrupt numbers for the timer device.
226*bb4ee6a4SAndroid Build Coastguard Worker     let irqs = [13, 14, 11, 10];
227*bb4ee6a4SAndroid Build Coastguard Worker     let compatible = "arm,armv8-timer";
228*bb4ee6a4SAndroid Build Coastguard Worker     let cpu_mask: u32 =
229*bb4ee6a4SAndroid Build Coastguard Worker         (((1 << num_cpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) & GIC_FDT_IRQ_PPI_CPU_MASK;
230*bb4ee6a4SAndroid Build Coastguard Worker 
231*bb4ee6a4SAndroid Build Coastguard Worker     let mut timer_reg_cells = Vec::new();
232*bb4ee6a4SAndroid Build Coastguard Worker     for &irq in &irqs {
233*bb4ee6a4SAndroid Build Coastguard Worker         timer_reg_cells.push(GIC_FDT_IRQ_TYPE_PPI);
234*bb4ee6a4SAndroid Build Coastguard Worker         timer_reg_cells.push(irq);
235*bb4ee6a4SAndroid Build Coastguard Worker         timer_reg_cells.push(cpu_mask | IRQ_TYPE_LEVEL_LOW);
236*bb4ee6a4SAndroid Build Coastguard Worker     }
237*bb4ee6a4SAndroid Build Coastguard Worker 
238*bb4ee6a4SAndroid Build Coastguard Worker     let timer_node = fdt.root_mut().subnode_mut("timer")?;
239*bb4ee6a4SAndroid Build Coastguard Worker     timer_node.set_prop("compatible", compatible)?;
240*bb4ee6a4SAndroid Build Coastguard Worker     timer_node.set_prop("interrupts", timer_reg_cells)?;
241*bb4ee6a4SAndroid Build Coastguard Worker     timer_node.set_prop("always-on", ())?;
242*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
243*bb4ee6a4SAndroid Build Coastguard Worker }
244*bb4ee6a4SAndroid Build Coastguard Worker 
create_virt_cpufreq_node(fdt: &mut Fdt, num_cpus: u64) -> Result<()>245*bb4ee6a4SAndroid Build Coastguard Worker fn create_virt_cpufreq_node(fdt: &mut Fdt, num_cpus: u64) -> Result<()> {
246*bb4ee6a4SAndroid Build Coastguard Worker     let compatible = "virtual,android-v-only-cpufreq";
247*bb4ee6a4SAndroid Build Coastguard Worker     let vcf_node = fdt.root_mut().subnode_mut("cpufreq")?;
248*bb4ee6a4SAndroid Build Coastguard Worker     let reg = [AARCH64_VIRTFREQ_BASE, AARCH64_VIRTFREQ_SIZE * num_cpus];
249*bb4ee6a4SAndroid Build Coastguard Worker 
250*bb4ee6a4SAndroid Build Coastguard Worker     vcf_node.set_prop("compatible", compatible)?;
251*bb4ee6a4SAndroid Build Coastguard Worker     vcf_node.set_prop("reg", &reg)?;
252*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
253*bb4ee6a4SAndroid Build Coastguard Worker }
254*bb4ee6a4SAndroid Build Coastguard Worker 
create_virt_cpufreq_v2_node(fdt: &mut Fdt, num_cpus: u64) -> Result<()>255*bb4ee6a4SAndroid Build Coastguard Worker fn create_virt_cpufreq_v2_node(fdt: &mut Fdt, num_cpus: u64) -> Result<()> {
256*bb4ee6a4SAndroid Build Coastguard Worker     let compatible = "qemu,virtual-cpufreq";
257*bb4ee6a4SAndroid Build Coastguard Worker     let vcf_node = fdt.root_mut().subnode_mut("cpufreq")?;
258*bb4ee6a4SAndroid Build Coastguard Worker     let reg = [AARCH64_VIRTFREQ_BASE, AARCH64_VIRTFREQ_V2_SIZE * num_cpus];
259*bb4ee6a4SAndroid Build Coastguard Worker 
260*bb4ee6a4SAndroid Build Coastguard Worker     vcf_node.set_prop("compatible", compatible)?;
261*bb4ee6a4SAndroid Build Coastguard Worker     vcf_node.set_prop("reg", &reg)?;
262*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
263*bb4ee6a4SAndroid Build Coastguard Worker }
264*bb4ee6a4SAndroid Build Coastguard Worker 
create_pmu_node(fdt: &mut Fdt, num_cpus: u32) -> Result<()>265*bb4ee6a4SAndroid Build Coastguard Worker fn create_pmu_node(fdt: &mut Fdt, num_cpus: u32) -> Result<()> {
266*bb4ee6a4SAndroid Build Coastguard Worker     let compatible = "arm,armv8-pmuv3";
267*bb4ee6a4SAndroid Build Coastguard Worker     let cpu_mask: u32 =
268*bb4ee6a4SAndroid Build Coastguard Worker         (((1 << num_cpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) & GIC_FDT_IRQ_PPI_CPU_MASK;
269*bb4ee6a4SAndroid Build Coastguard Worker     let irq = [
270*bb4ee6a4SAndroid Build Coastguard Worker         GIC_FDT_IRQ_TYPE_PPI,
271*bb4ee6a4SAndroid Build Coastguard Worker         AARCH64_PMU_IRQ,
272*bb4ee6a4SAndroid Build Coastguard Worker         cpu_mask | IRQ_TYPE_LEVEL_HIGH,
273*bb4ee6a4SAndroid Build Coastguard Worker     ];
274*bb4ee6a4SAndroid Build Coastguard Worker 
275*bb4ee6a4SAndroid Build Coastguard Worker     let pmu_node = fdt.root_mut().subnode_mut("pmu")?;
276*bb4ee6a4SAndroid Build Coastguard Worker     pmu_node.set_prop("compatible", compatible)?;
277*bb4ee6a4SAndroid Build Coastguard Worker     pmu_node.set_prop("interrupts", &irq)?;
278*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
279*bb4ee6a4SAndroid Build Coastguard Worker }
280*bb4ee6a4SAndroid Build Coastguard Worker 
create_serial_node(fdt: &mut Fdt, addr: u64, size: u64, irq: u32) -> Result<()>281*bb4ee6a4SAndroid Build Coastguard Worker fn create_serial_node(fdt: &mut Fdt, addr: u64, size: u64, irq: u32) -> Result<()> {
282*bb4ee6a4SAndroid Build Coastguard Worker     let serial_reg_prop = [addr, size];
283*bb4ee6a4SAndroid Build Coastguard Worker     let irq = [GIC_FDT_IRQ_TYPE_SPI, irq, IRQ_TYPE_EDGE_RISING];
284*bb4ee6a4SAndroid Build Coastguard Worker 
285*bb4ee6a4SAndroid Build Coastguard Worker     let serial_node = fdt
286*bb4ee6a4SAndroid Build Coastguard Worker         .root_mut()
287*bb4ee6a4SAndroid Build Coastguard Worker         .subnode_mut(&format!("U6_16550A@{:x}", addr))?;
288*bb4ee6a4SAndroid Build Coastguard Worker     serial_node.set_prop("compatible", "ns16550a")?;
289*bb4ee6a4SAndroid Build Coastguard Worker     serial_node.set_prop("reg", &serial_reg_prop)?;
290*bb4ee6a4SAndroid Build Coastguard Worker     serial_node.set_prop("clock-frequency", AARCH64_SERIAL_SPEED)?;
291*bb4ee6a4SAndroid Build Coastguard Worker     serial_node.set_prop("interrupts", &irq)?;
292*bb4ee6a4SAndroid Build Coastguard Worker 
293*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
294*bb4ee6a4SAndroid Build Coastguard Worker }
295*bb4ee6a4SAndroid Build Coastguard Worker 
create_serial_nodes(fdt: &mut Fdt, serial_devices: &[SerialDeviceInfo]) -> Result<()>296*bb4ee6a4SAndroid Build Coastguard Worker fn create_serial_nodes(fdt: &mut Fdt, serial_devices: &[SerialDeviceInfo]) -> Result<()> {
297*bb4ee6a4SAndroid Build Coastguard Worker     for dev in serial_devices {
298*bb4ee6a4SAndroid Build Coastguard Worker         create_serial_node(fdt, dev.address, dev.size, dev.irq)?;
299*bb4ee6a4SAndroid Build Coastguard Worker     }
300*bb4ee6a4SAndroid Build Coastguard Worker 
301*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
302*bb4ee6a4SAndroid Build Coastguard Worker }
303*bb4ee6a4SAndroid Build Coastguard Worker 
psci_compatible(version: &PsciVersion) -> Vec<&str>304*bb4ee6a4SAndroid Build Coastguard Worker fn psci_compatible(version: &PsciVersion) -> Vec<&str> {
305*bb4ee6a4SAndroid Build Coastguard Worker     // The PSCI kernel driver only supports compatible strings for the following
306*bb4ee6a4SAndroid Build Coastguard Worker     // backward-compatible versions.
307*bb4ee6a4SAndroid Build Coastguard Worker     let supported = [(PSCI_1_0, "arm,psci-1.0"), (PSCI_0_2, "arm,psci-0.2")];
308*bb4ee6a4SAndroid Build Coastguard Worker 
309*bb4ee6a4SAndroid Build Coastguard Worker     let mut compatible: Vec<_> = supported
310*bb4ee6a4SAndroid Build Coastguard Worker         .iter()
311*bb4ee6a4SAndroid Build Coastguard Worker         .filter(|&(v, _)| *version >= *v)
312*bb4ee6a4SAndroid Build Coastguard Worker         .map(|&(_, c)| c)
313*bb4ee6a4SAndroid Build Coastguard Worker         .collect();
314*bb4ee6a4SAndroid Build Coastguard Worker 
315*bb4ee6a4SAndroid Build Coastguard Worker     // The PSCI kernel driver also supports PSCI v0.1, which is NOT forward-compatible.
316*bb4ee6a4SAndroid Build Coastguard Worker     if compatible.is_empty() {
317*bb4ee6a4SAndroid Build Coastguard Worker         compatible = vec!["arm,psci"];
318*bb4ee6a4SAndroid Build Coastguard Worker     }
319*bb4ee6a4SAndroid Build Coastguard Worker 
320*bb4ee6a4SAndroid Build Coastguard Worker     compatible
321*bb4ee6a4SAndroid Build Coastguard Worker }
322*bb4ee6a4SAndroid Build Coastguard Worker 
create_psci_node(fdt: &mut Fdt, version: &PsciVersion) -> Result<()>323*bb4ee6a4SAndroid Build Coastguard Worker fn create_psci_node(fdt: &mut Fdt, version: &PsciVersion) -> Result<()> {
324*bb4ee6a4SAndroid Build Coastguard Worker     let compatible = psci_compatible(version);
325*bb4ee6a4SAndroid Build Coastguard Worker     let psci_node = fdt.root_mut().subnode_mut("psci")?;
326*bb4ee6a4SAndroid Build Coastguard Worker     psci_node.set_prop("compatible", compatible.as_slice())?;
327*bb4ee6a4SAndroid Build Coastguard Worker     // Only support aarch64 guest
328*bb4ee6a4SAndroid Build Coastguard Worker     psci_node.set_prop("method", "hvc")?;
329*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
330*bb4ee6a4SAndroid Build Coastguard Worker }
331*bb4ee6a4SAndroid Build Coastguard Worker 
create_chosen_node( fdt: &mut Fdt, cmdline: &str, initrd: Option<(GuestAddress, usize)>, stdout_path: Option<&str>, ) -> Result<()>332*bb4ee6a4SAndroid Build Coastguard Worker fn create_chosen_node(
333*bb4ee6a4SAndroid Build Coastguard Worker     fdt: &mut Fdt,
334*bb4ee6a4SAndroid Build Coastguard Worker     cmdline: &str,
335*bb4ee6a4SAndroid Build Coastguard Worker     initrd: Option<(GuestAddress, usize)>,
336*bb4ee6a4SAndroid Build Coastguard Worker     stdout_path: Option<&str>,
337*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
338*bb4ee6a4SAndroid Build Coastguard Worker     let chosen_node = fdt.root_mut().subnode_mut("chosen")?;
339*bb4ee6a4SAndroid Build Coastguard Worker     chosen_node.set_prop("linux,pci-probe-only", 1u32)?;
340*bb4ee6a4SAndroid Build Coastguard Worker     chosen_node.set_prop("bootargs", cmdline)?;
341*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(stdout_path) = stdout_path {
342*bb4ee6a4SAndroid Build Coastguard Worker         // Used by android bootloader for boot console output
343*bb4ee6a4SAndroid Build Coastguard Worker         chosen_node.set_prop("stdout-path", stdout_path)?;
344*bb4ee6a4SAndroid Build Coastguard Worker     }
345*bb4ee6a4SAndroid Build Coastguard Worker 
346*bb4ee6a4SAndroid Build Coastguard Worker     let mut kaslr_seed_bytes = [0u8; 8];
347*bb4ee6a4SAndroid Build Coastguard Worker     OsRng.fill_bytes(&mut kaslr_seed_bytes);
348*bb4ee6a4SAndroid Build Coastguard Worker     let kaslr_seed = u64::from_le_bytes(kaslr_seed_bytes);
349*bb4ee6a4SAndroid Build Coastguard Worker     chosen_node.set_prop("kaslr-seed", kaslr_seed)?;
350*bb4ee6a4SAndroid Build Coastguard Worker 
351*bb4ee6a4SAndroid Build Coastguard Worker     let mut rng_seed_bytes = [0u8; 256];
352*bb4ee6a4SAndroid Build Coastguard Worker     OsRng.fill_bytes(&mut rng_seed_bytes);
353*bb4ee6a4SAndroid Build Coastguard Worker     chosen_node.set_prop("rng-seed", &rng_seed_bytes)?;
354*bb4ee6a4SAndroid Build Coastguard Worker 
355*bb4ee6a4SAndroid Build Coastguard Worker     if let Some((initrd_addr, initrd_size)) = initrd {
356*bb4ee6a4SAndroid Build Coastguard Worker         let initrd_start = initrd_addr.offset() as u32;
357*bb4ee6a4SAndroid Build Coastguard Worker         let initrd_end = initrd_start + initrd_size as u32;
358*bb4ee6a4SAndroid Build Coastguard Worker         chosen_node.set_prop("linux,initrd-start", initrd_start)?;
359*bb4ee6a4SAndroid Build Coastguard Worker         chosen_node.set_prop("linux,initrd-end", initrd_end)?;
360*bb4ee6a4SAndroid Build Coastguard Worker     }
361*bb4ee6a4SAndroid Build Coastguard Worker 
362*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
363*bb4ee6a4SAndroid Build Coastguard Worker }
364*bb4ee6a4SAndroid Build Coastguard Worker 
create_config_node(fdt: &mut Fdt, (addr, size): (GuestAddress, usize)) -> Result<()>365*bb4ee6a4SAndroid Build Coastguard Worker fn create_config_node(fdt: &mut Fdt, (addr, size): (GuestAddress, usize)) -> Result<()> {
366*bb4ee6a4SAndroid Build Coastguard Worker     let addr: u32 = addr
367*bb4ee6a4SAndroid Build Coastguard Worker         .offset()
368*bb4ee6a4SAndroid Build Coastguard Worker         .try_into()
369*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| Error::PropertyValueTooLarge)?;
370*bb4ee6a4SAndroid Build Coastguard Worker     let size: u32 = size.try_into().map_err(|_| Error::PropertyValueTooLarge)?;
371*bb4ee6a4SAndroid Build Coastguard Worker 
372*bb4ee6a4SAndroid Build Coastguard Worker     let config_node = fdt.root_mut().subnode_mut("config")?;
373*bb4ee6a4SAndroid Build Coastguard Worker     config_node.set_prop("kernel-address", addr)?;
374*bb4ee6a4SAndroid Build Coastguard Worker     config_node.set_prop("kernel-size", size)?;
375*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
376*bb4ee6a4SAndroid Build Coastguard Worker }
377*bb4ee6a4SAndroid Build Coastguard Worker 
create_kvm_cpufreq_node(fdt: &mut Fdt) -> Result<()>378*bb4ee6a4SAndroid Build Coastguard Worker fn create_kvm_cpufreq_node(fdt: &mut Fdt) -> Result<()> {
379*bb4ee6a4SAndroid Build Coastguard Worker     let vcf_node = fdt.root_mut().subnode_mut("cpufreq")?;
380*bb4ee6a4SAndroid Build Coastguard Worker     vcf_node.set_prop("compatible", "virtual,kvm-cpufreq")?;
381*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
382*bb4ee6a4SAndroid Build Coastguard Worker }
383*bb4ee6a4SAndroid Build Coastguard Worker 
384*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
get_pkvm_pviommu_ids(platform_dev_resources: &Vec<PlatformBusResources>) -> Result<Vec<u32>>385*bb4ee6a4SAndroid Build Coastguard Worker fn get_pkvm_pviommu_ids(platform_dev_resources: &Vec<PlatformBusResources>) -> Result<Vec<u32>> {
386*bb4ee6a4SAndroid Build Coastguard Worker     let mut ids = HashSet::new();
387*bb4ee6a4SAndroid Build Coastguard Worker 
388*bb4ee6a4SAndroid Build Coastguard Worker     for res in platform_dev_resources {
389*bb4ee6a4SAndroid Build Coastguard Worker         for iommu in &res.iommus {
390*bb4ee6a4SAndroid Build Coastguard Worker             if let (IommuDevType::PkvmPviommu, Some(id), _) = iommu {
391*bb4ee6a4SAndroid Build Coastguard Worker                 ids.insert(*id);
392*bb4ee6a4SAndroid Build Coastguard Worker             }
393*bb4ee6a4SAndroid Build Coastguard Worker         }
394*bb4ee6a4SAndroid Build Coastguard Worker     }
395*bb4ee6a4SAndroid Build Coastguard Worker 
396*bb4ee6a4SAndroid Build Coastguard Worker     Ok(Vec::from_iter(ids))
397*bb4ee6a4SAndroid Build Coastguard Worker }
398*bb4ee6a4SAndroid Build Coastguard Worker 
create_pkvm_pviommu_node(fdt: &mut Fdt, index: usize, id: u32) -> Result<u32>399*bb4ee6a4SAndroid Build Coastguard Worker fn create_pkvm_pviommu_node(fdt: &mut Fdt, index: usize, id: u32) -> Result<u32> {
400*bb4ee6a4SAndroid Build Coastguard Worker     let name = format!("pviommu{index}");
401*bb4ee6a4SAndroid Build Coastguard Worker     let phandle = PHANDLE_PKVM_PVIOMMU
402*bb4ee6a4SAndroid Build Coastguard Worker         .checked_add(index.try_into().unwrap())
403*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
404*bb4ee6a4SAndroid Build Coastguard Worker 
405*bb4ee6a4SAndroid Build Coastguard Worker     let iommu_node = fdt.root_mut().subnode_mut(&name)?;
406*bb4ee6a4SAndroid Build Coastguard Worker     iommu_node.set_prop("phandle", phandle)?;
407*bb4ee6a4SAndroid Build Coastguard Worker     iommu_node.set_prop("#iommu-cells", 1u32)?;
408*bb4ee6a4SAndroid Build Coastguard Worker     iommu_node.set_prop("compatible", "pkvm,pviommu")?;
409*bb4ee6a4SAndroid Build Coastguard Worker     iommu_node.set_prop("id", id)?;
410*bb4ee6a4SAndroid Build Coastguard Worker 
411*bb4ee6a4SAndroid Build Coastguard Worker     Ok(phandle)
412*bb4ee6a4SAndroid Build Coastguard Worker }
413*bb4ee6a4SAndroid Build Coastguard Worker 
414*bb4ee6a4SAndroid Build Coastguard Worker /// PCI host controller address range.
415*bb4ee6a4SAndroid Build Coastguard Worker ///
416*bb4ee6a4SAndroid Build Coastguard Worker /// This represents a single entry in the "ranges" property for a PCI host controller.
417*bb4ee6a4SAndroid Build Coastguard Worker ///
418*bb4ee6a4SAndroid Build Coastguard Worker /// See [PCI Bus Binding to Open Firmware](https://www.openfirmware.info/data/docs/bus.pci.pdf)
419*bb4ee6a4SAndroid Build Coastguard Worker /// and https://www.kernel.org/doc/Documentation/devicetree/bindings/pci/host-generic-pci.txt
420*bb4ee6a4SAndroid Build Coastguard Worker /// for more information.
421*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
422*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciRange {
423*bb4ee6a4SAndroid Build Coastguard Worker     pub space: PciAddressSpace,
424*bb4ee6a4SAndroid Build Coastguard Worker     pub bus_address: u64,
425*bb4ee6a4SAndroid Build Coastguard Worker     pub cpu_physical_address: u64,
426*bb4ee6a4SAndroid Build Coastguard Worker     pub size: u64,
427*bb4ee6a4SAndroid Build Coastguard Worker     pub prefetchable: bool,
428*bb4ee6a4SAndroid Build Coastguard Worker }
429*bb4ee6a4SAndroid Build Coastguard Worker 
430*bb4ee6a4SAndroid Build Coastguard Worker /// PCI address space.
431*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
432*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
433*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciAddressSpace {
434*bb4ee6a4SAndroid Build Coastguard Worker     /// PCI configuration space
435*bb4ee6a4SAndroid Build Coastguard Worker     Configuration = 0b00,
436*bb4ee6a4SAndroid Build Coastguard Worker     /// I/O space
437*bb4ee6a4SAndroid Build Coastguard Worker     Io = 0b01,
438*bb4ee6a4SAndroid Build Coastguard Worker     /// 32-bit memory space
439*bb4ee6a4SAndroid Build Coastguard Worker     Memory = 0b10,
440*bb4ee6a4SAndroid Build Coastguard Worker     /// 64-bit memory space
441*bb4ee6a4SAndroid Build Coastguard Worker     Memory64 = 0b11,
442*bb4ee6a4SAndroid Build Coastguard Worker }
443*bb4ee6a4SAndroid Build Coastguard Worker 
444*bb4ee6a4SAndroid Build Coastguard Worker /// Location of memory-mapped PCI configuration space.
445*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
446*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciConfigRegion {
447*bb4ee6a4SAndroid Build Coastguard Worker     /// Physical address of the base of the memory-mapped PCI configuration region.
448*bb4ee6a4SAndroid Build Coastguard Worker     pub base: u64,
449*bb4ee6a4SAndroid Build Coastguard Worker     /// Size of the PCI configuration region in bytes.
450*bb4ee6a4SAndroid Build Coastguard Worker     pub size: u64,
451*bb4ee6a4SAndroid Build Coastguard Worker }
452*bb4ee6a4SAndroid Build Coastguard Worker 
453*bb4ee6a4SAndroid Build Coastguard Worker /// Location of memory-mapped vm watchdog
454*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
455*bb4ee6a4SAndroid Build Coastguard Worker pub struct VmWdtConfig {
456*bb4ee6a4SAndroid Build Coastguard Worker     /// Physical address of the base of the memory-mapped vm watchdog region.
457*bb4ee6a4SAndroid Build Coastguard Worker     pub base: u64,
458*bb4ee6a4SAndroid Build Coastguard Worker     /// Size of the vm watchdog region in bytes.
459*bb4ee6a4SAndroid Build Coastguard Worker     pub size: u64,
460*bb4ee6a4SAndroid Build Coastguard Worker     /// The internal clock frequency of the watchdog.
461*bb4ee6a4SAndroid Build Coastguard Worker     pub clock_hz: u32,
462*bb4ee6a4SAndroid Build Coastguard Worker     /// The expiration timeout measured in seconds.
463*bb4ee6a4SAndroid Build Coastguard Worker     pub timeout_sec: u32,
464*bb4ee6a4SAndroid Build Coastguard Worker }
465*bb4ee6a4SAndroid Build Coastguard Worker 
create_pci_nodes( fdt: &mut Fdt, pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>, cfg: PciConfigRegion, ranges: &[PciRange], dma_pool_phandle: Option<u32>, ) -> Result<()>466*bb4ee6a4SAndroid Build Coastguard Worker fn create_pci_nodes(
467*bb4ee6a4SAndroid Build Coastguard Worker     fdt: &mut Fdt,
468*bb4ee6a4SAndroid Build Coastguard Worker     pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>,
469*bb4ee6a4SAndroid Build Coastguard Worker     cfg: PciConfigRegion,
470*bb4ee6a4SAndroid Build Coastguard Worker     ranges: &[PciRange],
471*bb4ee6a4SAndroid Build Coastguard Worker     dma_pool_phandle: Option<u32>,
472*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
473*bb4ee6a4SAndroid Build Coastguard Worker     // Add devicetree nodes describing a PCI generic host controller.
474*bb4ee6a4SAndroid Build Coastguard Worker     // See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
475*bb4ee6a4SAndroid Build Coastguard Worker     // and "PCI Bus Binding to IEEE Std 1275-1994".
476*bb4ee6a4SAndroid Build Coastguard Worker     let ranges: Vec<u32> = ranges
477*bb4ee6a4SAndroid Build Coastguard Worker         .iter()
478*bb4ee6a4SAndroid Build Coastguard Worker         .flat_map(|r| {
479*bb4ee6a4SAndroid Build Coastguard Worker             let ss = r.space as u32;
480*bb4ee6a4SAndroid Build Coastguard Worker             let p = r.prefetchable as u32;
481*bb4ee6a4SAndroid Build Coastguard Worker             [
482*bb4ee6a4SAndroid Build Coastguard Worker                 // BUS_ADDRESS(3) encoded as defined in OF PCI Bus Binding
483*bb4ee6a4SAndroid Build Coastguard Worker                 (ss << 24) | (p << 30),
484*bb4ee6a4SAndroid Build Coastguard Worker                 (r.bus_address >> 32) as u32,
485*bb4ee6a4SAndroid Build Coastguard Worker                 r.bus_address as u32,
486*bb4ee6a4SAndroid Build Coastguard Worker                 // CPU_PHYSICAL(2)
487*bb4ee6a4SAndroid Build Coastguard Worker                 (r.cpu_physical_address >> 32) as u32,
488*bb4ee6a4SAndroid Build Coastguard Worker                 r.cpu_physical_address as u32,
489*bb4ee6a4SAndroid Build Coastguard Worker                 // SIZE(2)
490*bb4ee6a4SAndroid Build Coastguard Worker                 (r.size >> 32) as u32,
491*bb4ee6a4SAndroid Build Coastguard Worker                 r.size as u32,
492*bb4ee6a4SAndroid Build Coastguard Worker             ]
493*bb4ee6a4SAndroid Build Coastguard Worker         })
494*bb4ee6a4SAndroid Build Coastguard Worker         .collect();
495*bb4ee6a4SAndroid Build Coastguard Worker 
496*bb4ee6a4SAndroid Build Coastguard Worker     let bus_range = [0u32, 0u32]; // Only bus 0
497*bb4ee6a4SAndroid Build Coastguard Worker     let reg = [cfg.base, cfg.size];
498*bb4ee6a4SAndroid Build Coastguard Worker 
499*bb4ee6a4SAndroid Build Coastguard Worker     let mut interrupts: Vec<u32> = Vec::new();
500*bb4ee6a4SAndroid Build Coastguard Worker     let mut masks: Vec<u32> = Vec::new();
501*bb4ee6a4SAndroid Build Coastguard Worker 
502*bb4ee6a4SAndroid Build Coastguard Worker     for (address, irq_num, irq_pin) in pci_irqs.iter() {
503*bb4ee6a4SAndroid Build Coastguard Worker         // PCI_DEVICE(3)
504*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(address.to_config_address(0, 8));
505*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(0);
506*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(0);
507*bb4ee6a4SAndroid Build Coastguard Worker 
508*bb4ee6a4SAndroid Build Coastguard Worker         // INT#(1)
509*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(irq_pin.to_mask() + 1);
510*bb4ee6a4SAndroid Build Coastguard Worker 
511*bb4ee6a4SAndroid Build Coastguard Worker         // CONTROLLER(PHANDLE)
512*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(PHANDLE_GIC);
513*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(0);
514*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(0);
515*bb4ee6a4SAndroid Build Coastguard Worker 
516*bb4ee6a4SAndroid Build Coastguard Worker         // CONTROLLER_DATA(3)
517*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(GIC_FDT_IRQ_TYPE_SPI);
518*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(*irq_num);
519*bb4ee6a4SAndroid Build Coastguard Worker         interrupts.push(IRQ_TYPE_LEVEL_HIGH);
520*bb4ee6a4SAndroid Build Coastguard Worker 
521*bb4ee6a4SAndroid Build Coastguard Worker         // PCI_DEVICE(3)
522*bb4ee6a4SAndroid Build Coastguard Worker         masks.push(0xf800); // bits 11..15 (device)
523*bb4ee6a4SAndroid Build Coastguard Worker         masks.push(0);
524*bb4ee6a4SAndroid Build Coastguard Worker         masks.push(0);
525*bb4ee6a4SAndroid Build Coastguard Worker 
526*bb4ee6a4SAndroid Build Coastguard Worker         // INT#(1)
527*bb4ee6a4SAndroid Build Coastguard Worker         masks.push(0x7); // allow INTA#-INTD# (1 | 2 | 3 | 4)
528*bb4ee6a4SAndroid Build Coastguard Worker     }
529*bb4ee6a4SAndroid Build Coastguard Worker 
530*bb4ee6a4SAndroid Build Coastguard Worker     let pci_node = fdt.root_mut().subnode_mut("pci")?;
531*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("compatible", "pci-host-cam-generic")?;
532*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("device_type", "pci")?;
533*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("ranges", ranges)?;
534*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("bus-range", &bus_range)?;
535*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("#address-cells", 3u32)?;
536*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("#size-cells", 2u32)?;
537*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("reg", &reg)?;
538*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("#interrupt-cells", 1u32)?;
539*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("interrupt-map", interrupts)?;
540*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("interrupt-map-mask", masks)?;
541*bb4ee6a4SAndroid Build Coastguard Worker     pci_node.set_prop("dma-coherent", ())?;
542*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(dma_pool_phandle) = dma_pool_phandle {
543*bb4ee6a4SAndroid Build Coastguard Worker         pci_node.set_prop("memory-region", dma_pool_phandle)?;
544*bb4ee6a4SAndroid Build Coastguard Worker     }
545*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
546*bb4ee6a4SAndroid Build Coastguard Worker }
547*bb4ee6a4SAndroid Build Coastguard Worker 
create_rtc_node(fdt: &mut Fdt) -> Result<()>548*bb4ee6a4SAndroid Build Coastguard Worker fn create_rtc_node(fdt: &mut Fdt) -> Result<()> {
549*bb4ee6a4SAndroid Build Coastguard Worker     // the kernel driver for pl030 really really wants a clock node
550*bb4ee6a4SAndroid Build Coastguard Worker     // associated with an AMBA device or it will fail to probe, so we
551*bb4ee6a4SAndroid Build Coastguard Worker     // need to make up a clock node to associate with the pl030 rtc
552*bb4ee6a4SAndroid Build Coastguard Worker     // node and an associated handle with a unique phandle value.
553*bb4ee6a4SAndroid Build Coastguard Worker     const CLK_PHANDLE: u32 = 24;
554*bb4ee6a4SAndroid Build Coastguard Worker     let clock_node = fdt.root_mut().subnode_mut("pclk@3M")?;
555*bb4ee6a4SAndroid Build Coastguard Worker     clock_node.set_prop("#clock-cells", 0u32)?;
556*bb4ee6a4SAndroid Build Coastguard Worker     clock_node.set_prop("compatible", "fixed-clock")?;
557*bb4ee6a4SAndroid Build Coastguard Worker     clock_node.set_prop("clock-frequency", 3141592u32)?;
558*bb4ee6a4SAndroid Build Coastguard Worker     clock_node.set_prop("phandle", CLK_PHANDLE)?;
559*bb4ee6a4SAndroid Build Coastguard Worker 
560*bb4ee6a4SAndroid Build Coastguard Worker     let rtc_name = format!("rtc@{:x}", AARCH64_RTC_ADDR);
561*bb4ee6a4SAndroid Build Coastguard Worker     let reg = [AARCH64_RTC_ADDR, AARCH64_RTC_SIZE];
562*bb4ee6a4SAndroid Build Coastguard Worker     let irq = [GIC_FDT_IRQ_TYPE_SPI, AARCH64_RTC_IRQ, IRQ_TYPE_LEVEL_HIGH];
563*bb4ee6a4SAndroid Build Coastguard Worker 
564*bb4ee6a4SAndroid Build Coastguard Worker     let rtc_node = fdt.root_mut().subnode_mut(&rtc_name)?;
565*bb4ee6a4SAndroid Build Coastguard Worker     rtc_node.set_prop("compatible", "arm,primecell")?;
566*bb4ee6a4SAndroid Build Coastguard Worker     rtc_node.set_prop("arm,primecell-periphid", PL030_AMBA_ID)?;
567*bb4ee6a4SAndroid Build Coastguard Worker     rtc_node.set_prop("reg", &reg)?;
568*bb4ee6a4SAndroid Build Coastguard Worker     rtc_node.set_prop("interrupts", &irq)?;
569*bb4ee6a4SAndroid Build Coastguard Worker     rtc_node.set_prop("clocks", CLK_PHANDLE)?;
570*bb4ee6a4SAndroid Build Coastguard Worker     rtc_node.set_prop("clock-names", "apb_pclk")?;
571*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
572*bb4ee6a4SAndroid Build Coastguard Worker }
573*bb4ee6a4SAndroid Build Coastguard Worker 
574*bb4ee6a4SAndroid Build Coastguard Worker /// Create a flattened device tree node for Goldfish Battery device.
575*bb4ee6a4SAndroid Build Coastguard Worker ///
576*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
577*bb4ee6a4SAndroid Build Coastguard Worker ///
578*bb4ee6a4SAndroid Build Coastguard Worker /// * `fdt` - An Fdt in which the node is created
579*bb4ee6a4SAndroid Build Coastguard Worker /// * `mmio_base` - The MMIO base address of the battery
580*bb4ee6a4SAndroid Build Coastguard Worker /// * `irq` - The IRQ number of the battery
create_battery_node(fdt: &mut Fdt, mmio_base: u64, irq: u32) -> Result<()>581*bb4ee6a4SAndroid Build Coastguard Worker fn create_battery_node(fdt: &mut Fdt, mmio_base: u64, irq: u32) -> Result<()> {
582*bb4ee6a4SAndroid Build Coastguard Worker     let reg = [mmio_base, GOLDFISHBAT_MMIO_LEN];
583*bb4ee6a4SAndroid Build Coastguard Worker     let irqs = [GIC_FDT_IRQ_TYPE_SPI, irq, IRQ_TYPE_LEVEL_HIGH];
584*bb4ee6a4SAndroid Build Coastguard Worker     let bat_node = fdt.root_mut().subnode_mut("goldfish_battery")?;
585*bb4ee6a4SAndroid Build Coastguard Worker     bat_node.set_prop("compatible", "google,goldfish-battery")?;
586*bb4ee6a4SAndroid Build Coastguard Worker     bat_node.set_prop("reg", &reg)?;
587*bb4ee6a4SAndroid Build Coastguard Worker     bat_node.set_prop("interrupts", &irqs)?;
588*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
589*bb4ee6a4SAndroid Build Coastguard Worker }
590*bb4ee6a4SAndroid Build Coastguard Worker 
create_vmwdt_node(fdt: &mut Fdt, vmwdt_cfg: VmWdtConfig, num_cpus: u32) -> Result<()>591*bb4ee6a4SAndroid Build Coastguard Worker fn create_vmwdt_node(fdt: &mut Fdt, vmwdt_cfg: VmWdtConfig, num_cpus: u32) -> Result<()> {
592*bb4ee6a4SAndroid Build Coastguard Worker     let vmwdt_name = format!("vmwdt@{:x}", vmwdt_cfg.base);
593*bb4ee6a4SAndroid Build Coastguard Worker     let reg = [vmwdt_cfg.base, vmwdt_cfg.size];
594*bb4ee6a4SAndroid Build Coastguard Worker     let cpu_mask: u32 =
595*bb4ee6a4SAndroid Build Coastguard Worker         (((1 << num_cpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) & GIC_FDT_IRQ_PPI_CPU_MASK;
596*bb4ee6a4SAndroid Build Coastguard Worker     let irq = [
597*bb4ee6a4SAndroid Build Coastguard Worker         GIC_FDT_IRQ_TYPE_PPI,
598*bb4ee6a4SAndroid Build Coastguard Worker         AARCH64_VMWDT_IRQ,
599*bb4ee6a4SAndroid Build Coastguard Worker         cpu_mask | IRQ_TYPE_EDGE_RISING,
600*bb4ee6a4SAndroid Build Coastguard Worker     ];
601*bb4ee6a4SAndroid Build Coastguard Worker 
602*bb4ee6a4SAndroid Build Coastguard Worker     let vmwdt_node = fdt.root_mut().subnode_mut(&vmwdt_name)?;
603*bb4ee6a4SAndroid Build Coastguard Worker     vmwdt_node.set_prop("compatible", "qemu,vcpu-stall-detector")?;
604*bb4ee6a4SAndroid Build Coastguard Worker     vmwdt_node.set_prop("reg", &reg)?;
605*bb4ee6a4SAndroid Build Coastguard Worker     vmwdt_node.set_prop("clock-frequency", vmwdt_cfg.clock_hz)?;
606*bb4ee6a4SAndroid Build Coastguard Worker     vmwdt_node.set_prop("timeout-sec", vmwdt_cfg.timeout_sec)?;
607*bb4ee6a4SAndroid Build Coastguard Worker     vmwdt_node.set_prop("interrupts", &irq)?;
608*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
609*bb4ee6a4SAndroid Build Coastguard Worker }
610*bb4ee6a4SAndroid Build Coastguard Worker 
611*bb4ee6a4SAndroid Build Coastguard Worker // Add a node path to __symbols__ node of the FDT, so it can be referenced by an overlay.
add_symbols_entry(fdt: &mut Fdt, symbol: &str, path: &str) -> Result<()>612*bb4ee6a4SAndroid Build Coastguard Worker fn add_symbols_entry(fdt: &mut Fdt, symbol: &str, path: &str) -> Result<()> {
613*bb4ee6a4SAndroid Build Coastguard Worker     // Ensure the path points to a valid node with a defined phandle
614*bb4ee6a4SAndroid Build Coastguard Worker     let Some(target_node) = fdt.get_node(path) else {
615*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::InvalidPath(format!("{path} does not exist")));
616*bb4ee6a4SAndroid Build Coastguard Worker     };
617*bb4ee6a4SAndroid Build Coastguard Worker     target_node
618*bb4ee6a4SAndroid Build Coastguard Worker         .get_prop::<u32>("phandle")
619*bb4ee6a4SAndroid Build Coastguard Worker         .or_else(|| target_node.get_prop("linux,phandle"))
620*bb4ee6a4SAndroid Build Coastguard Worker         .ok_or_else(|| Error::InvalidPath(format!("{path} must have a phandle")))?;
621*bb4ee6a4SAndroid Build Coastguard Worker     // Add the label -> path mapping.
622*bb4ee6a4SAndroid Build Coastguard Worker     let symbols_node = fdt.root_mut().subnode_mut("__symbols__")?;
623*bb4ee6a4SAndroid Build Coastguard Worker     symbols_node.set_prop(symbol, path)?;
624*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
625*bb4ee6a4SAndroid Build Coastguard Worker }
626*bb4ee6a4SAndroid Build Coastguard Worker 
627*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a flattened device tree containing all of the parameters for the
628*bb4ee6a4SAndroid Build Coastguard Worker /// kernel and loads it into the guest memory at the specified offset.
629*bb4ee6a4SAndroid Build Coastguard Worker ///
630*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
631*bb4ee6a4SAndroid Build Coastguard Worker ///
632*bb4ee6a4SAndroid Build Coastguard Worker /// * `fdt_max_size` - The amount of space reserved for the device tree
633*bb4ee6a4SAndroid Build Coastguard Worker /// * `guest_mem` - The guest memory object
634*bb4ee6a4SAndroid Build Coastguard Worker /// * `pci_irqs` - List of PCI device address to PCI interrupt number and pin mappings
635*bb4ee6a4SAndroid Build Coastguard Worker /// * `pci_cfg` - Location of the memory-mapped PCI configuration space.
636*bb4ee6a4SAndroid Build Coastguard Worker /// * `pci_ranges` - Memory ranges accessible via the PCI host controller.
637*bb4ee6a4SAndroid Build Coastguard Worker /// * `num_cpus` - Number of virtual CPUs the guest will have
638*bb4ee6a4SAndroid Build Coastguard Worker /// * `fdt_address` - The offset into physical memory for the device tree
639*bb4ee6a4SAndroid Build Coastguard Worker /// * `cmdline` - The kernel commandline
640*bb4ee6a4SAndroid Build Coastguard Worker /// * `initrd` - An optional tuple of initrd guest physical address and size
641*bb4ee6a4SAndroid Build Coastguard Worker /// * `android_fstab` - An optional file holding Android fstab entries
642*bb4ee6a4SAndroid Build Coastguard Worker /// * `is_gicv3` - True if gicv3, false if v2
643*bb4ee6a4SAndroid Build Coastguard Worker /// * `psci_version` - the current PSCI version
644*bb4ee6a4SAndroid Build Coastguard Worker /// * `swiotlb` - Reserve a memory pool for DMA. Tuple of base address and size.
645*bb4ee6a4SAndroid Build Coastguard Worker /// * `bat_mmio_base_and_irq` - The battery base address and irq number
646*bb4ee6a4SAndroid Build Coastguard Worker /// * `vmwdt_cfg` - The virtual watchdog configuration
647*bb4ee6a4SAndroid Build Coastguard Worker /// * `dump_device_tree_blob` - Option path to write DTB to
648*bb4ee6a4SAndroid Build Coastguard Worker /// * `vm_generator` - Callback to add additional nodes to DTB. create_vm uses Aarch64Vm::create_fdt
create_fdt( fdt_max_size: usize, guest_mem: &GuestMemory, pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>, pci_cfg: PciConfigRegion, pci_ranges: &[PciRange], #[cfg(any(target_os = "android", target_os = "linux"))] platform_dev_resources: Vec< PlatformBusResources, >, num_cpus: u32, cpu_mpidr_generator: &impl Fn(usize) -> Option<u64>, cpu_clusters: Vec<CpuSet>, cpu_capacity: BTreeMap<usize, u32>, cpu_frequencies: BTreeMap<usize, Vec<u32>>, fdt_address: GuestAddress, cmdline: &str, image: (GuestAddress, usize), initrd: Option<(GuestAddress, usize)>, android_fstab: Option<File>, is_gicv3: bool, use_pmu: bool, psci_version: PsciVersion, swiotlb: Option<(Option<GuestAddress>, u64)>, bat_mmio_base_and_irq: Option<(u64, u32)>, vmwdt_cfg: VmWdtConfig, dump_device_tree_blob: Option<PathBuf>, vm_generator: &impl Fn(&mut Fdt, &BTreeMap<&str, u32>) -> cros_fdt::Result<()>, dynamic_power_coefficient: BTreeMap<usize, u32>, device_tree_overlays: Vec<DtbOverlay>, serial_devices: &[SerialDeviceInfo], virt_cpufreq_v2: bool, ) -> Result<()>649*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_fdt(
650*bb4ee6a4SAndroid Build Coastguard Worker     fdt_max_size: usize,
651*bb4ee6a4SAndroid Build Coastguard Worker     guest_mem: &GuestMemory,
652*bb4ee6a4SAndroid Build Coastguard Worker     pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>,
653*bb4ee6a4SAndroid Build Coastguard Worker     pci_cfg: PciConfigRegion,
654*bb4ee6a4SAndroid Build Coastguard Worker     pci_ranges: &[PciRange],
655*bb4ee6a4SAndroid Build Coastguard Worker     #[cfg(any(target_os = "android", target_os = "linux"))] platform_dev_resources: Vec<
656*bb4ee6a4SAndroid Build Coastguard Worker         PlatformBusResources,
657*bb4ee6a4SAndroid Build Coastguard Worker     >,
658*bb4ee6a4SAndroid Build Coastguard Worker     num_cpus: u32,
659*bb4ee6a4SAndroid Build Coastguard Worker     cpu_mpidr_generator: &impl Fn(usize) -> Option<u64>,
660*bb4ee6a4SAndroid Build Coastguard Worker     cpu_clusters: Vec<CpuSet>,
661*bb4ee6a4SAndroid Build Coastguard Worker     cpu_capacity: BTreeMap<usize, u32>,
662*bb4ee6a4SAndroid Build Coastguard Worker     cpu_frequencies: BTreeMap<usize, Vec<u32>>,
663*bb4ee6a4SAndroid Build Coastguard Worker     fdt_address: GuestAddress,
664*bb4ee6a4SAndroid Build Coastguard Worker     cmdline: &str,
665*bb4ee6a4SAndroid Build Coastguard Worker     image: (GuestAddress, usize),
666*bb4ee6a4SAndroid Build Coastguard Worker     initrd: Option<(GuestAddress, usize)>,
667*bb4ee6a4SAndroid Build Coastguard Worker     android_fstab: Option<File>,
668*bb4ee6a4SAndroid Build Coastguard Worker     is_gicv3: bool,
669*bb4ee6a4SAndroid Build Coastguard Worker     use_pmu: bool,
670*bb4ee6a4SAndroid Build Coastguard Worker     psci_version: PsciVersion,
671*bb4ee6a4SAndroid Build Coastguard Worker     swiotlb: Option<(Option<GuestAddress>, u64)>,
672*bb4ee6a4SAndroid Build Coastguard Worker     bat_mmio_base_and_irq: Option<(u64, u32)>,
673*bb4ee6a4SAndroid Build Coastguard Worker     vmwdt_cfg: VmWdtConfig,
674*bb4ee6a4SAndroid Build Coastguard Worker     dump_device_tree_blob: Option<PathBuf>,
675*bb4ee6a4SAndroid Build Coastguard Worker     vm_generator: &impl Fn(&mut Fdt, &BTreeMap<&str, u32>) -> cros_fdt::Result<()>,
676*bb4ee6a4SAndroid Build Coastguard Worker     dynamic_power_coefficient: BTreeMap<usize, u32>,
677*bb4ee6a4SAndroid Build Coastguard Worker     device_tree_overlays: Vec<DtbOverlay>,
678*bb4ee6a4SAndroid Build Coastguard Worker     serial_devices: &[SerialDeviceInfo],
679*bb4ee6a4SAndroid Build Coastguard Worker     virt_cpufreq_v2: bool,
680*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
681*bb4ee6a4SAndroid Build Coastguard Worker     let mut fdt = Fdt::new(&[]);
682*bb4ee6a4SAndroid Build Coastguard Worker     let mut phandles_key_cache = Vec::new();
683*bb4ee6a4SAndroid Build Coastguard Worker     let mut phandles = BTreeMap::new();
684*bb4ee6a4SAndroid Build Coastguard Worker 
685*bb4ee6a4SAndroid Build Coastguard Worker     // The whole thing is put into one giant node with some top level properties
686*bb4ee6a4SAndroid Build Coastguard Worker     let root_node = fdt.root_mut();
687*bb4ee6a4SAndroid Build Coastguard Worker     root_node.set_prop("interrupt-parent", PHANDLE_GIC)?;
688*bb4ee6a4SAndroid Build Coastguard Worker     phandles.insert("intc", PHANDLE_GIC);
689*bb4ee6a4SAndroid Build Coastguard Worker     root_node.set_prop("compatible", "linux,dummy-virt")?;
690*bb4ee6a4SAndroid Build Coastguard Worker     root_node.set_prop("#address-cells", 0x2u32)?;
691*bb4ee6a4SAndroid Build Coastguard Worker     root_node.set_prop("#size-cells", 0x2u32)?;
692*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(android_fstab) = android_fstab {
693*bb4ee6a4SAndroid Build Coastguard Worker         arch::android::create_android_fdt(&mut fdt, android_fstab)?;
694*bb4ee6a4SAndroid Build Coastguard Worker     }
695*bb4ee6a4SAndroid Build Coastguard Worker     let stdout_path = serial_devices
696*bb4ee6a4SAndroid Build Coastguard Worker         .first()
697*bb4ee6a4SAndroid Build Coastguard Worker         .map(|first_serial| format!("/U6_16550A@{:x}", first_serial.address));
698*bb4ee6a4SAndroid Build Coastguard Worker     create_chosen_node(&mut fdt, cmdline, initrd, stdout_path.as_deref())?;
699*bb4ee6a4SAndroid Build Coastguard Worker     create_config_node(&mut fdt, image)?;
700*bb4ee6a4SAndroid Build Coastguard Worker     create_memory_node(&mut fdt, guest_mem)?;
701*bb4ee6a4SAndroid Build Coastguard Worker     let dma_pool_phandle = match swiotlb {
702*bb4ee6a4SAndroid Build Coastguard Worker         Some(x) => {
703*bb4ee6a4SAndroid Build Coastguard Worker             let phandle = create_resv_memory_node(&mut fdt, x)?;
704*bb4ee6a4SAndroid Build Coastguard Worker             phandles.insert("restricted_dma_reserved", phandle);
705*bb4ee6a4SAndroid Build Coastguard Worker             Some(phandle)
706*bb4ee6a4SAndroid Build Coastguard Worker         }
707*bb4ee6a4SAndroid Build Coastguard Worker         None => None,
708*bb4ee6a4SAndroid Build Coastguard Worker     };
709*bb4ee6a4SAndroid Build Coastguard Worker     create_cpu_nodes(
710*bb4ee6a4SAndroid Build Coastguard Worker         &mut fdt,
711*bb4ee6a4SAndroid Build Coastguard Worker         num_cpus,
712*bb4ee6a4SAndroid Build Coastguard Worker         cpu_mpidr_generator,
713*bb4ee6a4SAndroid Build Coastguard Worker         cpu_clusters,
714*bb4ee6a4SAndroid Build Coastguard Worker         cpu_capacity,
715*bb4ee6a4SAndroid Build Coastguard Worker         dynamic_power_coefficient,
716*bb4ee6a4SAndroid Build Coastguard Worker         cpu_frequencies.clone(),
717*bb4ee6a4SAndroid Build Coastguard Worker     )?;
718*bb4ee6a4SAndroid Build Coastguard Worker     create_gic_node(&mut fdt, is_gicv3, num_cpus as u64)?;
719*bb4ee6a4SAndroid Build Coastguard Worker     create_timer_node(&mut fdt, num_cpus)?;
720*bb4ee6a4SAndroid Build Coastguard Worker     if use_pmu {
721*bb4ee6a4SAndroid Build Coastguard Worker         create_pmu_node(&mut fdt, num_cpus)?;
722*bb4ee6a4SAndroid Build Coastguard Worker     }
723*bb4ee6a4SAndroid Build Coastguard Worker     create_serial_nodes(&mut fdt, serial_devices)?;
724*bb4ee6a4SAndroid Build Coastguard Worker     create_psci_node(&mut fdt, &psci_version)?;
725*bb4ee6a4SAndroid Build Coastguard Worker     create_pci_nodes(&mut fdt, pci_irqs, pci_cfg, pci_ranges, dma_pool_phandle)?;
726*bb4ee6a4SAndroid Build Coastguard Worker     create_rtc_node(&mut fdt)?;
727*bb4ee6a4SAndroid Build Coastguard Worker     if let Some((bat_mmio_base, bat_irq)) = bat_mmio_base_and_irq {
728*bb4ee6a4SAndroid Build Coastguard Worker         create_battery_node(&mut fdt, bat_mmio_base, bat_irq)?;
729*bb4ee6a4SAndroid Build Coastguard Worker     }
730*bb4ee6a4SAndroid Build Coastguard Worker     create_vmwdt_node(&mut fdt, vmwdt_cfg, num_cpus)?;
731*bb4ee6a4SAndroid Build Coastguard Worker     create_kvm_cpufreq_node(&mut fdt)?;
732*bb4ee6a4SAndroid Build Coastguard Worker     vm_generator(&mut fdt, &phandles)?;
733*bb4ee6a4SAndroid Build Coastguard Worker     if !cpu_frequencies.is_empty() {
734*bb4ee6a4SAndroid Build Coastguard Worker         if virt_cpufreq_v2 {
735*bb4ee6a4SAndroid Build Coastguard Worker             create_virt_cpufreq_v2_node(&mut fdt, num_cpus as u64)?;
736*bb4ee6a4SAndroid Build Coastguard Worker         } else {
737*bb4ee6a4SAndroid Build Coastguard Worker             create_virt_cpufreq_node(&mut fdt, num_cpus as u64)?;
738*bb4ee6a4SAndroid Build Coastguard Worker         }
739*bb4ee6a4SAndroid Build Coastguard Worker     }
740*bb4ee6a4SAndroid Build Coastguard Worker 
741*bb4ee6a4SAndroid Build Coastguard Worker     let pviommu_ids = get_pkvm_pviommu_ids(&platform_dev_resources)?;
742*bb4ee6a4SAndroid Build Coastguard Worker 
743*bb4ee6a4SAndroid Build Coastguard Worker     let cache_offset = phandles_key_cache.len();
744*bb4ee6a4SAndroid Build Coastguard Worker     // Hack to extend the lifetime of the Strings as keys of phandles (i.e. &str).
745*bb4ee6a4SAndroid Build Coastguard Worker     phandles_key_cache.extend(pviommu_ids.iter().map(|id| format!("pviommu{id}")));
746*bb4ee6a4SAndroid Build Coastguard Worker     let pviommu_phandle_keys = &phandles_key_cache[cache_offset..];
747*bb4ee6a4SAndroid Build Coastguard Worker 
748*bb4ee6a4SAndroid Build Coastguard Worker     for (index, (id, key)) in pviommu_ids.iter().zip(pviommu_phandle_keys).enumerate() {
749*bb4ee6a4SAndroid Build Coastguard Worker         let phandle = create_pkvm_pviommu_node(&mut fdt, index, *id)?;
750*bb4ee6a4SAndroid Build Coastguard Worker         phandles.insert(key, phandle);
751*bb4ee6a4SAndroid Build Coastguard Worker     }
752*bb4ee6a4SAndroid Build Coastguard Worker 
753*bb4ee6a4SAndroid Build Coastguard Worker     // Done writing base FDT, now apply DT overlays
754*bb4ee6a4SAndroid Build Coastguard Worker     apply_device_tree_overlays(
755*bb4ee6a4SAndroid Build Coastguard Worker         &mut fdt,
756*bb4ee6a4SAndroid Build Coastguard Worker         device_tree_overlays,
757*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
758*bb4ee6a4SAndroid Build Coastguard Worker         platform_dev_resources,
759*bb4ee6a4SAndroid Build Coastguard Worker         #[cfg(any(target_os = "android", target_os = "linux"))]
760*bb4ee6a4SAndroid Build Coastguard Worker         &phandles,
761*bb4ee6a4SAndroid Build Coastguard Worker     )?;
762*bb4ee6a4SAndroid Build Coastguard Worker 
763*bb4ee6a4SAndroid Build Coastguard Worker     let fdt_final = fdt.finish()?;
764*bb4ee6a4SAndroid Build Coastguard Worker 
765*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(file_path) = dump_device_tree_blob {
766*bb4ee6a4SAndroid Build Coastguard Worker         let mut fd = open_file_or_duplicate(
767*bb4ee6a4SAndroid Build Coastguard Worker             &file_path,
768*bb4ee6a4SAndroid Build Coastguard Worker             OpenOptions::new()
769*bb4ee6a4SAndroid Build Coastguard Worker                 .read(true)
770*bb4ee6a4SAndroid Build Coastguard Worker                 .create(true)
771*bb4ee6a4SAndroid Build Coastguard Worker                 .truncate(true)
772*bb4ee6a4SAndroid Build Coastguard Worker                 .write(true),
773*bb4ee6a4SAndroid Build Coastguard Worker         )
774*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|e| Error::FdtIoError(e.into()))?;
775*bb4ee6a4SAndroid Build Coastguard Worker         fd.write_all(&fdt_final)
776*bb4ee6a4SAndroid Build Coastguard Worker             .map_err(|e| Error::FdtDumpIoError(e, file_path.clone()))?;
777*bb4ee6a4SAndroid Build Coastguard Worker     }
778*bb4ee6a4SAndroid Build Coastguard Worker 
779*bb4ee6a4SAndroid Build Coastguard Worker     if fdt_final.len() > fdt_max_size {
780*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::TotalSizeTooLarge);
781*bb4ee6a4SAndroid Build Coastguard Worker     }
782*bb4ee6a4SAndroid Build Coastguard Worker 
783*bb4ee6a4SAndroid Build Coastguard Worker     let written = guest_mem
784*bb4ee6a4SAndroid Build Coastguard Worker         .write_at_addr(fdt_final.as_slice(), fdt_address)
785*bb4ee6a4SAndroid Build Coastguard Worker         .map_err(|_| Error::FdtGuestMemoryWriteError)?;
786*bb4ee6a4SAndroid Build Coastguard Worker     if written < fdt_final.len() {
787*bb4ee6a4SAndroid Build Coastguard Worker         return Err(Error::FdtGuestMemoryWriteError);
788*bb4ee6a4SAndroid Build Coastguard Worker     }
789*bb4ee6a4SAndroid Build Coastguard Worker 
790*bb4ee6a4SAndroid Build Coastguard Worker     Ok(())
791*bb4ee6a4SAndroid Build Coastguard Worker }
792*bb4ee6a4SAndroid Build Coastguard Worker 
793*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(test)]
794*bb4ee6a4SAndroid Build Coastguard Worker mod tests {
795*bb4ee6a4SAndroid Build Coastguard Worker     use super::*;
796*bb4ee6a4SAndroid Build Coastguard Worker 
797*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
psci_compatible_v0_1()798*bb4ee6a4SAndroid Build Coastguard Worker     fn psci_compatible_v0_1() {
799*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
800*bb4ee6a4SAndroid Build Coastguard Worker             psci_compatible(&PsciVersion::new(0, 1).unwrap()),
801*bb4ee6a4SAndroid Build Coastguard Worker             vec!["arm,psci"]
802*bb4ee6a4SAndroid Build Coastguard Worker         );
803*bb4ee6a4SAndroid Build Coastguard Worker     }
804*bb4ee6a4SAndroid Build Coastguard Worker 
805*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
psci_compatible_v0_2()806*bb4ee6a4SAndroid Build Coastguard Worker     fn psci_compatible_v0_2() {
807*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
808*bb4ee6a4SAndroid Build Coastguard Worker             psci_compatible(&PsciVersion::new(0, 2).unwrap()),
809*bb4ee6a4SAndroid Build Coastguard Worker             vec!["arm,psci-0.2"]
810*bb4ee6a4SAndroid Build Coastguard Worker         );
811*bb4ee6a4SAndroid Build Coastguard Worker     }
812*bb4ee6a4SAndroid Build Coastguard Worker 
813*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
psci_compatible_v0_5()814*bb4ee6a4SAndroid Build Coastguard Worker     fn psci_compatible_v0_5() {
815*bb4ee6a4SAndroid Build Coastguard Worker         // Only the 0.2 version supported by the kernel should be added.
816*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
817*bb4ee6a4SAndroid Build Coastguard Worker             psci_compatible(&PsciVersion::new(0, 5).unwrap()),
818*bb4ee6a4SAndroid Build Coastguard Worker             vec!["arm,psci-0.2"]
819*bb4ee6a4SAndroid Build Coastguard Worker         );
820*bb4ee6a4SAndroid Build Coastguard Worker     }
821*bb4ee6a4SAndroid Build Coastguard Worker 
822*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
psci_compatible_v1_0()823*bb4ee6a4SAndroid Build Coastguard Worker     fn psci_compatible_v1_0() {
824*bb4ee6a4SAndroid Build Coastguard Worker         // Both 1.0 and 0.2 should be listed, in that order.
825*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
826*bb4ee6a4SAndroid Build Coastguard Worker             psci_compatible(&PsciVersion::new(1, 0).unwrap()),
827*bb4ee6a4SAndroid Build Coastguard Worker             vec!["arm,psci-1.0", "arm,psci-0.2"]
828*bb4ee6a4SAndroid Build Coastguard Worker         );
829*bb4ee6a4SAndroid Build Coastguard Worker     }
830*bb4ee6a4SAndroid Build Coastguard Worker 
831*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
psci_compatible_v1_5()832*bb4ee6a4SAndroid Build Coastguard Worker     fn psci_compatible_v1_5() {
833*bb4ee6a4SAndroid Build Coastguard Worker         // Only the 1.0 and 0.2 versions supported by the kernel should be listed.
834*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(
835*bb4ee6a4SAndroid Build Coastguard Worker             psci_compatible(&PsciVersion::new(1, 5).unwrap()),
836*bb4ee6a4SAndroid Build Coastguard Worker             vec!["arm,psci-1.0", "arm,psci-0.2"]
837*bb4ee6a4SAndroid Build Coastguard Worker         );
838*bb4ee6a4SAndroid Build Coastguard Worker     }
839*bb4ee6a4SAndroid Build Coastguard Worker 
840*bb4ee6a4SAndroid Build Coastguard Worker     #[test]
symbols_entries()841*bb4ee6a4SAndroid Build Coastguard Worker     fn symbols_entries() {
842*bb4ee6a4SAndroid Build Coastguard Worker         const TEST_SYMBOL: &str = "dev";
843*bb4ee6a4SAndroid Build Coastguard Worker         const TEST_PATH: &str = "/dev";
844*bb4ee6a4SAndroid Build Coastguard Worker 
845*bb4ee6a4SAndroid Build Coastguard Worker         let mut fdt = Fdt::new(&[]);
846*bb4ee6a4SAndroid Build Coastguard Worker         add_symbols_entry(&mut fdt, TEST_SYMBOL, TEST_PATH).expect_err("missing node");
847*bb4ee6a4SAndroid Build Coastguard Worker 
848*bb4ee6a4SAndroid Build Coastguard Worker         fdt.root_mut().subnode_mut(TEST_SYMBOL).unwrap();
849*bb4ee6a4SAndroid Build Coastguard Worker         add_symbols_entry(&mut fdt, TEST_SYMBOL, TEST_PATH).expect_err("missing phandle");
850*bb4ee6a4SAndroid Build Coastguard Worker 
851*bb4ee6a4SAndroid Build Coastguard Worker         let intc_node = fdt.get_node_mut(TEST_PATH).unwrap();
852*bb4ee6a4SAndroid Build Coastguard Worker         intc_node.set_prop("phandle", 1u32).unwrap();
853*bb4ee6a4SAndroid Build Coastguard Worker         add_symbols_entry(&mut fdt, TEST_SYMBOL, TEST_PATH).expect("valid path");
854*bb4ee6a4SAndroid Build Coastguard Worker 
855*bb4ee6a4SAndroid Build Coastguard Worker         let symbols = fdt.get_node("/__symbols__").unwrap();
856*bb4ee6a4SAndroid Build Coastguard Worker         assert_eq!(symbols.get_prop::<String>(TEST_SYMBOL).unwrap(), TEST_PATH);
857*bb4ee6a4SAndroid Build Coastguard Worker     }
858*bb4ee6a4SAndroid Build Coastguard Worker }
859