From 9b17b26ac7288fb0ce45487a546955ce84ac9ae0 Mon Sep 17 00:00:00 2001 From: Changyuan Lyu Date: Tue, 30 Dec 2025 14:10:03 -0800 Subject: [PATCH] refactor(aarch64): decouple DT cpu-map and MPIDR allocation Signed-off-by: Changyuan Lyu --- alioth/src/board/board.rs | 7 +- alioth/src/board/board_aarch64.rs | 120 ++++++++++++------------------ alioth/src/board/board_test.rs | 21 ++++++ alioth/src/board/board_x86_64.rs | 2 +- 4 files changed, 74 insertions(+), 76 deletions(-) diff --git a/alioth/src/board/board.rs b/alioth/src/board/board.rs index 9c9fb9d0..cdd3451d 100644 --- a/alioth/src/board/board.rs +++ b/alioth/src/board/board.rs @@ -122,7 +122,12 @@ impl CpuTopology { let thread_id = index / total_cores; let core_id = index % total_cores % self.cores; let socket_id = index % total_cores / self.cores; - (thread_id as u8, core_id, socket_id as u8) + (socket_id as u8, core_id, thread_id as u8) + } + + pub fn decode(&self, socket_id: u8, core_id: u16, thread_id: u8) -> u16 { + let total_cores = self.cores * self.sockets as u16; + thread_id as u16 * total_cores + core_id + socket_id as u16 * self.cores } } diff --git a/alioth/src/board/board_aarch64.rs b/alioth/src/board/board_aarch64.rs index 637e15f0..c7acc9b8 100644 --- a/alioth/src/board/board_aarch64.rs +++ b/alioth/src/board/board_aarch64.rs @@ -92,7 +92,7 @@ impl ArchBoard { } fn encode_mpidr(topology: &CpuTopology, index: u16) -> MpidrEl1 { - let (thread_id, core_id, socket_id) = topology.encode(index); + let (socket_id, core_id, thread_id) = topology.encode(index); let mut mpidr = MpidrEl1(0); mpidr.set_aff0(thread_id); mpidr.set_aff1(core_id as u8); @@ -100,44 +100,6 @@ fn encode_mpidr(topology: &CpuTopology, index: u16) -> MpidrEl1 { mpidr } -fn dt_cpu_node(topology: &CpuTopology, socket: u8, core: u16) -> Node { - let mut mpidr = MpidrEl1(0); - mpidr.set_aff1(core as u8); - mpidr.set_aff2(socket); - if topology.smt { - Node { - props: HashMap::new(), - nodes: vec![ - ( - "thread0".to_owned(), - Node { - props: HashMap::from([( - "cpu", - PropVal::PHandle(PHANDLE_CPU | mpidr.0 as u32), - )]), - nodes: Vec::new(), - }, - ), - ( - "thread1".to_owned(), - Node { - props: HashMap::from([( - "cpu", - PropVal::PHandle(PHANDLE_CPU | mpidr.0 as u32 | 1), - )]), - nodes: Vec::new(), - }, - ), - ], - } - } else { - Node { - nodes: Vec::new(), - props: HashMap::from([("cpu", PropVal::PHandle(PHANDLE_CPU | mpidr.0 as u32))]), - } - } -} - impl Board where V: Vm, @@ -259,7 +221,48 @@ where } pub fn create_cpu_nodes(&self, root: &mut Node) { - let mut cpu_nodes: Vec<_> = (0..(self.config.cpu.count)) + let topology = &self.config.cpu.topology; + + let thread_node = |socket_id: u8, core_id: u16, thread_id: u8| { + let phandle = PHANDLE_CPU | topology.decode(socket_id, core_id, thread_id) as u32; + Node { + props: HashMap::from([("cpu", PropVal::PHandle(phandle))]), + nodes: Vec::new(), + } + }; + let core_node = |socket_id: u8, core_id: u16| { + if topology.smt { + Node { + props: HashMap::new(), + nodes: vec![ + ("thread0".to_owned(), thread_node(socket_id, core_id, 0)), + ("thread1".to_owned(), thread_node(socket_id, core_id, 1)), + ], + } + } else { + thread_node(socket_id, core_id, 0) + } + }; + let socket_node = |socket_id: u8| Node { + props: HashMap::new(), + nodes: vec![( + "cluster0".to_owned(), + Node { + props: HashMap::new(), + nodes: (0..topology.cores) + .map(|core_id| (format!("core{core_id}"), core_node(socket_id, core_id))) + .collect(), + }, + )], + }; + let cpu_map_node = Node { + props: HashMap::new(), + nodes: (0..topology.sockets) + .map(|socket_id| (format!("socket{socket_id}"), socket_node(socket_id))) + .collect(), + }; + + let cpus_nodes = (0..(self.config.cpu.count)) .map(|index| { let mpidr = self.encode_cpu_identity(index); ( @@ -270,52 +273,21 @@ where ("compatible", PropVal::Str("arm,arm-v8")), ("enable-method", PropVal::Str("psci")), ("reg", PropVal::U64(mpidr)), - ("phandle", PropVal::PHandle(PHANDLE_CPU | mpidr as u32)), + ("phandle", PropVal::PHandle(PHANDLE_CPU | index as u32)), ]), nodes: Vec::new(), }, ) }) + .chain([("cpu-map".to_owned(), cpu_map_node)]) .collect(); - let cpu_map = Node { - props: HashMap::new(), - nodes: (0..self.config.cpu.topology.sockets) - .map(|socket| { - ( - format!("socket{socket}",), - Node { - props: HashMap::new(), - nodes: vec![( - "cluster0".to_owned(), - Node { - props: HashMap::new(), - nodes: (0..self.config.cpu.topology.cores) - .map(|core| { - ( - format!("core{core}"), - dt_cpu_node( - &self.config.cpu.topology, - socket, - core, - ), - ) - }) - .collect(), - }, - )], - }, - ) - }) - .collect(), - }; - cpu_nodes.push(("cpu-map".to_owned(), cpu_map)); let cpus = Node { props: HashMap::from([ ("#address-cells", PropVal::U32(2)), ("#size-cells", PropVal::U32(0)), ]), - nodes: cpu_nodes, + nodes: cpus_nodes, }; root.nodes.push(("cpus".to_owned(), cpus)); } diff --git a/alioth/src/board/board_test.rs b/alioth/src/board/board_test.rs index 6aaac5a4..1ef83c86 100644 --- a/alioth/src/board/board_test.rs +++ b/alioth/src/board/board_test.rs @@ -13,6 +13,7 @@ // limitations under the License. use assert_matches::assert_matches; +use rstest::rstest; use crate::board::{CpuConfig, CpuTopology, Error}; @@ -45,3 +46,23 @@ fn test_cpu_topology_fixup() { }; assert_matches!(invalid.fixup(), Err(Error::InvalidCpuTopology { .. })) } + +#[rstest] +#[case(CpuTopology{smt: false, cores: 1, sockets: 1}, 0, (0, 0, 0))] +#[case(CpuTopology{smt: true, cores: 2, sockets: 1}, 0, (0, 0, 0))] +#[case(CpuTopology{smt: true, cores: 2, sockets: 1}, 1, (0, 1, 0))] +#[case(CpuTopology{smt: true, cores: 2, sockets: 1}, 2, (0, 0, 1))] +#[case(CpuTopology{smt: true, cores: 2, sockets: 1}, 3, (0, 1, 1))] +#[case(CpuTopology{smt: true, cores: 6, sockets: 2}, 4, (0, 4, 0))] +#[case(CpuTopology{smt: true, cores: 6, sockets: 2}, 11, (1, 5, 0))] +#[case(CpuTopology{smt: true, cores: 6, sockets: 2}, 14, (0, 2, 1))] +#[case(CpuTopology{smt: true, cores: 6, sockets: 2}, 23, (1, 5, 1))] +fn test_cpu_topology_encode_decode( + #[case] topology: CpuTopology, + #[case] index: u16, + #[case] ids: (u8, u16, u8), +) { + assert_eq!(topology.encode(index), ids); + let (socket_id, core_id, thread_id) = ids; + assert_eq!(topology.decode(socket_id, core_id, thread_id), index); +} diff --git a/alioth/src/board/board_x86_64.rs b/alioth/src/board/board_x86_64.rs index 76c6e474..ef80d1ce 100644 --- a/alioth/src/board/board_x86_64.rs +++ b/alioth/src/board/board_x86_64.rs @@ -156,7 +156,7 @@ impl ArchBoard { } fn encode_x2apic_id(topology: &CpuTopology, index: u16) -> u32 { - let (thread_id, core_id, socket_id) = topology.encode(index); + let (socket_id, core_id, thread_id) = topology.encode(index); let thread_width = topology.smt as u32; let cores_per_socket = topology.cores as u32;