diff options
author | Pierre-Clément Tosi <ptosi@google.com> | 2024-03-21 15:42:57 +0000 |
---|---|---|
committer | crosvm LUCI <crosvm-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2024-03-28 13:26:29 +0000 |
commit | 9a4a79a44791da6927b92195a804acb010ea1e29 (patch) | |
tree | baf558629753c139c02cf0323e514e5c662c3a81 /aarch64 | |
parent | 3b29c72913c076ca537355d0270c8a3419477ec1 (diff) | |
download | crosvm-9a4a79a44791da6927b92195a804acb010ea1e29.tar.gz |
arm64: Use vCPU MPIDR value for DT /cpus/cpu@X/reg
On AArch64, Linux expects the <reg> property to match the MPIDR:
> On ARM v8 64-bit systems <reg> is required and matches the MPIDR_EL1
> register affinity bits. If cpus node's #address-cells property is set
> to 1 the reg cell bits [23:0] must be set to bits [23:0] of MPIDR_EL1.
> All other bits in the reg cells must be set to 0.
so introduce the plumbing to let hypervisor backends describe the MPIDR
topology while generating the FDT. For now, use a default implementation
that matches the previous behavior for all realistic topologies (i.e.
when the VM has 16777215 or fewer vCPUs).
Keep generating the DT with #address-cells=1, even if it limits us to
bits MPIDR_EL1[23:0], as that is more than enough with the default
topology.
Bug: b/331362077
Test: tools/run_tests -p aarch64
Change-Id: I4850e582f197b53bdfce7fe6c40c2c9726c65c6b
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5401898
Commit-Queue: Pierre-Clément Tosi <ptosi@google.com>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Diffstat (limited to 'aarch64')
-rw-r--r-- | aarch64/src/fdt.rs | 11 | ||||
-rw-r--r-- | aarch64/src/lib.rs | 7 |
2 files changed, 16 insertions, 2 deletions
diff --git a/aarch64/src/fdt.rs b/aarch64/src/fdt.rs index 6dcdc163d..b55c8852d 100644 --- a/aarch64/src/fdt.rs +++ b/aarch64/src/fdt.rs @@ -132,6 +132,7 @@ fn create_resv_memory_node( fn 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>, @@ -143,14 +144,18 @@ fn create_cpu_nodes( cpus_node.set_prop("#size-cells", 0x0u32)?; for cpu_id in 0..num_cpus { - let cpu_name = format!("cpu@{:x}", cpu_id); + let reg = u32::try_from( + cpu_mpidr_generator(cpu_id.try_into().unwrap()).ok_or(Error::PropertyValueInvalid)?, + ) + .map_err(|_| Error::PropertyValueTooLarge)?; + let cpu_name = format!("cpu@{:x}", reg); let cpu_node = cpus_node.subnode_mut(&cpu_name)?; cpu_node.set_prop("device_type", "cpu")?; cpu_node.set_prop("compatible", "arm,arm-v8")?; if num_cpus > 1 { cpu_node.set_prop("enable-method", "psci")?; } - cpu_node.set_prop("reg", cpu_id)?; + cpu_node.set_prop("reg", reg)?; cpu_node.set_prop("phandle", PHANDLE_CPU0 + cpu_id)?; if let Some(pwr_coefficient) = dynamic_power_coefficient.get(&(cpu_id as usize)) { @@ -625,6 +630,7 @@ pub fn create_fdt( 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>>, @@ -676,6 +682,7 @@ pub fn create_fdt( create_cpu_nodes( &mut fdt, num_cpus, + cpu_mpidr_generator, cpu_clusters, cpu_capacity, dynamic_power_coefficient, diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs index b97b896aa..5c997c463 100644 --- a/aarch64/src/lib.rs +++ b/aarch64/src/lib.rs @@ -372,6 +372,12 @@ fn get_block_size() -> u64 { block_size as u64 } +fn get_vcpu_mpidr_aff<Vcpu: VcpuAArch64>(vcpus: &[Vcpu], index: usize) -> Option<u64> { + const MPIDR_AFF_MASK: u64 = 0xff_00ff_ffff; + + Some(vcpus.get(index)?.get_mpidr().ok()? & MPIDR_AFF_MASK) +} + impl arch::LinuxArch for AArch64 { type Error = Error; @@ -766,6 +772,7 @@ impl arch::LinuxArch for AArch64 { &pci_ranges, dev_resources, vcpu_count as u32, + &|n| get_vcpu_mpidr_aff(&vcpus, n), components.cpu_clusters, components.cpu_capacity, components.cpu_frequencies, |