pvmfw: Get vcpufreq by compat & NOP unused OPPs
If the input DT doesn't contain an OPP table, remove it from the
template instead of passing the placeholder table to the guest.
Instead of hard-coding the path to the cpufreq node in the VMM-provided
DT, locate it by compatible (as the guest kernel would do) and warn
about any extra node (similar to other nodes found by compatible).
Test: m pvmfw
Bug: 284369518
Change-Id: I9009ee0bb8eea932482582d8f005de35ec118920
diff --git a/pvmfw/src/fdt.rs b/pvmfw/src/fdt.rs
index 41ae5e5..dfc9ad1 100644
--- a/pvmfw/src/fdt.rs
+++ b/pvmfw/src/fdt.rs
@@ -229,13 +229,19 @@
}
fn read_vcpufreq_info(fdt: &Fdt) -> libfdt::Result<Option<VcpufreqInfo>> {
- if let Some(node) = fdt.node(cstr!("/cpufreq"))? {
- let mut regs = node.reg()?.ok_or(FdtError::NotFound)?;
- let reg = regs.next().ok_or(FdtError::NotFound)?;
- return Ok(Some(VcpufreqInfo { addr: reg.addr, size: reg.size.unwrap() }));
+ let mut nodes = fdt.compatible_nodes(cstr!("virtual,android-v-only-cpufreq"))?;
+ let Some(node) = nodes.next() else {
+ return Ok(None);
};
- Ok(None)
+ if nodes.next().is_some() {
+ warn!("DT has more than 1 cpufreq node: discarding extra nodes.");
+ }
+
+ let mut regs = node.reg()?.ok_or(FdtError::NotFound)?;
+ let reg = regs.next().ok_or(FdtError::NotFound)?;
+
+ Ok(Some(VcpufreqInfo { addr: reg.addr, size: reg.size.unwrap() }))
}
fn validate_vcpufreq_info(
@@ -262,10 +268,15 @@
fn patch_opptable(
node: FdtNodeMut,
- opptable: ArrayVec<[u64; DeviceTreeInfo::MAX_CPUS]>,
+ opptable: Option<ArrayVec<[u64; DeviceTreeInfo::MAX_CPUS]>>,
) -> libfdt::Result<()> {
let oppcompat = cstr!("operating-points-v2");
let next = node.next_compatible(oppcompat)?.ok_or(FdtError::NoSpace)?;
+
+ let Some(opptable) = opptable else {
+ return next.nop();
+ };
+
let mut next_subnode = next.first_subnode()?;
for entry in opptable {
@@ -297,9 +308,7 @@
const COMPAT: &CStr = cstr!("arm,arm-v8");
for (idx, cpu) in cpus.iter().enumerate() {
let cur = get_nth_compatible(fdt, idx, COMPAT)?.ok_or(FdtError::NoSpace)?;
- if let Some(opptable) = cpu.opptable_info {
- patch_opptable(cur, opptable)?;
- }
+ patch_opptable(cur, cpu.opptable_info)?;
}
let mut next = get_nth_compatible(fdt, cpus.len(), COMPAT)?;
while let Some(current) = next {