Skip to content

Commit 1ee3362

Browse files
psurplyjlrivasp
authored andcommitted
lib: use whoami field to build core hierarchy
This change allows the core records to be placed dynamically in the decode output based on the fields present in the WHOAMI header field. For instance, when the PCORE record has the core_id and thread_id encoded in its WHOAMI, the register will now be decoded under: pcore.core0.thread0 When the ECORE record has the module_id and core_id encoded in its WHOAMI field, the registers will be placed under: ecore.module0.core0 Signed-off-by: Surply, Pierre <[email protected]>
1 parent c62132a commit 1ee3362

File tree

5 files changed

+84
-30
lines changed

5 files changed

+84
-30
lines changed

lib/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,13 @@
8282
//! let nodes = crashlog.decode(&mut cm);
8383
//!
8484
//! // Get the status register of the fourth MCA bank from the register tree.
85-
//! let status = nodes.get_by_path("core0.thread.arch_state.mca.bank3.status").unwrap();
85+
//! let status = nodes.get_by_path(
86+
//! "pcore.core0.thread0.thread.arch_state.mca.bank3.status"
87+
//! ).unwrap();
8688
//! assert_eq!(status.kind, NodeType::Field { value: 0xbe000000e1840400 });
8789
//!
8890
//! // Get the instruction pointer of the first core.
89-
//! let lip = nodes.get_by_path("core0.thread.arch_state.lip").unwrap();
91+
//! let lip = nodes.get_by_path("pcore.core0.thread0.thread.arch_state.lip").unwrap();
9092
//! assert_eq!(lip.kind, NodeType::Field { value: 0xfffff80577036530 });
9193
//! ```
9294
//!

lib/src/node.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,46 @@ impl Node {
177177
Some(ptr)
178178
}
179179

