Skip to content

Commit 229bfdd

Browse files
committed
shell: add perf_status command for SOF telemetry
Add a new SOF shell command exposing the existing telemetry / performance_monitor counters from the live shell. sof perf_status - print the ipc4_perf_measurements_state (disabled/stopped/started/paused) and per-active-core systick counters from the SOF telemetry slot (count, last/max time elapsed, avg_kcps, peak_kcps, peak4k, peak8k) sof perf_status reset - reset_performance_counters() sof perf_status start - enable_performance_counters() and transition state to STARTED sof perf_status stop|pause - transition state without zeroing counters (useful for snapshots) Per-core data is read via telemetry_get_systick_info_ptr() when the debug slot manager is enabled, otherwise directly from ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT]. We iterate only cores enabled in cpu_enabled_cores() so the output matches the active topology and matches what get_performance_data() would put on the IPC. New Kconfig CONFIG_SOF_SHELL_PERF_STATUS (default y, depends on SOF_TELEMETRY). The full per-component perf_data_item_comp array (potentially hundreds of items in MW3) is intentionally not dumped here; that will land separately as 'perf_components' once there's a stream-friendly iterator. cpu_load is already available via Zephyr's 'kernel cpu_load' so it is not duplicated. Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
1 parent b8a1121 commit 229bfdd

3 files changed

Lines changed: 155 additions & 2 deletions

File tree

zephyr/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,23 @@ config SOF_SHELL_DBGWIN_DUMP
544544
critical_log, broken-marker and other slots from the shell
545545
without host-side tooling.
546546

547+
config SOF_SHELL_PERF_STATUS
548+
bool "Performance / telemetry status command"
549+
default y
550+
depends on SHELL && SOF_TELEMETRY
551+
help
552+
Enables 'sof perf_status [reset|start|stop|pause]' which prints
553+
the current ipc4_perf_measurements_state plus per-active-core
554+
systick counters from the SOF telemetry slot:
555+
count, last/max time elapsed (cycles), avg/peak KCPS and the
556+
4k/8k peak utilization buckets.
557+
558+
With one of the optional sub-commands the command transitions
559+
the perf measurement state machine ('start' calls
560+
enable_performance_counters(), 'reset' calls
561+
reset_performance_counters(); 'stop'/'pause' just update the
562+
state) - useful for taking before/after snapshots without IPC.
563+
547564
endmenu # SOF shell commands
548565

549566
config SOF_VREGIONS

zephyr/shell.md

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ debug or testing. Items get ticked off as commands land on `topic/shell`.
8888
| Audio buffers | `buffer_list`, `buffer_info <id>` | **DONE (task 2)** |
8989
| **Scheduler** | `sched_tasks`, `sched_load`, `task_info <task>` | **DONE (task 3)** |
9090
| Logging / trace | `log_status`, `mtrace_dump` (snapshot) | **DONE (task 4)** &mdash; runtime per-source `log_level` deferred (needs `CONFIG_LOG_RUNTIME_FILTERING`, see notes) |
91-
| Telemetry / perf | `perf_status`, `perf_reset`, `cpu_load` | TODO |
91+
| **Telemetry / perf** | `perf_status`, `perf_status reset`, `perf_status start/stop/pause` | **DONE (task 6)** |
9292
| Notifications | `notify_subscribers`, `notify_stats` | TODO |
9393
| **Debug window / mailbox** | `dbgwin_dump <slot>`, `mailbox_hex` | **DONE (task 5)** |
9494
| Crash / panic | `crash_log`, `crash_clear`, `panic_info`, `bt`, `regs` | TODO |
@@ -114,7 +114,7 @@ debug or testing. Items get ticked off as commands land on `topic/shell`.
114114
3. **`sched_tasks` / `sched_load`** &mdash; DONE.
115115
4. **`log_status` / `mtrace_dump`** &mdash; DONE.
116116
5. **`mailbox_hex` / `dbgwin_dump`** &mdash; DONE (was originally `crash_log`/`bt`; pivoted because SOF panic.c isn't built on Zephyr and `bt` of a running CPU from itself isn't meaningful).
117-
6. `perf_status` &mdash; wraps SOF telemetry counters.
117+
6. **`perf_status`** &mdash; DONE.
118118
7. `dai_list` / `dma_chan_status` &mdash; link/DMA blind spot.
119119
8. `kctl_get/set` &mdash; today only doable via tplg/IPC.
120120

