diff --git a/app/debug_stream_overlay.conf b/app/debug_stream_overlay.conf new file mode 100644 index 000000000000..0195e5070b33 --- /dev/null +++ b/app/debug_stream_overlay.conf @@ -0,0 +1,20 @@ +# Enable debug-stream protocol +CONFIG_SOF_DEBUG_STREAM_SLOT=y +# Add thread_info-client for debug stream +CONFIG_SOF_DEBUG_STREAM_THREAD_INFO=y +# Zephyr option for storing human readable thread names +CONFIG_THREAD_NAME=y + +# Debug window slot configuration 1 +# The CONFIG_SOF_TELEMETRY uses slot 2, but with performance and IO-performance +# it extends beyond slot 3. +CONFIG_MEMORY_WIN_2_SIZE=16384 +CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=n +CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=n + +# If we turn telemetry off all together, we can use slot 2. Slot 1 is used by mtrace +#CONFIG_SOF_DEBUG_STREAM_SLOT_NUMBER=2 +#CONFIG_SOF_TELEMETRY=n +#CONFIG_SOF_TELEMETRY_PERFORMANCE_MEASUREMENTS=n +#CONFIG_SOF_TELEMETRY_IO_PERFORMANCE_MEASUREMENTS=n + diff --git a/src/debug/debug_stream/debug_stream_slot.c b/src/debug/debug_stream/debug_stream_slot.c index bf8a593a348e..349eb2693137 100644 --- a/src/debug/debug_stream/debug_stream_slot.c +++ b/src/debug/debug_stream/debug_stream_slot.c @@ -109,7 +109,7 @@ static int debug_stream_slot_init(void) size_t offset = hdr_size; int i; - LOG_INF("%u sections of %u bytes, hdr %u, secton area %u\n", + LOG_INF("%u sections of %u bytes, hdr %u, section area %u\n", CONFIG_MP_MAX_NUM_CPUS, section_size, hdr_size, section_area_size); diff --git a/tools/debug_stream/debug_stream.py b/tools/debug_stream/debug_stream.py index 717845dc49e5..752e53a92d1f 100644 --- a/tools/debug_stream/debug_stream.py +++ b/tools/debug_stream/debug_stream.py @@ -10,6 +10,8 @@ import argparse import ctypes import time +import sys +import os import logging @@ -18,6 +20,7 @@ ) DEBUG_STREAM_PAYLOAD_MAGIC = 0x1ED15EED +DEBUG_SLOT_SIZE = 4096 # TODO: python construct would probably be cleaner than ctypes structs @@ -225,7 +228,7 @@ def get_hdr(self, slot, pos): slot[self.boffset + pos * WSIZE :], ctypes.POINTER(DebugStreamRecord) ).contents if header.id > 100 or header.size_words >= self.buf_words: - logging.warning( + logging.info( "Broken record id %u seqno %u size %u", header.id, header.seqno, @@ -286,7 +289,7 @@ def catch_up(self, slot): self.decode_past_records(slot, circ.w_ptr, circ.next_seqno) self.prev_w_ptr = circ.w_ptr self.prev_seqno = circ.next_seqno - 1 - logging.info("seqno %u w_ptr %u", self.prev_seqno, self.prev_w_ptr) + logging.debug("seqno %u w_ptr %u", self.prev_seqno, self.prev_w_ptr) def decode_past_records(self, slot, pos, seqno): """ @@ -373,7 +376,7 @@ class DebugStreamDecoder: Class for decoding debug-stream slot contents """ - file_size = 4096 # ADSP debug slot size + file_size = DEBUG_SLOT_SIZE file = None slot = None descs = [] @@ -393,6 +396,12 @@ def update_slot(self): self.file.seek(0) self.slot = self.file.read(self.file_size) + def set_slot(self, buf): + """ + Update slot contents + """ + self.slot = buf + def get_descriptors(self): """ Read the core specific descriptors and initialize core @@ -403,15 +412,26 @@ def get_descriptors(self): return False hdr = ctypes.cast(self.slot, ctypes.POINTER(DebugStreamSlotHdr)) if hdr.contents.hdr.magic != DEBUG_STREAM_PAYLOAD_MAGIC: - logging.warning("Debug Slot has bad magic 0x%08x", hdr.contents.hdr.magic) + logging.info("Debug Slot has bad magic 0x%08x", hdr.contents.hdr.magic) return False num_sections = hdr.contents.num_sections if num_sections == len(self.descs): return True + if num_sections > 32: + logging.info("Suspiciously many sections %u", num_sections) + return False hsize = ctypes.sizeof(DebugStreamSlotHdr) self.descs = (DebugStreamSectionDescriptor * num_sections).from_buffer_copy( self.slot, hsize ) + for i in range(len(self.descs)): + if (self.descs[i].core_id > 32 or + self.descs[i].buf_words > DEBUG_SLOT_SIZE // WSIZE or + self.descs[i].offset > DEBUG_SLOT_SIZE): + logging.info("Suspicious descriptor %u values %u %u %u", i, + self.descs[i].core_id, self.descs[i].buf_words, + self.descs[i].offset) + return False self.circdec = [ CircularBufferDecoder(self.descs[i], i, self.rec_printer) for i in range(len(self.descs)) @@ -473,6 +493,41 @@ def reset(self): self.file = None self.slot = None +def cavstool_main_loop(my_args): + import cavstool + try: + (hda, sd, dsp, hda_ostream_id) = cavstool.map_regs(True) + except Exception as e: + logging.error("Could not map device in sysfs; run as root?") + logging.error(e) + sys.exit(1) + ADSP_DW_SLOT_DEBUG_STREAM = 0x53523134 + decoder = DebugStreamDecoder() + while True: + if not cavstool.fw_is_alive(dsp): + cavstool.wait_fw_entered(dsp, timeout_s=None) + if my_args.direct_access_slot < 0: + offset = cavstool.debug_slot_offset_by_type(ADSP_DW_SLOT_DEBUG_STREAM) + if offset is None: + logging.error("Could not find debug_stream slot") + sys.exit(1) + logging.info("Got offset 0x%08x by type 0x%08x", offset, + ADSP_DW_SLOT_DEBUG_STREAM) + else: + offset = cavstool.debug_slot_offset(my_args.direct_access_slot) + buf = cavstool.win_read(offset, 0, DEBUG_SLOT_SIZE) + decoder.set_slot(buf) + if not decoder.get_descriptors(): + time.sleep(my_args.update_interval) + continue + decoder.catch_up_all() + while True: + if decoder.poll(): + time.sleep(my_args.update_interval) + buf = cavstool.win_read(offset, 0, DEBUG_SLOT_SIZE) + decoder.set_slot(buf) + if not decoder.check_slot(): + break def main_f(my_args): """ @@ -483,6 +538,8 @@ def main_f(my_args): about the host CPU load. That is why there where no synchronous mechanism done and the host simply polls for new records. """ + if my_args.direct_access_slot >= 0 or not os.path.isfile(my_args.debugstream_file): + return cavstool_main_loop(my_args) decoder = DebugStreamDecoder() prev_error = None while True: @@ -491,7 +548,8 @@ def main_f(my_args): decoder.set_file(file) decoder.update_slot() if not decoder.get_descriptors(): - break + time.sleep(my_args.update_interval) + continue decoder.catch_up_all() while True: if decoder.poll(): @@ -527,6 +585,13 @@ def parse_params(): help="File to read the DebugStream data from, default /sys/kernel/debug/sof/debug_stream", default="/sys/kernel/debug/sof/debug_stream", ) + parser.add_argument( + "-c", + "--direct-access-slot", + help="Access specified debug window slot directly, no need for debugfs file", + type=int, + default=-1, + ) parsed_args = parser.parse_args() return parsed_args