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
2 changes: 1 addition & 1 deletion plugins/solidigm/solidigm-nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "cmd.h"

#define SOLIDIGM_PLUGIN_VERSION "1.14"
#define SOLIDIGM_PLUGIN_VERSION "1.15"

PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
COMMAND_LIST(
Expand Down
14 changes: 10 additions & 4 deletions plugins/solidigm/solidigm-telemetry/data-area.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#define MAX_ARRAY_RANK 16
#define NLOG_HEADER_ID 101

static bool uint8_array_to_string(const struct telemetry_log *tl,
static bool uint8_array_try_string(const struct telemetry_log *tl,
uint64_t offset_bit, uint32_t size_bit,
uint32_t array_size,
struct json_object **str_obj)
Expand Down Expand Up @@ -54,6 +54,11 @@ static bool uint8_array_to_string(const struct telemetry_log *tl,
if (data_ptr[actual_length] == '\0')
break;
}
// making sure trailing bytes are nulls
for (size_t i = actual_length; i < array_size; i++) {
if (data_ptr[i] != '\0')
return false;
}

// Create JSON string directly from the data without intermediate buffer
*str_obj = json_object_new_string_len((const char *)data_ptr, actual_length);
Expand Down Expand Up @@ -292,12 +297,13 @@ int sldm_telemetry_structure_parse(const struct telemetry_log *tl,

if (array_size_dimension[0] > 1 || force_array) {
// Check if this is a UINT8 array that should be treated as a string
if (strcmp(type, "UINT8") == 0 && !force_array) {
if (json_object_is_type(output, json_type_object) &&
(strcmp(type, "UINT8") == 0 || strcmp(type, "uint8_t") == 0) && !force_array) {
// Handle UINT8 arrays as strings
struct json_object *str_obj = NULL;
uint64_t offset = parent_offset_bit + offset_bit;

if (uint8_array_to_string(tl, offset, size_bit,
if (uint8_array_try_string(tl, offset, size_bit,
array_size_dimension[0], &str_obj)) {
json_object_object_add(output, name, str_obj);
return 0;
Expand All @@ -308,7 +314,7 @@ int sldm_telemetry_structure_parse(const struct telemetry_log *tl,
}

sub_output = json_create_array();
if (json_object_get_type(output) == json_type_array)
if (json_object_is_type(output, json_type_array))
json_object_array_add(output, sub_output);
else
json_object_add_value_array(output, name, sub_output);
Expand Down
316 changes: 316 additions & 0 deletions plugins/solidigm/solidigm-telemetry/debug-info.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
// SPDX-License-Identifier: MIT
/*
* Copyright (c) 2025 Solidigm.
*
* Author: [email protected]
*/

#include "debug-info.h"
#include "common.h"
#include "config.h"
#include "data-area.h"
#include "skht.h"
#include "tracker.h"
#include "uart-log.h"
#include "util/json.h"
#include <string.h>

#define DEBUG_INFO_SIGNATURE 0x54321234 /* "ST21" */
#define MAX_DEBUG_INFO_CORES 255

enum debug_info_id {
DEBUG_INFO_ID_UART_LOG = 3,
DEBUG_INFO_ID_TRACKER_INFO = 6,
DEBUG_INFO_ID_TRACKER_BUFFER = 7,
DEBUG_INFO_ID_TRACKER_CONTEXT = 8,
};

int sldm_debug_info_parse(struct telemetry_log *tl, uint32_t offset, uint32_t size,
struct json_object *output)
{
struct json_object *debug_info_blk_header_def = NULL;
struct json_object *debug_info_header_def = NULL;
struct json_object *debug_info_seg_header_def = NULL;
struct json_object *cores_array = NULL;
struct json_object *segments_array = NULL;
uint64_t current_offset_bit;
uint32_t current_offset_byte;
int counter = 0;
int err = 0;

if (!tl || !tl->configuration || !output) {
SOLIDIGM_LOG_WARNING("Invalid parameters for debug info parsing");
return -1;
}

if (offset + size > tl->log_size) {
SOLIDIGM_LOG_WARNING("Debug info data exceeds log size");
return -1;
}

/* Get structure definitions from configuration */
if (!sldm_config_get_struct_by_key_version(tl->configuration,
"DebugInfoBlkHeader_t",
SKT_VER_MAJOR, SKT_VER_MINOR,
&debug_info_blk_header_def)) {
SOLIDIGM_LOG_WARNING("DebugInfoBlkHeader_t structure not found in config");
return -1;
}

if (!sldm_config_get_struct_by_key_version(tl->configuration,
"DebugInfoHeader_t",
SKT_VER_MAJOR, SKT_VER_MINOR,
&debug_info_header_def)) {
SOLIDIGM_LOG_WARNING("DebugInfoHeader_t structure not found in config");
return -1;
}

if (!sldm_config_get_struct_by_key_version(tl->configuration,
"DebugInfoSegHeader_t",
SKT_VER_MAJOR, SKT_VER_MINOR,
&debug_info_seg_header_def)) {
SOLIDIGM_LOG_WARNING("DebugInfoSegHeader_t structure not found in config");
return -1;
}

/* Parse Debug Info Block Header */
current_offset_bit = offset * 8;
err = sldm_telemetry_structure_parse(tl, debug_info_blk_header_def,
current_offset_bit, output, NULL);
if (err) {
SOLIDIGM_LOG_WARNING("Failed to parse DebugInfoBlkHeader_t");
return err;
}

/* Get the size of DebugInfoBlkHeader_t to move to the next structure */
struct json_object *blk_header_size_obj = NULL;

if (json_object_object_get_ex(debug_info_blk_header_def, "sizeBit",
&blk_header_size_obj)) {
uint32_t blk_header_size_bits = json_object_get_int(blk_header_size_obj);

current_offset_bit += blk_header_size_bits;
} else {
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoBlkHeader_t size");
return -1;
}

/* Create arrays for cores and segments */
cores_array = json_create_array();
segments_array = json_create_array();
json_object_add_value_array(output, "Cores", cores_array);
json_object_add_value_array(output, "Segments", segments_array);

/* Parse Debug Info Headers for each core */
current_offset_byte = (uint32_t)(current_offset_bit / 8);

while (current_offset_byte < (offset + size) && counter < MAX_DEBUG_INFO_CORES) {
uint64_t core_offset_bit = current_offset_bit;
struct json_object *core_debug_info = json_create_object();
struct json_object *signature_obj = NULL;
uint32_t debug_signature = 0;
uint32_t total_bytes = 0;
uint32_t num_segments = 0;
uint32_t core_id = 0;

/* Check if we have enough space for the debug info header */
if (current_offset_byte + sizeof(uint32_t) > (offset + size)) {
json_free_object(core_debug_info);
break;
}

/* Parse DebugInfoHeader_t */
err = sldm_telemetry_structure_parse(tl, debug_info_header_def,
current_offset_bit,
core_debug_info, NULL);
if (err) {
SOLIDIGM_LOG_WARNING("Failed to parse DebugInfoHeader_t for core %d",
counter);
json_free_object(core_debug_info);
break;
}

/* Validate signature */
struct json_object *debug_info_header_obj = NULL;

if (json_object_object_get_ex(core_debug_info, "DebugInfoHeader_t",
&debug_info_header_obj) &&
json_object_object_get_ex(debug_info_header_obj, "nSignature",
&signature_obj)) {
debug_signature = json_object_get_int(signature_obj);
}

if (debug_signature != DEBUG_INFO_SIGNATURE) {
json_free_object(core_debug_info);
break;
}

/* Get total bytes and number of segments */
struct json_object *total_bytes_obj = NULL;
struct json_object *num_segments_obj = NULL;
struct json_object *core_id_obj = NULL;

if (json_object_object_get_ex(debug_info_header_obj, "nTotalBytes",
&total_bytes_obj))
total_bytes = json_object_get_int(total_bytes_obj);

if (json_object_object_get_ex(debug_info_header_obj, "nNumSegments",
&num_segments_obj))
num_segments = json_object_get_int(num_segments_obj);

if (json_object_object_get_ex(debug_info_header_obj, "nCoreId",
&core_id_obj))
core_id = json_object_get_int(core_id_obj);

/* Add core info to the cores array */
json_object_array_add(cores_array, core_debug_info);

/* Move to the position after DebugInfoHeader_t */
struct json_object *header_size_obj = NULL;

if (json_object_object_get_ex(debug_info_header_def, "sizeBit",
&header_size_obj)) {
uint32_t header_size_bits = json_object_get_int(header_size_obj);

current_offset_bit += header_size_bits;
current_offset_byte = (uint32_t)(current_offset_bit / 8);
} else {
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoHeader_t size");
break;
}

/* Parse segment headers for this core */
for (uint32_t seg = 0; seg < num_segments && seg < 16; seg++) {
struct json_object *tracker_info = NULL;
struct json_object *debug_info_uart_log = NULL;
struct json_object *segment_info = json_create_object();
char *tracker_log_name = NULL;

/* Check bounds */
if (current_offset_byte >= (offset + size)) {
json_free_object(segment_info);
break;
}

/* Parse DebugInfoSegHeader_t */
err = sldm_telemetry_structure_parse(tl,
debug_info_seg_header_def,
current_offset_bit,
segment_info, NULL);
if (err) {
SOLIDIGM_LOG_WARNING(
"Failed to parse DebugInfoSegHeader_t for core %d, seg %d",
core_id, seg);
json_free_object(segment_info);
break;
}

/* Add core and segment identifiers */
json_object_add_value_uint(segment_info, "CoreId", core_id);
json_object_add_value_uint(segment_info, "SegmentIndex", seg);

/* Add segment to segments array */
json_object_array_add(segments_array, segment_info);

/* Move to next segment header */
struct json_object *seg_header_size_obj = NULL;

if (json_object_object_get_ex(debug_info_seg_header_def,
"sizeBit",
&seg_header_size_obj)) {
uint32_t seg_header_size_bits;

seg_header_size_bits = json_object_get_int(seg_header_size_obj);
current_offset_bit += seg_header_size_bits;
current_offset_byte = (uint32_t)(current_offset_bit / 8);
} else {
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoHeader_t size");
json_free_object(segment_info);
break;
}
// Get DebugInfoSegHeader_t size for logging
struct json_object *debug_info_seg_header_obj = NULL;
struct json_object *size_obj = NULL;
uint32_t debug_info_seg_size = 0;

if (json_object_object_get_ex(segment_info, "DebugInfoSegHeader_t",
&debug_info_seg_header_obj) &&
json_object_object_get_ex(debug_info_seg_header_obj, "nSize",
&size_obj)) {
debug_info_seg_size = json_object_get_int(size_obj);
} else {
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoSegHeader_t size");
json_free_object(segment_info);
break;
}

struct json_object *id_obj = NULL;
uint32_t debug_info_seg_id = 0;

if (json_object_object_get_ex(debug_info_seg_header_obj, "nId",
&id_obj)) {
debug_info_seg_id = json_object_get_int(id_obj);
} else {
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoSegHeader_t id");
json_free_object(segment_info);
break;
}
switch (debug_info_seg_id) {
case DEBUG_INFO_ID_UART_LOG:
debug_info_uart_log = json_create_object();
if (!debug_info_uart_log) {
SOLIDIGM_LOG_WARNING(
"Failed to create JSON object for UART log");
json_free_object(segment_info);
break;
}
sldm_parse_cd_uart_log(tl, current_offset_byte,
debug_info_seg_size,
debug_info_uart_log);
json_object_object_add(segment_info, "DebugInfoUartLog",
debug_info_uart_log);
break;
case DEBUG_INFO_ID_TRACKER_INFO:
tracker_log_name = "TrackerInfo";
case DEBUG_INFO_ID_TRACKER_BUFFER:
if (!tracker_log_name)
tracker_log_name = "TrackerBuffer";
case DEBUG_INFO_ID_TRACKER_CONTEXT:
if (!tracker_log_name)
tracker_log_name = "TrackerContext";

tracker_info = json_create_object();
if (!tracker_info) {
SOLIDIGM_LOG_WARNING(
"Failed to create JSON object for tracker info");
json_free_object(segment_info);
break;
}
sldm_tracker_parse(tl, current_offset_byte,
debug_info_seg_size, tracker_info);

// Add tracker info to segment
json_object_object_add(segment_info, tracker_log_name,
tracker_info);
break;
}

current_offset_bit += debug_info_seg_size * 8;
current_offset_byte = (uint32_t)(current_offset_bit / 8);
}

/* Move to the next core based on total_bytes */
if (total_bytes > 0) {
current_offset_bit = core_offset_bit + total_bytes * 8;
current_offset_byte = (uint32_t)(current_offset_bit / 8);
}

counter++;
if (counter >= MAX_DEBUG_INFO_CORES) {
SOLIDIGM_LOG_WARNING("Attempted to parse debug info for %d cores.",
counter);
break;
}
}
return 0;
}
21 changes: 21 additions & 0 deletions plugins/solidigm/solidigm-telemetry/debug-info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright (c) 2025 Solidigm.
*
* Author: [email protected]
*/

#ifndef SLDM_DEBUG_INFO_H
#define SLDM_DEBUG_INFO_H

#include "telemetry-log.h"
#include "util/json.h"

/**
* Parse debug info data from telemetry log

*/
int sldm_debug_info_parse(struct telemetry_log *tl, uint32_t offset, uint32_t size,
struct json_object *output);

#endif /* SLDM_DEBUG_INFO_H */
Loading