180+
/// Returns the value associated to the node if present.
181+
///
182+
/// # Examples
183+
///
184+
/// ```
185+
/// use intel_crashlog::prelude::*;
186+
///
187+
/// let field = Node::field("foo", 42);
188+
/// assert_eq!(field.value(), Some(42));
189+
/// let section = Node::section("bar");
190+
/// assert_eq!(section.value(), None);
191+
/// ```
192+
pub fn value(&self) -> Option<u64> {
193+
if let NodeType::Field { value } = self.kind {
194+
Some(value)
195+
} else {
196+
None
197+
}
198+
}
199+
200+
/// Returns the value of the field stored at the given path.
201+
///
202+
/// # Examples
203+
///
204+
/// ```
205+
/// use intel_crashlog::prelude::*;
206+
///
207+
/// let mut foo = Node::section("foo");
208+
/// foo.add(Node::field("bar", 42));
209+
/// let mut root = Node::root();
210+
/// root.add(foo);
211+
///
212+
/// assert_eq!(root.get_value_by_path("foo.bar"), Some(42));
213+
/// assert_eq!(root.get_value_by_path("foo"), None);
214+
/// assert_eq!(root.get_value_by_path("foo.baz"), None);
215+
/// ```
216+
pub fn get_value_by_path(&self, path: &str) -> Option<u64> {
217+
self.get_by_path(path).and_then(|node| node.value())
218+
}
219+
180220
fn merge_instance(&mut self, mut other: Node) {
181221
let mut instance = 0;
182222
let name = other.name.clone();

lib/src/record/core.rs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::Record;
55
use crate::Error;
66
#[cfg(feature = "collateral_manager")]
77
use crate::collateral::{CollateralManager, CollateralTree};
8-
use crate::node::{Node, NodeType};
8+
use crate::node::Node;
99
#[cfg(not(feature = "std"))]
1010
use alloc::format;
1111

@@ -15,33 +15,43 @@ impl Record {
1515
&self,
1616
cm: &mut CollateralManager<T>,
1717
) -> Result<Node, Error> {
18-
let mut section = Node::section("core");
19-
20-
for decode_def in ["layout_thread.csv", "layout_core.csv"] {
21-
if let Ok(thread) = self.decode_with_decode_def(cm, decode_def, 0) {
22-
let core_id = thread
23-
.children()
24-
.next()
25-
.and_then(|child| child.get_by_path("hdr.whoami.core_id"))
26-
.map(|core_id| &core_id.kind);
27-
if let Some(NodeType::Field { value }) = core_id {
28-
section.name = format!("core{value}");
29-
}
30-
section.merge(thread);
31-
}
32-
}
18+
let mut section = Node::section(self.header.record_type()?);
19+
20+
for subsection_name in ["thread", "core"] {
21+
let decode_def = format!("layout_{subsection_name}.csv");
22+
let Ok(mut root) = self.decode_with_decode_def(cm, &decode_def, 0) else {
23+
continue;
24+
};
3325

34-
if let Some(offset) = self.header.extended_record_offset() {
35-
for decode_def in ["layout_sq.csv", "layout_module.csv"] {
36-
if let Ok(node) = self.decode_with_decode_def(cm, decode_def, offset) {
37-
section.merge(node);
26+
if let Some(offset) = self.header.extended_record_offset() {
27+
for decode_def in ["layout_sq.csv", "layout_module.csv"] {
28+
let Ok(extension) = self.decode_with_decode_def(cm, decode_def, offset) else {
29+
continue;
30+
};
31+
32+
root.merge(extension);
3833
break;
3934
}
4035
}
36+
37+
let Some(subsection) = root.get(subsection_name) else {
38+
continue;
39+
};
40+
let hierarchy = ["module", "core", "thread"]
41+
.into_iter()
42+
.filter_map(|level| {
43+
subsection
44+
.get_value_by_path(&format!("hdr.whoami.{level}_id"))
45+
.map(|id| format!("{level}{id}"))
46+
});
47+
48+
section.create_hierarchy_from_iter(hierarchy).merge(root);
49+
50+
let mut root = Node::root();
51+
root.add(section);
52+
return Ok(root);
4153
}
4254

43-
let mut root = Node::root();
44-
root.add(section);
45-
Ok(root)
55+
Err(Error::MissingDecodeDefinitions(self.header.version.clone()))
4656
}
4757
}

lib/tests/core.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn lnc_three_strike_timeout() {
1111
let nodes = crashlog.decode(&mut cm);
1212

1313
let status = nodes
14-
.get_by_path("core0.thread.arch_state.mca.bank3.status")
14+
.get_by_path("pcore.core0.thread0.thread.arch_state.mca.bank3.status")
1515
.unwrap();
1616
assert_eq!(
1717
status.kind,
@@ -20,15 +20,17 @@ fn lnc_three_strike_timeout() {
2020
}
2121
);
2222

23-
let lip = nodes.get_by_path("core0.thread.arch_state.lip").unwrap();
23+
let lip = nodes
24+
.get_by_path("pcore.core0.thread0.thread.arch_state.lip")
25+
.unwrap();
2426
assert_eq!(
2527
lip.kind,
2628
NodeType::Field {
2729
value: 0xfffff80577036530
2830
}
2931
);
3032

31-
let entry = nodes.get_by_path("core0.sq.entry0").unwrap();
33+
let entry = nodes.get_by_path("pcore.core0.thread0.sq.entry0").unwrap();
3234
assert_eq!(
3335
entry.kind,
3436
NodeType::Field {

lib/tests/crashlog.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn core_box_header_type6() {
4646
let root = crashlog.decode(&mut cm);
4747

4848
let entry0 = root
49-
.get_by_path("processors.cpu0.die8.core0.sq.entry0")
49+
.get_by_path("processors.cpu0.die8.pcore.core0.thread0.sq.entry0")
5050
.unwrap();
5151

5252
assert_eq!(
@@ -62,7 +62,7 @@ fn core_box_header_type6() {
6262
assert_eq!(record_type_box.kind, NodeType::Field { value: 0x3d });
6363

6464
let bank3 = root
65-
.get_by_path("processors.cpu0.die8.core0.thread.arch_state.mca.bank3.status")
65+
.get_by_path("processors.cpu0.die8.pcore.core0.thread0.thread.arch_state.mca.bank3.status")
6666
.unwrap();
6767

6868
assert_eq!(

0 commit comments

Comments
 (0)