1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 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 #[cfg(any(target_os = "android", target_os = "linux"))]
6*bb4ee6a4SAndroid Build Coastguard Worker use std::collections::BTreeMap;
7*bb4ee6a4SAndroid Build Coastguard Worker
8*bb4ee6a4SAndroid Build Coastguard Worker use arch::apply_device_tree_overlays;
9*bb4ee6a4SAndroid Build Coastguard Worker use arch::DtbOverlay;
10*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
11*bb4ee6a4SAndroid Build Coastguard Worker use arch::PlatformBusResources;
12*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Error;
13*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Fdt;
14*bb4ee6a4SAndroid Build Coastguard Worker use cros_fdt::Result;
15*bb4ee6a4SAndroid Build Coastguard Worker use devices::irqchip::aia_aplic_addr;
16*bb4ee6a4SAndroid Build Coastguard Worker use devices::irqchip::aia_imsic_size;
17*bb4ee6a4SAndroid Build Coastguard Worker use devices::irqchip::AIA_APLIC_SIZE;
18*bb4ee6a4SAndroid Build Coastguard Worker use devices::irqchip::AIA_IMSIC_BASE;
19*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciAddress;
20*bb4ee6a4SAndroid Build Coastguard Worker use devices::PciInterruptPin;
21*bb4ee6a4SAndroid Build Coastguard Worker use rand::rngs::OsRng;
22*bb4ee6a4SAndroid Build Coastguard Worker use rand::RngCore;
23*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestAddress;
24*bb4ee6a4SAndroid Build Coastguard Worker use vm_memory::GuestMemory;
25*bb4ee6a4SAndroid Build Coastguard Worker
26*bb4ee6a4SAndroid Build Coastguard Worker // This is the start of DRAM in the physical address space.
27*bb4ee6a4SAndroid Build Coastguard Worker use crate::RISCV64_PHYS_MEM_START;
28*bb4ee6a4SAndroid Build Coastguard Worker
29*bb4ee6a4SAndroid Build Coastguard Worker // CPUs are assigned phandles starting with this number.
30*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_CPU0: u32 = 0x100;
31*bb4ee6a4SAndroid Build Coastguard Worker
32*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_AIA_APLIC: u32 = 2;
33*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_AIA_IMSIC: u32 = 3;
34*bb4ee6a4SAndroid Build Coastguard Worker const PHANDLE_CPU_INTC_BASE: u32 = 4;
35*bb4ee6a4SAndroid Build Coastguard Worker
create_memory_node(fdt: &mut Fdt, guest_mem: &GuestMemory) -> Result<()>36*bb4ee6a4SAndroid Build Coastguard Worker fn create_memory_node(fdt: &mut Fdt, guest_mem: &GuestMemory) -> Result<()> {
37*bb4ee6a4SAndroid Build Coastguard Worker let mut mem_reg_prop = Vec::new();
38*bb4ee6a4SAndroid Build Coastguard Worker let mut previous_memory_region_end = None;
39*bb4ee6a4SAndroid Build Coastguard Worker let mut regions = guest_mem.guest_memory_regions();
40*bb4ee6a4SAndroid Build Coastguard Worker regions.sort();
41*bb4ee6a4SAndroid Build Coastguard Worker for region in regions {
42*bb4ee6a4SAndroid Build Coastguard Worker // Merge with the previous region if possible.
43*bb4ee6a4SAndroid Build Coastguard Worker if let Some(previous_end) = previous_memory_region_end {
44*bb4ee6a4SAndroid Build Coastguard Worker if region.0 == previous_end {
45*bb4ee6a4SAndroid Build Coastguard Worker *mem_reg_prop.last_mut().unwrap() += region.1 as u64;
46*bb4ee6a4SAndroid Build Coastguard Worker previous_memory_region_end =
47*bb4ee6a4SAndroid Build Coastguard Worker Some(previous_end.checked_add(region.1 as u64).unwrap());
48*bb4ee6a4SAndroid Build Coastguard Worker continue;
49*bb4ee6a4SAndroid Build Coastguard Worker }
50*bb4ee6a4SAndroid Build Coastguard Worker assert!(region.0 > previous_end, "Memory regions overlap");
51*bb4ee6a4SAndroid Build Coastguard Worker }
52*bb4ee6a4SAndroid Build Coastguard Worker
53*bb4ee6a4SAndroid Build Coastguard Worker mem_reg_prop.push(region.0.offset());
54*bb4ee6a4SAndroid Build Coastguard Worker mem_reg_prop.push(region.1 as u64);
55*bb4ee6a4SAndroid Build Coastguard Worker previous_memory_region_end = Some(region.0.checked_add(region.1 as u64).unwrap());
56*bb4ee6a4SAndroid Build Coastguard Worker }
57*bb4ee6a4SAndroid Build Coastguard Worker
58*bb4ee6a4SAndroid Build Coastguard Worker let memory_node = fdt.root_mut().subnode_mut("memory")?;
59*bb4ee6a4SAndroid Build Coastguard Worker memory_node.set_prop("device_type", "memory")?;
60*bb4ee6a4SAndroid Build Coastguard Worker memory_node.set_prop("reg", mem_reg_prop)?;
61*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
62*bb4ee6a4SAndroid Build Coastguard Worker }
63*bb4ee6a4SAndroid Build Coastguard Worker
create_cpu_nodes(fdt: &mut Fdt, num_cpus: u32, timebase_frequency: u32) -> Result<()>64*bb4ee6a4SAndroid Build Coastguard Worker fn create_cpu_nodes(fdt: &mut Fdt, num_cpus: u32, timebase_frequency: u32) -> Result<()> {
65*bb4ee6a4SAndroid Build Coastguard Worker let cpus_node = fdt.root_mut().subnode_mut("cpus")?;
66*bb4ee6a4SAndroid Build Coastguard Worker cpus_node.set_prop("#address-cells", 0x1u32)?;
67*bb4ee6a4SAndroid Build Coastguard Worker cpus_node.set_prop("#size-cells", 0x0u32)?;
68*bb4ee6a4SAndroid Build Coastguard Worker cpus_node.set_prop("timebase-frequency", timebase_frequency)?;
69*bb4ee6a4SAndroid Build Coastguard Worker
70*bb4ee6a4SAndroid Build Coastguard Worker for cpu_id in 0..num_cpus {
71*bb4ee6a4SAndroid Build Coastguard Worker let cpu_name = format!("cpu@{:x}", cpu_id);
72*bb4ee6a4SAndroid Build Coastguard Worker let cpu_node = cpus_node.subnode_mut(&cpu_name)?;
73*bb4ee6a4SAndroid Build Coastguard Worker cpu_node.set_prop("device_type", "cpu")?;
74*bb4ee6a4SAndroid Build Coastguard Worker cpu_node.set_prop("compatible", "riscv")?;
75*bb4ee6a4SAndroid Build Coastguard Worker cpu_node.set_prop("mmu-type", "sv48")?;
76*bb4ee6a4SAndroid Build Coastguard Worker cpu_node.set_prop("riscv,isa", "rv64iafdcsu_smaia_ssaia")?;
77*bb4ee6a4SAndroid Build Coastguard Worker cpu_node.set_prop("status", "okay")?;
78*bb4ee6a4SAndroid Build Coastguard Worker cpu_node.set_prop("reg", cpu_id)?;
79*bb4ee6a4SAndroid Build Coastguard Worker cpu_node.set_prop("phandle", PHANDLE_CPU0 + cpu_id)?;
80*bb4ee6a4SAndroid Build Coastguard Worker
81*bb4ee6a4SAndroid Build Coastguard Worker // Add interrupt controller node
82*bb4ee6a4SAndroid Build Coastguard Worker let intc_node = cpu_node.subnode_mut("interrupt-controller")?;
83*bb4ee6a4SAndroid Build Coastguard Worker intc_node.set_prop("compatible", "riscv,cpu-intc")?;
84*bb4ee6a4SAndroid Build Coastguard Worker intc_node.set_prop("#interrupt-cells", 1u32)?;
85*bb4ee6a4SAndroid Build Coastguard Worker intc_node.set_prop("interrupt-controller", ())?;
86*bb4ee6a4SAndroid Build Coastguard Worker intc_node.set_prop("phandle", PHANDLE_CPU_INTC_BASE + cpu_id)?;
87*bb4ee6a4SAndroid Build Coastguard Worker }
88*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
89*bb4ee6a4SAndroid Build Coastguard Worker }
90*bb4ee6a4SAndroid Build Coastguard Worker
create_chosen_node( fdt: &mut Fdt, cmdline: &str, initrd: Option<(GuestAddress, usize)>, ) -> Result<()>91*bb4ee6a4SAndroid Build Coastguard Worker fn create_chosen_node(
92*bb4ee6a4SAndroid Build Coastguard Worker fdt: &mut Fdt,
93*bb4ee6a4SAndroid Build Coastguard Worker cmdline: &str,
94*bb4ee6a4SAndroid Build Coastguard Worker initrd: Option<(GuestAddress, usize)>,
95*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
96*bb4ee6a4SAndroid Build Coastguard Worker let chosen_node = fdt.root_mut().subnode_mut("chosen")?;
97*bb4ee6a4SAndroid Build Coastguard Worker chosen_node.set_prop("linux,pci-probe-only", 1u32)?;
98*bb4ee6a4SAndroid Build Coastguard Worker chosen_node.set_prop("bootargs", cmdline)?;
99*bb4ee6a4SAndroid Build Coastguard Worker
100*bb4ee6a4SAndroid Build Coastguard Worker let mut kaslr_seed_bytes = [0u8; 8];
101*bb4ee6a4SAndroid Build Coastguard Worker OsRng.fill_bytes(&mut kaslr_seed_bytes);
102*bb4ee6a4SAndroid Build Coastguard Worker let kaslr_seed = u64::from_le_bytes(kaslr_seed_bytes);
103*bb4ee6a4SAndroid Build Coastguard Worker chosen_node.set_prop("kaslr-seed", kaslr_seed)?;
104*bb4ee6a4SAndroid Build Coastguard Worker
105*bb4ee6a4SAndroid Build Coastguard Worker let mut rng_seed_bytes = [0u8; 256];
106*bb4ee6a4SAndroid Build Coastguard Worker OsRng.fill_bytes(&mut rng_seed_bytes);
107*bb4ee6a4SAndroid Build Coastguard Worker chosen_node.set_prop("rng-seed", &rng_seed_bytes)?;
108*bb4ee6a4SAndroid Build Coastguard Worker
109*bb4ee6a4SAndroid Build Coastguard Worker if let Some((initrd_addr, initrd_size)) = initrd {
110*bb4ee6a4SAndroid Build Coastguard Worker let initrd_start = initrd_addr.offset();
111*bb4ee6a4SAndroid Build Coastguard Worker let initrd_end = initrd_start + initrd_size as u64;
112*bb4ee6a4SAndroid Build Coastguard Worker chosen_node.set_prop("linux,initrd-start", initrd_start)?;
113*bb4ee6a4SAndroid Build Coastguard Worker chosen_node.set_prop("linux,initrd-end", initrd_end)?;
114*bb4ee6a4SAndroid Build Coastguard Worker }
115*bb4ee6a4SAndroid Build Coastguard Worker
116*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
117*bb4ee6a4SAndroid Build Coastguard Worker }
118*bb4ee6a4SAndroid Build Coastguard Worker
119*bb4ee6a4SAndroid Build Coastguard Worker // num_ids: number of imsic ids from the aia subsystem
120*bb4ee6a4SAndroid Build Coastguard Worker // num_sources: number of aplic sources from the aia subsystem
create_aia_node( fdt: &mut Fdt, num_cpus: usize, num_ids: usize, num_sources: usize, ) -> Result<()>121*bb4ee6a4SAndroid Build Coastguard Worker fn create_aia_node(
122*bb4ee6a4SAndroid Build Coastguard Worker fdt: &mut Fdt,
123*bb4ee6a4SAndroid Build Coastguard Worker num_cpus: usize,
124*bb4ee6a4SAndroid Build Coastguard Worker num_ids: usize,
125*bb4ee6a4SAndroid Build Coastguard Worker num_sources: usize,
126*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
127*bb4ee6a4SAndroid Build Coastguard Worker let name = format!("imsics@{:#08x}", AIA_IMSIC_BASE);
128*bb4ee6a4SAndroid Build Coastguard Worker let imsic_node = fdt.root_mut().subnode_mut(&name)?;
129*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("compatible", "riscv,imsics")?;
130*bb4ee6a4SAndroid Build Coastguard Worker
131*bb4ee6a4SAndroid Build Coastguard Worker let regs = [
132*bb4ee6a4SAndroid Build Coastguard Worker 0u32,
133*bb4ee6a4SAndroid Build Coastguard Worker AIA_IMSIC_BASE as u32,
134*bb4ee6a4SAndroid Build Coastguard Worker 0,
135*bb4ee6a4SAndroid Build Coastguard Worker aia_imsic_size(num_cpus) as u32,
136*bb4ee6a4SAndroid Build Coastguard Worker ];
137*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("reg", ®s)?;
138*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("#interrupt-cells", 0u32)?;
139*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("interrupt-controller", ())?;
140*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("msi-controller", ())?;
141*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("riscv,num-ids", num_ids as u32)?;
142*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("phandle", PHANDLE_AIA_IMSIC)?;
143*bb4ee6a4SAndroid Build Coastguard Worker
144*bb4ee6a4SAndroid Build Coastguard Worker const S_MODE_EXT_IRQ: u32 = 9;
145*bb4ee6a4SAndroid Build Coastguard Worker let mut cpu_intc_regs: Vec<u32> = Vec::with_capacity(num_cpus * 2);
146*bb4ee6a4SAndroid Build Coastguard Worker for hart in 0..num_cpus {
147*bb4ee6a4SAndroid Build Coastguard Worker cpu_intc_regs.push(PHANDLE_CPU_INTC_BASE + hart as u32);
148*bb4ee6a4SAndroid Build Coastguard Worker cpu_intc_regs.push(S_MODE_EXT_IRQ);
149*bb4ee6a4SAndroid Build Coastguard Worker }
150*bb4ee6a4SAndroid Build Coastguard Worker imsic_node.set_prop("interrupts-extended", cpu_intc_regs)?;
151*bb4ee6a4SAndroid Build Coastguard Worker
152*bb4ee6a4SAndroid Build Coastguard Worker /* Skip APLIC node if we have no interrupt sources */
153*bb4ee6a4SAndroid Build Coastguard Worker if num_sources > 0 {
154*bb4ee6a4SAndroid Build Coastguard Worker let name = format!("aplic@{:#08x}", aia_aplic_addr(num_cpus));
155*bb4ee6a4SAndroid Build Coastguard Worker let aplic_node = fdt.root_mut().subnode_mut(&name)?;
156*bb4ee6a4SAndroid Build Coastguard Worker aplic_node.set_prop("compatible", "riscv,aplic")?;
157*bb4ee6a4SAndroid Build Coastguard Worker
158*bb4ee6a4SAndroid Build Coastguard Worker let regs = [0u32, aia_aplic_addr(num_cpus) as u32, 0, AIA_APLIC_SIZE];
159*bb4ee6a4SAndroid Build Coastguard Worker aplic_node.set_prop("reg", ®s)?;
160*bb4ee6a4SAndroid Build Coastguard Worker aplic_node.set_prop("#interrupt-cells", 2u32)?;
161*bb4ee6a4SAndroid Build Coastguard Worker aplic_node.set_prop("interrupt-controller", ())?;
162*bb4ee6a4SAndroid Build Coastguard Worker aplic_node.set_prop("riscv,num-sources", num_sources as u32)?;
163*bb4ee6a4SAndroid Build Coastguard Worker aplic_node.set_prop("phandle", PHANDLE_AIA_APLIC)?;
164*bb4ee6a4SAndroid Build Coastguard Worker aplic_node.set_prop("msi-parent", PHANDLE_AIA_IMSIC)?;
165*bb4ee6a4SAndroid Build Coastguard Worker }
166*bb4ee6a4SAndroid Build Coastguard Worker
167*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
168*bb4ee6a4SAndroid Build Coastguard Worker }
169*bb4ee6a4SAndroid Build Coastguard Worker
170*bb4ee6a4SAndroid Build Coastguard Worker /// PCI host controller address range.
171*bb4ee6a4SAndroid Build Coastguard Worker ///
172*bb4ee6a4SAndroid Build Coastguard Worker /// This represents a single entry in the "ranges" property for a PCI host controller.
173*bb4ee6a4SAndroid Build Coastguard Worker ///
174*bb4ee6a4SAndroid Build Coastguard Worker /// See [PCI Bus Binding to Open Firmware](https://www.openfirmware.info/data/docs/bus.pci.pdf)
175*bb4ee6a4SAndroid Build Coastguard Worker /// and https://www.kernel.org/doc/Documentation/devicetree/bindings/pci/host-generic-pci.txt
176*bb4ee6a4SAndroid Build Coastguard Worker /// for more information.
177*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
178*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciRange {
179*bb4ee6a4SAndroid Build Coastguard Worker pub space: PciAddressSpace,
180*bb4ee6a4SAndroid Build Coastguard Worker pub bus_address: u64,
181*bb4ee6a4SAndroid Build Coastguard Worker pub cpu_physical_address: u64,
182*bb4ee6a4SAndroid Build Coastguard Worker pub size: u64,
183*bb4ee6a4SAndroid Build Coastguard Worker pub prefetchable: bool,
184*bb4ee6a4SAndroid Build Coastguard Worker }
185*bb4ee6a4SAndroid Build Coastguard Worker
186*bb4ee6a4SAndroid Build Coastguard Worker /// PCI address space.
187*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
188*bb4ee6a4SAndroid Build Coastguard Worker #[allow(dead_code)]
189*bb4ee6a4SAndroid Build Coastguard Worker pub enum PciAddressSpace {
190*bb4ee6a4SAndroid Build Coastguard Worker /// PCI configuration space
191*bb4ee6a4SAndroid Build Coastguard Worker Configuration = 0b00,
192*bb4ee6a4SAndroid Build Coastguard Worker /// I/O space
193*bb4ee6a4SAndroid Build Coastguard Worker Io = 0b01,
194*bb4ee6a4SAndroid Build Coastguard Worker /// 32-bit memory space
195*bb4ee6a4SAndroid Build Coastguard Worker Memory = 0b10,
196*bb4ee6a4SAndroid Build Coastguard Worker /// 64-bit memory space
197*bb4ee6a4SAndroid Build Coastguard Worker Memory64 = 0b11,
198*bb4ee6a4SAndroid Build Coastguard Worker }
199*bb4ee6a4SAndroid Build Coastguard Worker
200*bb4ee6a4SAndroid Build Coastguard Worker /// Location of memory-mapped PCI configuration space.
201*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)]
202*bb4ee6a4SAndroid Build Coastguard Worker pub struct PciConfigRegion {
203*bb4ee6a4SAndroid Build Coastguard Worker /// Physical address of the base of the memory-mapped PCI configuration region.
204*bb4ee6a4SAndroid Build Coastguard Worker pub base: u64,
205*bb4ee6a4SAndroid Build Coastguard Worker /// Size of the PCI configuration region in bytes.
206*bb4ee6a4SAndroid Build Coastguard Worker pub size: u64,
207*bb4ee6a4SAndroid Build Coastguard Worker }
208*bb4ee6a4SAndroid Build Coastguard Worker
create_pci_nodes( fdt: &mut Fdt, pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>, cfg: PciConfigRegion, ranges: &[PciRange], ) -> Result<()>209*bb4ee6a4SAndroid Build Coastguard Worker fn create_pci_nodes(
210*bb4ee6a4SAndroid Build Coastguard Worker fdt: &mut Fdt,
211*bb4ee6a4SAndroid Build Coastguard Worker pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>,
212*bb4ee6a4SAndroid Build Coastguard Worker cfg: PciConfigRegion,
213*bb4ee6a4SAndroid Build Coastguard Worker ranges: &[PciRange],
214*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
215*bb4ee6a4SAndroid Build Coastguard Worker // Add devicetree nodes describing a PCI generic host controller.
216*bb4ee6a4SAndroid Build Coastguard Worker // See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
217*bb4ee6a4SAndroid Build Coastguard Worker // and "PCI Bus Binding to IEEE Std 1275-1994".
218*bb4ee6a4SAndroid Build Coastguard Worker let ranges: Vec<u32> = ranges
219*bb4ee6a4SAndroid Build Coastguard Worker .iter()
220*bb4ee6a4SAndroid Build Coastguard Worker .flat_map(|r| {
221*bb4ee6a4SAndroid Build Coastguard Worker let ss = r.space as u32;
222*bb4ee6a4SAndroid Build Coastguard Worker let p = r.prefetchable as u32;
223*bb4ee6a4SAndroid Build Coastguard Worker [
224*bb4ee6a4SAndroid Build Coastguard Worker // BUS_ADDRESS(3) encoded as defined in OF PCI Bus Binding
225*bb4ee6a4SAndroid Build Coastguard Worker (ss << 24) | (p << 30),
226*bb4ee6a4SAndroid Build Coastguard Worker (r.bus_address >> 32) as u32,
227*bb4ee6a4SAndroid Build Coastguard Worker r.bus_address as u32,
228*bb4ee6a4SAndroid Build Coastguard Worker // CPU_PHYSICAL(2)
229*bb4ee6a4SAndroid Build Coastguard Worker (r.cpu_physical_address >> 32) as u32,
230*bb4ee6a4SAndroid Build Coastguard Worker r.cpu_physical_address as u32,
231*bb4ee6a4SAndroid Build Coastguard Worker // SIZE(2)
232*bb4ee6a4SAndroid Build Coastguard Worker (r.size >> 32) as u32,
233*bb4ee6a4SAndroid Build Coastguard Worker r.size as u32,
234*bb4ee6a4SAndroid Build Coastguard Worker ]
235*bb4ee6a4SAndroid Build Coastguard Worker })
236*bb4ee6a4SAndroid Build Coastguard Worker .collect();
237*bb4ee6a4SAndroid Build Coastguard Worker
238*bb4ee6a4SAndroid Build Coastguard Worker let bus_range = [0u32, 0u32]; // Only bus 0
239*bb4ee6a4SAndroid Build Coastguard Worker let reg = [cfg.base, cfg.size];
240*bb4ee6a4SAndroid Build Coastguard Worker
241*bb4ee6a4SAndroid Build Coastguard Worker const IRQ_TYPE_LEVEL_HIGH: u32 = 0x00000004;
242*bb4ee6a4SAndroid Build Coastguard Worker let mut interrupts: Vec<u32> = Vec::new();
243*bb4ee6a4SAndroid Build Coastguard Worker let mut masks: Vec<u32> = Vec::new();
244*bb4ee6a4SAndroid Build Coastguard Worker
245*bb4ee6a4SAndroid Build Coastguard Worker for (address, irq_num, irq_pin) in pci_irqs.iter() {
246*bb4ee6a4SAndroid Build Coastguard Worker // PCI_DEVICE(3)
247*bb4ee6a4SAndroid Build Coastguard Worker interrupts.push(address.to_config_address(0, 8));
248*bb4ee6a4SAndroid Build Coastguard Worker interrupts.push(0);
249*bb4ee6a4SAndroid Build Coastguard Worker interrupts.push(0);
250*bb4ee6a4SAndroid Build Coastguard Worker
251*bb4ee6a4SAndroid Build Coastguard Worker // INT#(1)
252*bb4ee6a4SAndroid Build Coastguard Worker interrupts.push(irq_pin.to_mask() + 1);
253*bb4ee6a4SAndroid Build Coastguard Worker
254*bb4ee6a4SAndroid Build Coastguard Worker // INTERRUPT INFO
255*bb4ee6a4SAndroid Build Coastguard Worker interrupts.push(PHANDLE_AIA_APLIC);
256*bb4ee6a4SAndroid Build Coastguard Worker interrupts.push(*irq_num);
257*bb4ee6a4SAndroid Build Coastguard Worker interrupts.push(IRQ_TYPE_LEVEL_HIGH);
258*bb4ee6a4SAndroid Build Coastguard Worker
259*bb4ee6a4SAndroid Build Coastguard Worker // PCI_DEVICE(3)
260*bb4ee6a4SAndroid Build Coastguard Worker masks.push(0xf800); // bits 11..15 (device)
261*bb4ee6a4SAndroid Build Coastguard Worker masks.push(0);
262*bb4ee6a4SAndroid Build Coastguard Worker masks.push(0);
263*bb4ee6a4SAndroid Build Coastguard Worker
264*bb4ee6a4SAndroid Build Coastguard Worker // INT#(1)
265*bb4ee6a4SAndroid Build Coastguard Worker masks.push(0x7); // allow INTA#-INTD# (1 | 2 | 3 | 4)
266*bb4ee6a4SAndroid Build Coastguard Worker }
267*bb4ee6a4SAndroid Build Coastguard Worker
268*bb4ee6a4SAndroid Build Coastguard Worker let pci_node = fdt.root_mut().subnode_mut("pci")?;
269*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("compatible", "pci-host-cam-generic")?;
270*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("device_type", "pci")?;
271*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("ranges", ranges)?;
272*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("bus-range", &bus_range)?;
273*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("#address-cells", 3u32)?;
274*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("#size-cells", 2u32)?;
275*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("reg", ®)?;
276*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("#interrupt-cells", 1u32)?;
277*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("interrupt-map", interrupts)?;
278*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("interrupt-map-mask", masks)?;
279*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("msi-parent", PHANDLE_AIA_IMSIC)?;
280*bb4ee6a4SAndroid Build Coastguard Worker pci_node.set_prop("dma-coherent", ())?;
281*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
282*bb4ee6a4SAndroid Build Coastguard Worker }
283*bb4ee6a4SAndroid Build Coastguard Worker
284*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a flattened device tree containing all of the parameters for the
285*bb4ee6a4SAndroid Build Coastguard Worker /// kernel and loads it into the guest memory at the specified offset.
286*bb4ee6a4SAndroid Build Coastguard Worker ///
287*bb4ee6a4SAndroid Build Coastguard Worker /// # Arguments
288*bb4ee6a4SAndroid Build Coastguard Worker ///
289*bb4ee6a4SAndroid Build Coastguard Worker /// * `fdt_max_size` - The amount of space reserved for the device tree
290*bb4ee6a4SAndroid Build Coastguard Worker /// * `guest_mem` - The guest memory object
291*bb4ee6a4SAndroid Build Coastguard Worker /// * `pci_irqs` - List of PCI device address to PCI interrupt number and pin mappings
292*bb4ee6a4SAndroid Build Coastguard Worker /// * `pci_cfg` - Location of the memory-mapped PCI configuration space.
293*bb4ee6a4SAndroid Build Coastguard Worker /// * `pci_ranges` - Memory ranges accessible via the PCI host controller.
294*bb4ee6a4SAndroid Build Coastguard Worker /// * `num_cpus` - Number of virtual CPUs the guest will have
295*bb4ee6a4SAndroid Build Coastguard Worker /// * `fdt_load_offset` - The offset into physical memory for the device tree
296*bb4ee6a4SAndroid Build Coastguard Worker /// * `cmdline` - The kernel commandline
297*bb4ee6a4SAndroid Build Coastguard Worker /// * `initrd` - An optional tuple of initrd guest physical address and size
298*bb4ee6a4SAndroid Build Coastguard Worker /// * `timebase_frequency` - The time base frequency for the VM.
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, fdt_load_offset: u64, aia_num_ids: usize, aia_num_sources: usize, cmdline: &str, initrd: Option<(GuestAddress, usize)>, timebase_frequency: u32, device_tree_overlays: Vec<DtbOverlay>, ) -> Result<()>299*bb4ee6a4SAndroid Build Coastguard Worker pub fn create_fdt(
300*bb4ee6a4SAndroid Build Coastguard Worker fdt_max_size: usize,
301*bb4ee6a4SAndroid Build Coastguard Worker guest_mem: &GuestMemory,
302*bb4ee6a4SAndroid Build Coastguard Worker pci_irqs: Vec<(PciAddress, u32, PciInterruptPin)>,
303*bb4ee6a4SAndroid Build Coastguard Worker pci_cfg: PciConfigRegion,
304*bb4ee6a4SAndroid Build Coastguard Worker pci_ranges: &[PciRange],
305*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))] platform_dev_resources: Vec<
306*bb4ee6a4SAndroid Build Coastguard Worker PlatformBusResources,
307*bb4ee6a4SAndroid Build Coastguard Worker >,
308*bb4ee6a4SAndroid Build Coastguard Worker num_cpus: u32,
309*bb4ee6a4SAndroid Build Coastguard Worker fdt_load_offset: u64,
310*bb4ee6a4SAndroid Build Coastguard Worker aia_num_ids: usize,
311*bb4ee6a4SAndroid Build Coastguard Worker aia_num_sources: usize,
312*bb4ee6a4SAndroid Build Coastguard Worker cmdline: &str,
313*bb4ee6a4SAndroid Build Coastguard Worker initrd: Option<(GuestAddress, usize)>,
314*bb4ee6a4SAndroid Build Coastguard Worker timebase_frequency: u32,
315*bb4ee6a4SAndroid Build Coastguard Worker device_tree_overlays: Vec<DtbOverlay>,
316*bb4ee6a4SAndroid Build Coastguard Worker ) -> Result<()> {
317*bb4ee6a4SAndroid Build Coastguard Worker let mut fdt = Fdt::new(&[]);
318*bb4ee6a4SAndroid Build Coastguard Worker
319*bb4ee6a4SAndroid Build Coastguard Worker // The whole thing is put into one giant node with some top level properties
320*bb4ee6a4SAndroid Build Coastguard Worker let root_node = fdt.root_mut();
321*bb4ee6a4SAndroid Build Coastguard Worker root_node.set_prop("compatible", "linux,dummy-virt")?;
322*bb4ee6a4SAndroid Build Coastguard Worker root_node.set_prop("#address-cells", 0x2u32)?;
323*bb4ee6a4SAndroid Build Coastguard Worker root_node.set_prop("#size-cells", 0x2u32)?;
324*bb4ee6a4SAndroid Build Coastguard Worker create_chosen_node(&mut fdt, cmdline, initrd)?;
325*bb4ee6a4SAndroid Build Coastguard Worker create_memory_node(&mut fdt, guest_mem)?;
326*bb4ee6a4SAndroid Build Coastguard Worker create_cpu_nodes(&mut fdt, num_cpus, timebase_frequency)?;
327*bb4ee6a4SAndroid Build Coastguard Worker create_aia_node(&mut fdt, num_cpus as usize, aia_num_ids, aia_num_sources)?;
328*bb4ee6a4SAndroid Build Coastguard Worker create_pci_nodes(&mut fdt, pci_irqs, pci_cfg, pci_ranges)?;
329*bb4ee6a4SAndroid Build Coastguard Worker
330*bb4ee6a4SAndroid Build Coastguard Worker // Done writing base FDT, now apply DT overlays
331*bb4ee6a4SAndroid Build Coastguard Worker apply_device_tree_overlays(
332*bb4ee6a4SAndroid Build Coastguard Worker &mut fdt,
333*bb4ee6a4SAndroid Build Coastguard Worker device_tree_overlays,
334*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
335*bb4ee6a4SAndroid Build Coastguard Worker platform_dev_resources,
336*bb4ee6a4SAndroid Build Coastguard Worker #[cfg(any(target_os = "android", target_os = "linux"))]
337*bb4ee6a4SAndroid Build Coastguard Worker &BTreeMap::new(),
338*bb4ee6a4SAndroid Build Coastguard Worker )?;
339*bb4ee6a4SAndroid Build Coastguard Worker
340*bb4ee6a4SAndroid Build Coastguard Worker let fdt_final = fdt.finish()?;
341*bb4ee6a4SAndroid Build Coastguard Worker if fdt_final.len() > fdt_max_size {
342*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::TotalSizeTooLarge);
343*bb4ee6a4SAndroid Build Coastguard Worker }
344*bb4ee6a4SAndroid Build Coastguard Worker
345*bb4ee6a4SAndroid Build Coastguard Worker let fdt_address = GuestAddress(RISCV64_PHYS_MEM_START + fdt_load_offset);
346*bb4ee6a4SAndroid Build Coastguard Worker let written = guest_mem
347*bb4ee6a4SAndroid Build Coastguard Worker .write_at_addr(fdt_final.as_slice(), fdt_address)
348*bb4ee6a4SAndroid Build Coastguard Worker .map_err(|_| Error::FdtGuestMemoryWriteError)?;
349*bb4ee6a4SAndroid Build Coastguard Worker if written < fdt_final.len() {
350*bb4ee6a4SAndroid Build Coastguard Worker return Err(Error::FdtGuestMemoryWriteError);
351*bb4ee6a4SAndroid Build Coastguard Worker }
352*bb4ee6a4SAndroid Build Coastguard Worker
353*bb4ee6a4SAndroid Build Coastguard Worker Ok(())
354*bb4ee6a4SAndroid Build Coastguard Worker }
355