Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions lib/src/errata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ pub struct Errata {
/// The Crash Log headers have their sizes in DWORDs, but for some products that are using
/// ECORE and PCORE Crash Log records, their sizes are written in bytes.
pub core_record_size_bytes: bool,

/// Type0 legacy header
///
/// Some Intel(R) products in the discrete GPU segment are using legacy Crash Log record
/// headers with type0, which has a different layout compared with the currently defined Type0
/// Header.
pub type0_legacy_gpu: bool,
}

const GNR_SP_PRODUCT_ID: u32 = 0x2f;
Expand All @@ -38,10 +45,25 @@ const CWF_SP_PRODUCT_ID: u32 = 0x8e;
const SERVER_LEGACY_PRODUCT_IDS: [u32; 3] =
[GNR_SP_PRODUCT_ID, SRF_SP_PRODUCT_ID, CWF_SP_PRODUCT_ID];

const BMG_X3_PRODUCT_ID: u32 = 0x5d;
const BMG_G31_PRODUCT_ID: u32 = 0x5e;
const BMG_X2_PRODUCT_ID: u32 = 0x5f;
const CRI_PRODUCT_ID: u32 = 0xb6;
const GPU_LEGACY_PRODUCT_IDS: [u32; 4] = [
BMG_X3_PRODUCT_ID,
BMG_G31_PRODUCT_ID,
BMG_X2_PRODUCT_ID,
CRI_PRODUCT_ID,
];

impl Errata {
pub fn from_version(version: &Version) -> Self {
let type0_legacy_server =
version.header_type == 0 && SERVER_LEGACY_PRODUCT_IDS.contains(&version.product_id);

let type0_legacy_gpu =
version.header_type == 0 && GPU_LEGACY_PRODUCT_IDS.contains(&version.product_id);

let type0_legacy_server_box =
type0_legacy_server && version.record_type == record_types::PCORE;

Expand All @@ -52,12 +74,14 @@ impl Errata {
&& (version.product_id < 0x71 || version.product_id == CGC_PRODUCT_ID);

let core_record_size_bytes = !type0_legacy_server
&& !type0_legacy_gpu
&& (ecore_record_with_size_in_bytes || pcore_record_with_size_in_bytes);

Errata {
type0_legacy_server,
type0_legacy_server_box,
core_record_size_bytes,
type0_legacy_gpu,
}
}
}
56 changes: 52 additions & 4 deletions lib/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ pub enum HeaderType {
completion_status: u32,
collection_complete: bool,
},

Type0LegacyGpu {
timestamp: u64,
agent_version: u32,
reason: u32,
completion_status: u32,
collection_complete: bool,
},
}

impl HeaderType {
Expand Down Expand Up @@ -218,6 +226,23 @@ impl HeaderType {
})
}

fn type0_legacy_gpu_from_slice(slice: &[u8]) -> Option<Self> {
let reason = u32::from_le_bytes(slice.get(4..8)?.try_into().ok()?);
let timestamp = u64::from_le_bytes(slice.get(8..16)?.try_into().ok()?);
let agent_version = u32::from_le_bytes(slice.get(20..24)?.try_into().ok()?);
let cs_data = u32::from_le_bytes(slice.get(28..32)?.try_into().ok()?);
let completion_status = cs_data & 0x7FFFFFFF;
let collection_complete = (cs_data >> 31) != 0;

Some(HeaderType::Type0LegacyGpu {
timestamp,
agent_version,
reason,
completion_status,
collection_complete,
})
}