@@ -309,3 +309,43 @@ debug or testing. Items get ticked off as commands land on `topic/shell`.
309309
ACE.
310310
- `dbgwin_dump` is read-only. We do not implement a write/seize
311311
command to avoid corrupting host-visible state.
312+
313+
## Task 6 &mdash; `perf_status`
314+
315+
### Commands
316+
317+
| Command | Description |
318+
|---|---|
319+
| `sof perf_status` | Print the SOF telemetry performance state (`disabled`/`stopped`/`started`/`paused`) and per-active-core systick counters (`count`, `last_time_elapsed`, `max_time_elapsed`, `avg_kcps`, `peak_kcps`, plus 4k/8k peak utilization). |
320+
| `sof perf_status reset` | Call `reset_performance_counters()` to zero all counters. |
321+
| `sof perf_status start` | Call `enable_performance_counters()` and set state to `STARTED`. |
322+
| `sof perf_status stop` / `pause` | Transition state to `STOPPED` or `PAUSED` (stops sampling without zeroing counters). |
323+
324+
### Implementation
325+
326+
- Reads per-core systick info via
327+
`telemetry_get_systick_info_ptr()` (with
328+
`CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER`) or directly from
329+
`ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT]` otherwise.
330+
- Iterates only cores in `cpu_enabled_cores()` so the output matches
331+
the active topology.
332+
- Uses the existing `perf_meas_get_state()` /
333+
`perf_meas_set_state()` /
334+
`enable_performance_counters()` /
335+
`reset_performance_counters()` API from
336+
[src/include/sof/debug/telemetry/performance_monitor.h](src/include/sof/debug/telemetry/performance_monitor.h);
337+
no new state added.
338+
- New Kconfig `CONFIG_SOF_SHELL_PERF_STATUS` (default `y`,
339+
depends on `SOF_TELEMETRY`).
340+
- Shell command in [zephyr/sof_shell.c](zephyr/sof_shell.c).
341+
342+
### Notes / follow-ups
343+
344+
- We deliberately do not dump the full per-component
345+
`perf_data_item_comp` array yet: it can grow large
346+
(`CONFIG_MEMORY_WIN_3_SIZE` / item size, ~hundreds of items on PTL)
347+
and would require a heap allocation. A future `perf_components` /
348+
`perf_status -v` could iterate `performance_data_bitmap` and stream
349+
one row per occupied slot.
350+
- Zephyr already provides `kernel cpu_load` and `kernel threads`;
351+
`cpu_load` was therefore not duplicated here.

