aboutsummaryrefslogtreecommitdiff
path: root/aarch64
diff options
context:
space:
mode:
authorPierre-Clément Tosi <ptosi@google.com>2024-03-21 15:42:57 +0000
committercrosvm LUCI <crosvm-scoped@luci-project-accounts.iam.gserviceaccount.com>2024-03-28 13:26:29 +0000
commit9a4a79a44791da6927b92195a804acb010ea1e29 (patch)
treebaf558629753c139c02cf0323e514e5c662c3a81 /aarch64
parent3b29c72913c076ca537355d0270c8a3419477ec1 (diff)
downloadcrosvm-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.rs11
-rw-r--r--aarch64/src/lib.rs7
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,