Skip to content

Commit 494cb3a

Browse files
lgdacunhigaw
authored andcommitted
plugins/solidigm: Added debug info to parse-telemetry-log.
Parsing UART and Tracker logs contained in Debug Info. Signed-off-by: Leonardo da Cunha <[email protected]>
1 parent 8cfb8c7 commit 494cb3a

File tree

8 files changed

+495
-5
lines changed

8 files changed

+495
-5
lines changed

plugins/solidigm/solidigm-nvme.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#include "cmd.h"
1515

16-
#define SOLIDIGM_PLUGIN_VERSION "1.14"
16+
#define SOLIDIGM_PLUGIN_VERSION "1.15"
1717

1818
PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
1919
COMMAND_LIST(

plugins/solidigm/solidigm-telemetry/data-area.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#define MAX_ARRAY_RANK 16
2222
#define NLOG_HEADER_ID 101
2323

24-
static bool uint8_array_to_string(const struct telemetry_log *tl,
24+
static bool uint8_array_try_string(const struct telemetry_log *tl,
2525
uint64_t offset_bit, uint32_t size_bit,
2626
uint32_t array_size,
2727
struct json_object **str_obj)
@@ -54,6 +54,11 @@ static bool uint8_array_to_string(const struct telemetry_log *tl,
5454
if (data_ptr[actual_length] == '\0')
5555
break;
5656
}
57+
// making sure trailing bytes are nulls
58+
for (size_t i = actual_length; i < array_size; i++) {
59+
if (data_ptr[i] != '\0')
60+
return false;
61+
}
5762

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

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

300-
if (uint8_array_to_string(tl, offset, size_bit,
306+
if (uint8_array_try_string(tl, offset, size_bit,
301307
array_size_dimension[0], &str_obj)) {
302308
json_object_object_add(output, name, str_obj);
303309
return 0;
@@ -308,7 +314,7 @@ int sldm_telemetry_structure_parse(const struct telemetry_log *tl,
308314
}
309315

310316
sub_output = json_create_array();
311-
if (json_object_get_type(output) == json_type_array)
317+
if (json_object_is_type(output, json_type_array))
312318
json_object_array_add(output, sub_output);
313319
else
314320
json_object_add_value_array(output, name, sub_output);
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
// SPDX-License-Identifier: MIT
2+
/*
3+
* Copyright (c) 2025 Solidigm.
4+
*
5+
6+
*/
7+
8+
#include "debug-info.h"
9+
#include "common.h"
10+
#include "config.h"
11+
#include "data-area.h"
12+
#include "skht.h"
13+
#include "tracker.h"
14+
#include "uart-log.h"
15+
#include "util/json.h"
16+
#include <string.h>
17+
18+
#define DEBUG_INFO_SIGNATURE 0x54321234 /* "ST21" */
19+
#define MAX_DEBUG_INFO_CORES 255
20+
21+
enum debug_info_id {
22+
DEBUG_INFO_ID_UART_LOG = 3,
23+
DEBUG_INFO_ID_TRACKER_INFO = 6,
24+
DEBUG_INFO_ID_TRACKER_BUFFER = 7,
25+
DEBUG_INFO_ID_TRACKER_CONTEXT = 8,
26+
};
27+
28+
int sldm_debug_info_parse(struct telemetry_log *tl, uint32_t offset, uint32_t size,
29+
struct json_object *output)
30+
{
31+
struct json_object *debug_info_blk_header_def = NULL;
32+
struct json_object *debug_info_header_def = NULL;
33+
struct json_object *debug_info_seg_header_def = NULL;
34+
struct json_object *cores_array = NULL;
35+
struct json_object *segments_array = NULL;
36+
uint64_t current_offset_bit;
37+
uint32_t current_offset_byte;
38+
int counter = 0;
39+
int err = 0;
40+
41+
if (!tl || !tl->configuration || !output) {
42+
SOLIDIGM_LOG_WARNING("Invalid parameters for debug info parsing");
43+
return -1;
44+
}
45+
46+
if (offset + size > tl->log_size) {
47+
SOLIDIGM_LOG_WARNING("Debug info data exceeds log size");
48+
return -1;
49+
}
50+
51+
/* Get structure definitions from configuration */
52+
if (!sldm_config_get_struct_by_key_version(tl->configuration,
53+
"DebugInfoBlkHeader_t",
54+
SKT_VER_MAJOR, SKT_VER_MINOR,
55+
&debug_info_blk_header_def)) {
56+
SOLIDIGM_LOG_WARNING("DebugInfoBlkHeader_t structure not found in config");
57+
return -1;
58+
}
59+
60+
if (!sldm_config_get_struct_by_key_version(tl->configuration,
61+
"DebugInfoHeader_t",
62+
SKT_VER_MAJOR, SKT_VER_MINOR,
63+
&debug_info_header_def)) {
64+
SOLIDIGM_LOG_WARNING("DebugInfoHeader_t structure not found in config");
65+
return -1;
66+
}
67+
68+
if (!sldm_config_get_struct_by_key_version(tl->configuration,
69+
"DebugInfoSegHeader_t",
70+
SKT_VER_MAJOR, SKT_VER_MINOR,
71+
&debug_info_seg_header_def)) {
72+
SOLIDIGM_LOG_WARNING("DebugInfoSegHeader_t structure not found in config");
73+
return -1;
74+
}
75+
76+
/* Parse Debug Info Block Header */
77+
current_offset_bit = offset * 8;
78+
err = sldm_telemetry_structure_parse(tl, debug_info_blk_header_def,
79+
current_offset_bit, output, NULL);
80+
if (err) {
81+
SOLIDIGM_LOG_WARNING("Failed to parse DebugInfoBlkHeader_t");
82+
return err;
83+
}
84+
85+
/* Get the size of DebugInfoBlkHeader_t to move to the next structure */
86+
struct json_object *blk_header_size_obj = NULL;
87+
88+
if (json_object_object_get_ex(debug_info_blk_header_def, "sizeBit",
89+
&blk_header_size_obj)) {
90+
uint32_t blk_header_size_bits = json_object_get_int(blk_header_size_obj);
91+
92+
current_offset_bit += blk_header_size_bits;
93+
} else {
94+
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoBlkHeader_t size");
95+
return -1;
96+
}
97+
98+
/* Create arrays for cores and segments */
99+
cores_array = json_create_array();
100+
segments_array = json_create_array();
101+
json_object_add_value_array(output, "Cores", cores_array);
102+
json_object_add_value_array(output, "Segments", segments_array);
103+
104+
/* Parse Debug Info Headers for each core */
105+
current_offset_byte = (uint32_t)(current_offset_bit / 8);
106+
107+
while (current_offset_byte < (offset + size) && counter < MAX_DEBUG_INFO_CORES) {
108+
uint64_t core_offset_bit = current_offset_bit;
109+
struct json_object *core_debug_info = json_create_object();
110+
struct json_object *signature_obj = NULL;
111+
uint32_t debug_signature = 0;
112+
uint32_t total_bytes = 0;
113+
uint32_t num_segments = 0;
114+
uint32_t core_id = 0;
115+
116+
/* Check if we have enough space for the debug info header */
117+
if (current_offset_byte + sizeof(uint32_t) > (offset + size)) {
118+
json_free_object(core_debug_info);
119+
break;
120+
}
121+
122+
/* Parse DebugInfoHeader_t */
123+
err = sldm_telemetry_structure_parse(tl, debug_info_header_def,
124+
current_offset_bit,
125+
core_debug_info, NULL);
126+
if (err) {
127+
SOLIDIGM_LOG_WARNING("Failed to parse DebugInfoHeader_t for core %d",
128+
counter);
129+
json_free_object(core_debug_info);
130+
break;
131+
}
132+
133+
/* Validate signature */
134+
struct json_object *debug_info_header_obj = NULL;
135+
136+
if (json_object_object_get_ex(core_debug_info, "DebugInfoHeader_t",
137+
&debug_info_header_obj) &&
138+
json_object_object_get_ex(debug_info_header_obj, "nSignature",
139+
&signature_obj)) {
140+
debug_signature = json_object_get_int(signature_obj);
141+
}
142+
143+
if (debug_signature != DEBUG_INFO_SIGNATURE) {
144+
json_free_object(core_debug_info);
145+
break;
146+
}
147+
148+
/* Get total bytes and number of segments */
149+
struct json_object *total_bytes_obj = NULL;
150+
struct json_object *num_segments_obj = NULL;
151+
struct json_object *core_id_obj = NULL;
152+
153+
if (json_object_object_get_ex(debug_info_header_obj, "nTotalBytes",
154+
&total_bytes_obj))
155+
total_bytes = json_object_get_int(total_bytes_obj);
156+
157+
if (json_object_object_get_ex(debug_info_header_obj, "nNumSegments",
158+
&num_segments_obj))
159+
num_segments = json_object_get_int(num_segments_obj);
160+
161+
if (json_object_object_get_ex(debug_info_header_obj, "nCoreId",
162+
&core_id_obj))
163+
core_id = json_object_get_int(core_id_obj);
164+
165+
/* Add core info to the cores array */
166+
json_object_array_add(cores_array, core_debug_info);
167+
168+
/* Move to the position after DebugInfoHeader_t */
169+
struct json_object *header_size_obj = NULL;
170+
171+
if (json_object_object_get_ex(debug_info_header_def, "sizeBit",
172+
&header_size_obj)) {
173+
uint32_t header_size_bits = json_object_get_int(header_size_obj);
174+
175+
current_offset_bit += header_size_bits;
176+
current_offset_byte = (uint32_t)(current_offset_bit / 8);
177+
} else {
178+
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoHeader_t size");
179+
break;
180+
}
181+
182+
/* Parse segment headers for this core */
183+
for (uint32_t seg = 0; seg < num_segments && seg < 16; seg++) {
184+
struct json_object *tracker_info = NULL;
185+
struct json_object *debug_info_uart_log = NULL;
186+
struct json_object *segment_info = json_create_object();
187+
char *tracker_log_name = NULL;
188+
189+
/* Check bounds */
190+
if (current_offset_byte >= (offset + size)) {
191+
json_free_object(segment_info);
192+
break;
193+
}
194+
195+
/* Parse DebugInfoSegHeader_t */
196+
err = sldm_telemetry_structure_parse(tl,
197+
debug_info_seg_header_def,
198+
current_offset_bit,
199+
segment_info, NULL);
200+
if (err) {
201+
SOLIDIGM_LOG_WARNING(
202+
"Failed to parse DebugInfoSegHeader_t for core %d, seg %d",
203+
core_id, seg);
204+
json_free_object(segment_info);
205+
break;
206+
}
207+
208+
/* Add core and segment identifiers */
209+
json_object_add_value_uint(segment_info, "CoreId", core_id);
210+
json_object_add_value_uint(segment_info, "SegmentIndex", seg);
211+
212+
/* Add segment to segments array */
213+
json_object_array_add(segments_array, segment_info);
214+
215+
/* Move to next segment header */
216+
struct json_object *seg_header_size_obj = NULL;
217+
218+
if (json_object_object_get_ex(debug_info_seg_header_def,
219+
"sizeBit",
220+
&seg_header_size_obj)) {
221+
uint32_t seg_header_size_bits;
222+
223+
seg_header_size_bits = json_object_get_int(seg_header_size_obj);
224+
current_offset_bit += seg_header_size_bits;
225+
current_offset_byte = (uint32_t)(current_offset_bit / 8);
226+
} else {
227+
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoHeader_t size");
228+
json_free_object(segment_info);
229+
break;
230+
}
231+
// Get DebugInfoSegHeader_t size for logging
232+
struct json_object *debug_info_seg_header_obj = NULL;
233+
struct json_object *size_obj = NULL;
234+
uint32_t debug_info_seg_size = 0;
235+
236+
if (json_object_object_get_ex(segment_info, "DebugInfoSegHeader_t",
237+
&debug_info_seg_header_obj) &&
238+
json_object_object_get_ex(debug_info_seg_header_obj, "nSize",
239+
&size_obj)) {
240+
debug_info_seg_size = json_object_get_int(size_obj);
241+
} else {
242+
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoSegHeader_t size");
243+
json_free_object(segment_info);
244+
break;
245+
}
246+
247+
struct json_object *id_obj = NULL;
248+
uint32_t debug_info_seg_id = 0;
249+
250+
if (json_object_object_get_ex(debug_info_seg_header_obj, "nId",
251+
&id_obj)) {
252+
debug_info_seg_id = json_object_get_int(id_obj);
253+
} else {
254+
SOLIDIGM_LOG_WARNING("Cannot determine DebugInfoSegHeader_t id");
255+
json_free_object(segment_info);
256+
break;
257+
}
258+
switch (debug_info_seg_id) {
259+
case DEBUG_INFO_ID_UART_LOG:
260+
debug_info_uart_log = json_create_object();
261+
if (!debug_info_uart_log) {
262+
SOLIDIGM_LOG_WARNING(
263+
"Failed to create JSON object for UART log");
264+
json_free_object(segment_info);
265+
break;
266+
}
267+
sldm_parse_cd_uart_log(tl, current_offset_byte,
268+
debug_info_seg_size,
269+
debug_info_uart_log);
270+
json_object_object_add(segment_info, "DebugInfoUartLog",
271+
debug_info_uart_log);
272+
break;
273+
case DEBUG_INFO_ID_TRACKER_INFO:
274+
tracker_log_name = "TrackerInfo";
275+
case DEBUG_INFO_ID_TRACKER_BUFFER:
276+
if (!tracker_log_name)
277+
tracker_log_name = "TrackerBuffer";
278+
case DEBUG_INFO_ID_TRACKER_CONTEXT:
279+
if (!tracker_log_name)
280+
tracker_log_name = "TrackerContext";
281+
282+
tracker_info = json_create_object();
283+
if (!tracker_info) {
284+
SOLIDIGM_LOG_WARNING(
285+
"Failed to create JSON object for tracker info");
286+
json_free_object(segment_info);
287+
break;
288+
}
289+
sldm_tracker_parse(tl, current_offset_byte,
290+
debug_info_seg_size, tracker_info);
291+
292+
// Add tracker info to segment
293+
json_object_object_add(segment_info, tracker_log_name,
294+
tracker_info);
295+
break;
296+
}
297+
298+
current_offset_bit += debug_info_seg_size * 8;
299+
current_offset_byte = (uint32_t)(current_offset_bit / 8);
300+
}
301+
302+
/* Move to the next core based on total_bytes */
303+
if (total_bytes > 0) {
304+
current_offset_bit = core_offset_bit + total_bytes * 8;
305+
current_offset_byte = (uint32_t)(current_offset_bit / 8);
306+
}
307+
308+
counter++;
309+
if (counter >= MAX_DEBUG_INFO_CORES) {
310+
SOLIDIGM_LOG_WARNING("Attempted to parse debug info for %d cores.",
311+
counter);
312+
break;
313+
}
314+
}
315+
return 0;
316+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/* SPDX-License-Identifier: MIT */
2+
/*
3+
* Copyright (c) 2025 Solidigm.
4+
*
5+
6+
*/
7+
8+
#ifndef SLDM_DEBUG_INFO_H
9+
#define SLDM_DEBUG_INFO_H
10+
11+
#include "telemetry-log.h"
12+
#include "util/json.h"
13+
14+
/**
15+
* Parse debug info data from telemetry log
16+
17+
*/
18+
int sldm_debug_info_parse(struct telemetry_log *tl, uint32_t offset, uint32_t size,
19+
struct json_object *output);
20+
21+
#endif /* SLDM_DEBUG_INFO_H */

0 commit comments

Comments
 (0)