zephyr/sof_shell.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,6 +2147,95 @@ __cold static int cmd_sof_dbgwin_dump(const struct shell *sh,
21472147

21482148
#endif /* CONFIG_SOF_SHELL_DBGWIN_DUMP */
21492149

2150+
#if CONFIG_SOF_SHELL_PERF_STATUS
2151+
2152+
#include <sof/debug/telemetry/telemetry.h>
2153+
#include <sof/debug/telemetry/performance_monitor.h>
2154+
#include <ipc4/base_fw.h>
2155+
2156+
static const char *perf_state_str(enum ipc4_perf_measurements_state_set s)
2157+
{
2158+
switch (s) {
2159+
case IPC4_PERF_MEASUREMENTS_DISABLED: return "disabled";
2160+
case IPC4_PERF_MEASUREMENTS_STOPPED: return "stopped";
2161+
case IPC4_PERF_MEASUREMENTS_STARTED: return "started";
2162+
case IPC4_PERF_MEASUREMENTS_PAUSED: return "paused";
2163+
default: return "?";
2164+
}
2165+
}
2166+
2167+
__cold static int cmd_sof_perf_status(const struct shell *sh,
2168+
size_t argc, char *argv[])
2169+
{
2170+
struct system_tick_info *systick;
2171+
int core_id, ret;
2172+
2173+
if (argc > 1) {
2174+
if (!strcmp(argv[1], "reset")) {
2175+
ret = reset_performance_counters();
2176+
shell_print(sh, "perf: reset_performance_counters() = %d", ret);
2177+
return ret;
2178+
}
2179+
if (!strcmp(argv[1], "start")) {
2180+
ret = enable_performance_counters();
2181+
if (!ret)
2182+
perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STARTED);
2183+
shell_print(sh, "perf: enable_performance_counters() = %d", ret);
2184+
return ret;
2185+
}
2186+
if (!strcmp(argv[1], "stop")) {
2187+
perf_meas_set_state(IPC4_PERF_MEASUREMENTS_STOPPED);
2188+
shell_print(sh, "perf: stopped");
2189+
return 0;
2190+
}
2191+
if (!strcmp(argv[1], "pause")) {
2192+
perf_meas_set_state(IPC4_PERF_MEASUREMENTS_PAUSED);
2193+
shell_print(sh, "perf: paused");
2194+
return 0;
2195+
}
2196+
shell_print(sh, "Usage: sof perf_status [reset|start|stop|pause]");
2197+
return -EINVAL;
2198+
}
2199+
2200+
shell_print(sh, "Performance measurements: %s",
2201+
perf_state_str(perf_meas_get_state()));
2202+
2203+
#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER
2204+
systick = telemetry_get_systick_info_ptr();
2205+
if (!systick) {
2206+
shell_print(sh, "telemetry slot not allocated");
2207+
return 0;
2208+
}
2209+
#else
2210+
{
2211+
struct telemetry_wnd_data *wnd =
2212+
(struct telemetry_wnd_data *)
2213+
ADSP_DW->slots[SOF_DW_TELEMETRY_SLOT];
2214+
systick = (struct system_tick_info *)wnd->system_tick_info;
2215+
}
2216+
#endif
2217+
2218+
shell_print(sh, "Per-core systick (count, last_us_cyc, max_us_cyc, avg_kcps, peak_kcps):");
2219+
for (core_id = 0; core_id < CONFIG_MAX_CORE_COUNT; core_id++) {
2220+
if (!(cpu_enabled_cores() & BIT(core_id)))
2221+
continue;
2222+
shell_print(sh,
2223+
" core %u: count=%u last=%u max=%u avg_kcps=%u peak_kcps=%u peak4k=%u peak8k=%u",
2224+
core_id,
2225+
systick[core_id].count,
2226+
systick[core_id].last_time_elapsed,
2227+
systick[core_id].max_time_elapsed,
2228+
systick[core_id].avg_utilization,
2229+
systick[core_id].peak_utilization,
2230+
systick[core_id].peak_utilization_4k,
2231+
systick[core_id].peak_utilization_8k);
2232+
}
2233+
2234+
return 0;
2235+
}
2236+
2237+
#endif /* CONFIG_SOF_SHELL_PERF_STATUS */
2238+
21502239
SHELL_STATIC_SUBCMD_SET_CREATE(sof_commands,
21512240
SHELL_CMD(test_inject_sched_gap, NULL,
21522241
"Inject a gap to audio scheduling\n",
@@ -2347,6 +2436,13 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sof_commands,
23472436
cmd_sof_dbgwin_dump, 1, 2),
23482437
#endif
23492438

2439+
#if CONFIG_SOF_SHELL_PERF_STATUS
2440+
SHELL_CMD_ARG(perf_status, NULL,
2441+
"Show telemetry perf state and per-core systick;"
2442+
" optional [reset|start|stop|pause]\n",
2443+
cmd_sof_perf_status, 1, 1),
2444+
#endif
2445+
23502446
SHELL_SUBCMD_SET_END
23512447
);
23522448

0 commit comments

Comments
 (0)