summary refs log tree commit diff
path: root/aarch64/src/fdt.rs
diff options
context:
space:
mode:
Diffstat (limited to 'aarch64/src/fdt.rs')
-rw-r--r--aarch64/src/fdt.rs23
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)?;