diff options
Diffstat (limited to 'aarch64/src/fdt.rs')
-rw-r--r-- | aarch64/src/fdt.rs | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/aarch64/src/fdt.rs b/aarch64/src/fdt.rs index fc976ef..19662c6 100644 --- a/aarch64/src/fdt.rs +++ b/aarch64/src/fdt.rs @@ -42,6 +42,8 @@ use crate::AARCH64_MMIO_SIZE; use crate::AARCH64_PCI_CFG_BASE; use crate::AARCH64_PCI_CFG_SIZE; +use crate::AARCH64_PMU_IRQ; + // This is an arbitrary number to specify the node for the GIC. // If we had a more complex interrupt architecture, then we'd need an enum for // these. @@ -137,6 +139,23 @@ fn create_timer_node(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<()> { Ok(()) } +fn create_pmu_node(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<()> { + let compatible = "arm,armv8-pmuv3"; + let cpu_mask: u32 = + (((1 << num_cpus) - 1) << GIC_FDT_IRQ_PPI_CPU_SHIFT) & GIC_FDT_IRQ_PPI_CPU_MASK; + let irq = generate_prop32(&[ + GIC_FDT_IRQ_TYPE_PPI, + AARCH64_PMU_IRQ, + cpu_mask | IRQ_TYPE_LEVEL_HIGH, + ]); + + begin_node(fdt, "pmu")?; + property_string(fdt, "compatible", compatible)?; + property(fdt, "interrupts", &irq)?; + end_node(fdt)?; + Ok(()) +} + fn create_serial_node(fdt: &mut Vec<u8>, addr: u64, irq: u32) -> Result<()> { let serial_reg_prop = generate_prop64(&[addr, AARCH64_SERIAL_SIZE]); let irq = generate_prop32(&[GIC_FDT_IRQ_TYPE_SPI, irq, IRQ_TYPE_EDGE_RISING]); @@ -351,6 +370,7 @@ pub fn create_fdt( initrd: Option<(GuestAddress, usize)>, android_fstab: Option<File>, is_gicv3: bool, + use_pmu: bool, ) -> Result<()> { let mut fdt = vec![0; fdt_max_size]; start_fdt(&mut fdt, fdt_max_size)?; @@ -369,6 +389,9 @@ pub fn create_fdt( create_cpu_nodes(&mut fdt, num_cpus)?; create_gic_node(&mut fdt, is_gicv3, num_cpus as u64)?; create_timer_node(&mut fdt, num_cpus)?; + if use_pmu { + create_pmu_node(&mut fdt, num_cpus)?; + } create_serial_nodes(&mut fdt)?; create_psci_node(&mut fdt)?; create_pci_nodes(&mut fdt, pci_irqs, pci_device_base, pci_device_size)?; |