pub fn from_slice(header_type_value: u16, slice: &[u8]) -> Result<Self, Error> {
match header_type_value {
0 => Ok(HeaderType::Type0),
Expand All @@ -234,6 +259,10 @@ impl HeaderType {
pub fn from_slice_type0_legacy_server(slice: &[u8]) -> Result<Self, Error> {
Self::type0_legacy_server_from_slice(slice).ok_or(Error::InvalidHeader)
}

pub fn from_slice_type0_legacy_gpu(slice: &[u8]) -> Result<Self, Error> {
Self::type0_legacy_gpu_from_slice(slice).ok_or(Error::InvalidHeader)
}
}

/// Header of a Crash Log record
Expand All @@ -256,14 +285,16 @@ impl Header {
};
let errata = Errata::from_version(&version);

let size = if errata.type0_legacy_server {
RecordSize::from_slice_type0_legacy_server(slice).ok_or(Error::InvalidHeader)?
let size = if errata.type0_legacy_server || errata.type0_legacy_gpu {
RecordSize::from_slice_type0_legacy(slice).ok_or(Error::InvalidHeader)?
} else {
RecordSize::from_slice(slice).ok_or(Error::InvalidHeader)?
};

let header_type = if errata.type0_legacy_server {
HeaderType::from_slice_type0_legacy_server(slice)?
} else if errata.type0_legacy_gpu {
HeaderType::from_slice_type0_legacy_gpu(slice)?
} else {
HeaderType::from_slice(version.header_type, slice)?
};
Expand Down Expand Up @@ -428,6 +459,7 @@ impl Header {
..
} => 28 + completion_status_size as usize * 4,
HeaderType::Type0LegacyServer { .. } => 32,
HeaderType::Type0LegacyGpu { .. } => 32,
}
}

Expand Down Expand Up @@ -580,8 +612,8 @@ impl RecordSize {
})
}

/// Creates a [RecordSize] from the raw record of a server product with legacy header type0
pub fn from_slice_type0_legacy_server(slice: &[u8]) -> Option<Self> {
/// Creates a [RecordSize] from the raw record of a product with legacy header type0
pub fn from_slice_type0_legacy(slice: &[u8]) -> Option<Self> {
Some(RecordSize {
record_size: u16::from_le_bytes(slice.get(16..18)?.try_into().ok()?),
extended_record_size: 0,
Expand Down Expand Up @@ -736,6 +768,22 @@ impl From<&Header> for Node {
collection_complete as u64,
));
}
HeaderType::Type0LegacyGpu {
timestamp,
agent_version,
reason,
completion_status,
collection_complete,
} => {
node.add(Node::field("timestamp", timestamp));
node.add(Node::field("agent_version", agent_version as u64));
node.add(Node::field("reason", reason as u64));
node.add(Node::field("completion_status", completion_status as u64));
node.add(Node::field(
"record_collection_completed",
collection_complete as u64,
));
}
_ => (),
}

Expand Down
24 changes: 22 additions & 2 deletions lib/tests/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ fn decode_die_id_header() {
}

#[test]
fn decode_legacy_header_type0() {
let data = fs::read("tests/samples/legacy_type0.crashlog").unwrap();
fn decode_legacy_header_type0_server() {
let data = fs::read("tests/samples/legacy_type0_server.crashlog").unwrap();
let header = Header::from_slice(&data).unwrap().unwrap();

let socket_id = header.socket_id();
Expand All @@ -83,3 +83,23 @@ fn decode_legacy_header_type0() {
let die_id = header.die_id().unwrap();
assert_eq!(die_id, 10);
}

#[test]
fn decode_legacy_header_type0_gpu() {
let data = fs::read("tests/samples/legacy_type0_gpu.crashlog").unwrap();
let header = Header::from_slice(&data).unwrap().unwrap();

let socket_id = header.socket_id();
assert_eq!(socket_id, 0);

let die_id = header.die_id();
assert_eq!(die_id, None);

let node = Node::from(&header);
assert_eq!(
node.get_by_path("record_collection_completed")
.unwrap()
.kind,
NodeType::Field { value: 1 }
);
}
2 changes: 1 addition & 1 deletion lib/tests/record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ fn box_header_type6() {
#[test]
fn header_type0_legacy_server() {
let mut cm = CollateralManager::file_system_tree(Path::new(COLLATERAL_TREE_PATH)).unwrap();
let data = fs::read("tests/samples/legacy_type0.crashlog").unwrap();
let data = fs::read("tests/samples/legacy_type0_server.crashlog").unwrap();

let crashlog = CrashLog::from_slice(&data).unwrap();

Expand Down
Binary file added lib/tests/samples/legacy_type0_gpu.crashlog
Binary file not shown.
Loading