diff --git a/soc/intel/intel_adsp/Kconfig b/soc/intel/intel_adsp/Kconfig index 7523f167fad2e..aa57372e211e7 100644 --- a/soc/intel/intel_adsp/Kconfig +++ b/soc/intel/intel_adsp/Kconfig @@ -66,7 +66,7 @@ config MEMORY_WIN_1_SIZE config MEMORY_WIN_2_SIZE int "Size of memory window 2" - default 8192 + default 12288 help Size of memory window 2. @@ -80,6 +80,15 @@ config MEMORY_WIN_3_SIZE This window is used for trace. +config INTEL_ADSP_DEBUG_SLOT_MANAGER + bool "Debug slot manager" + help + If selected the debug slot allocation can be only done via + the manager API, direct debug window access and tampering is + forbidden. + The API use allows dynamic slot allocation instead of static + and error prone slot usage. + config ADSP_CLOCK bool help diff --git a/soc/intel/intel_adsp/common/CMakeLists.txt b/soc/intel/intel_adsp/common/CMakeLists.txt index 9e49bd26eabec..d091bd5afd360 100644 --- a/soc/intel/intel_adsp/common/CMakeLists.txt +++ b/soc/intel/intel_adsp/common/CMakeLists.txt @@ -25,6 +25,10 @@ zephyr_library_sources( zephyr_library_sources_ifdef(CONFIG_ADSP_CLOCK clk.c) +zephyr_library_sources_ifdef(CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + debug_window.c + ) + if(CONFIG_SMP OR CONFIG_MP_MAX_NUM_CPUS GREATER 1) zephyr_library_sources(multiprocessing.c) endif() diff --git a/soc/intel/intel_adsp/common/debug_window.c b/soc/intel/intel_adsp/common/debug_window.c new file mode 100644 index 0000000000000..f66fad1420a05 --- /dev/null +++ b/soc/intel/intel_adsp/common/debug_window.c @@ -0,0 +1,158 @@ +/* Copyright (c) 2025 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(debug_window, CONFIG_SOC_LOG_LEVEL); + +struct adsp_debug_window { + struct adsp_dw_desc descs[ADSP_DW_DESC_COUNT]; + uint8_t reserved[ADSP_DW_PAGE0_SLOT_OFFSET - + ADSP_DW_DESC_COUNT * sizeof(struct adsp_dw_desc)]; + uint8_t partial_page0[ADSP_DW_SLOT_SIZE - ADSP_DW_PAGE0_SLOT_OFFSET]; + uint8_t slots[ADSP_DW_SLOT_COUNT][ADSP_DW_SLOT_SIZE]; +} __packed; + +#define WIN2_MBASE DT_REG_ADDR(DT_PHANDLE(DT_NODELABEL(mem_window2), memory)) +#define WIN2_SLOTS ((HP_SRAM_WIN2_SIZE / ADSP_DW_PAGE_SIZE) - 1) +#define ADSP_DW_FULL_SLOTS MIN(WIN2_SLOTS, ADSP_DW_SLOT_COUNT) + +#define ADSP_DW ((volatile struct adsp_debug_window *) \ + (sys_cache_uncached_ptr_get((__sparse_force void __sparse_cache *) \ + (WIN2_MBASE + WIN2_OFFSET)))) + +static int adsp_dw_find_slot(uint32_t type, bool prefer_partial) +{ + int i; + + if (prefer_partial) { + if (ADSP_DW->descs[ADSP_DW_SLOT_COUNT].type == type) { + return ADSP_DW_SLOT_COUNT; + } + } + + for (i = 0; i < ADSP_DW_FULL_SLOTS; i++) { + if (ADSP_DW->descs[i].type == type) { + return i; + } + } + + if (!prefer_partial) { + if (ADSP_DW->descs[ADSP_DW_SLOT_COUNT].type == type) { + return ADSP_DW_SLOT_COUNT; + } + } + + return -ENOENT; +} + +volatile void *adsp_dw_request_slot(struct adsp_dw_desc *dw_desc, size_t *slot_size) +{ + int slot_idx; + + if (!dw_desc->type) { + return NULL; + } + + /* Check if a slot have been allocated for this type */ + slot_idx = adsp_dw_find_slot(dw_desc->type, !!slot_size); + if (slot_idx < 0) { + /* Look for an empty slot */ + slot_idx = adsp_dw_find_slot(ADSP_DW_SLOT_UNUSED, !!slot_size); + if (slot_idx < 0) { + LOG_INF("No available slot for %#x", dw_desc->type); + return NULL; + } + } + + ADSP_DW->descs[slot_idx].resource_id = dw_desc->resource_id; + ADSP_DW->descs[slot_idx].type = dw_desc->type; + ADSP_DW->descs[slot_idx].vma = dw_desc->vma; + + if (slot_size) { + *slot_size = ADSP_DW_SLOT_SIZE; + } + + if (slot_idx == ADSP_DW_SLOT_COUNT) { + if (slot_size) { + *slot_size -= ADSP_DW_PAGE0_SLOT_OFFSET; + } + + LOG_DBG("Allocating partial page0 to be used for %#x", dw_desc->type); + + return ADSP_DW->partial_page0; + } + + LOG_DBG("Allocating debug slot %d to be used for %#x", slot_idx, dw_desc->type); + + return ADSP_DW->slots[slot_idx]; +} + +volatile void *adsp_dw_seize_slot(uint32_t slot_index, struct adsp_dw_desc *dw_desc, + size_t *slot_size) +{ + if ((slot_index >= ADSP_DW_FULL_SLOTS && slot_index != ADSP_DW_SLOT_COUNT) || + !dw_desc->type) { + return NULL; + } + + if (slot_index < ADSP_DW_FULL_SLOTS) { + if (ADSP_DW->descs[slot_index].type != ADSP_DW_SLOT_UNUSED) { + LOG_INF("Overtaking debug slot %d, used by %#x for %#x", slot_index, + ADSP_DW->descs[slot_index].type, dw_desc->type); + } + + if (slot_size) { + *slot_size = ADSP_DW_SLOT_SIZE; + } + + ADSP_DW->descs[slot_index].resource_id = dw_desc->resource_id; + ADSP_DW->descs[slot_index].type = dw_desc->type; + ADSP_DW->descs[slot_index].vma = dw_desc->vma; + + return ADSP_DW->slots[slot_index]; + } + + /* The caller is not prepared to handle partial debug slot */ + if (!slot_size) { + return NULL; + } + + if (ADSP_DW->descs[slot_index].type != ADSP_DW_SLOT_UNUSED) { + LOG_INF("Overtaking partial page0, used by %#x for %#x", + ADSP_DW->descs[slot_index].type, dw_desc->type); + } + + *slot_size = ADSP_DW_SLOT_SIZE - ADSP_DW_PAGE0_SLOT_OFFSET; + + ADSP_DW->descs[slot_index].resource_id = dw_desc->resource_id; + ADSP_DW->descs[slot_index].type = dw_desc->type; + ADSP_DW->descs[slot_index].vma = dw_desc->vma; + + return ADSP_DW->partial_page0; +} + +void adsp_dw_release_slot(uint32_t type) +{ + int slot_idx; + + slot_idx = adsp_dw_find_slot(type, true); + + if (slot_idx < 0) { + return; + } + + if (slot_idx == ADSP_DW_SLOT_COUNT) { + LOG_DBG("Releasing partial page0 used by %#x", type); + } else { + LOG_DBG("Releasing debug slot %d used by %#x", slot_idx, type); + } + + ADSP_DW->descs[slot_idx].resource_id = 0; + ADSP_DW->descs[slot_idx].type = ADSP_DW_SLOT_UNUSED; + ADSP_DW->descs[slot_idx].vma = 0; +} diff --git a/soc/intel/intel_adsp/common/gdbstub_backend_sram.c b/soc/intel/intel_adsp/common/gdbstub_backend_sram.c index 6d7420de587e8..3461c4dcb9b3c 100644 --- a/soc/intel/intel_adsp/common/gdbstub_backend_sram.c +++ b/soc/intel/intel_adsp/common/gdbstub_backend_sram.c @@ -57,18 +57,25 @@ static inline int ring_have_data(const volatile struct gdb_sram_ring *ring) return ring->head != ring->tail; } +#ifndef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER #define RX_UNCACHED (uint8_t *) (HP_SRAM_WIN2_BASE + SOF_GDB_WINDOW_OFFSET) #define TX_UNCACHED (uint8_t *) (RX_UNCACHED + sizeof(struct gdb_sram_ring)) +#endif static volatile struct gdb_sram_ring *rx; static volatile struct gdb_sram_ring *tx; void z_gdb_backend_init(void) { +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + __ASSERT_NO_MSG(rx && tx); +#else __ASSERT_NO_MSG(sizeof(ADSP_DW->descs) <= SOF_GDB_WINDOW_OFFSET); rx = sys_cache_uncached_ptr_get(RX_UNCACHED); tx = sys_cache_uncached_ptr_get(TX_UNCACHED); +#endif + rx->head = rx->tail = 0; tx->head = tx->tail = 0; } @@ -96,7 +103,24 @@ unsigned char z_gdb_getchar(void) static int gdbstub_backend_sram_init(void) { +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_GDB_STUB, }; + size_t slot_size; + char *slot_addr; + + /* Force use the partial page0 slot */ + slot_addr = (char *)adsp_dw_request_slot(&slot_desc, &slot_size); + + if (!slot_addr) { + return -ENOMEM; + } + + rx = sys_cache_uncached_ptr_get(slot_addr); + tx = sys_cache_uncached_ptr_get(slot_addr + sizeof(struct gdb_sram_ring)); +#else ADSP_DW->descs[ADSP_DW_SLOT_NUM_GDB].type = ADSP_DW_SLOT_GDB_STUB; +#endif + return 0; } diff --git a/soc/intel/intel_adsp/common/include/adsp_debug_window.h b/soc/intel/intel_adsp/common/include/adsp_debug_window.h index 2a8a33590d330..d7a74d0bd1fe6 100644 --- a/soc/intel/intel_adsp/common/include/adsp_debug_window.h +++ b/soc/intel/intel_adsp/common/include/adsp_debug_window.h @@ -35,21 +35,36 @@ * u32 res_id; * u32 type; * u32 vma; + * + * The descriptor layout is: + * + * -------------------- + * | Desc0 - slot0 | + * -------------------- + * | Desc1 - slot1 | + * -------------------- + * | Desc2 - slot2 | + * -------------------- + * | ... | + * -------------------- + * | Desc13 - slot13 | + * -------------------- + * | Desc14 - slot14 | + * -------------------- + * + * Additional descriptor to descibe the function of the partial slot at page0: + * + * -------------------------- + * | Desc15 - page0 + 1024 | + * -------------------------- */ #define ADSP_DW_PAGE_SIZE 0x1000 #define ADSP_DW_SLOT_SIZE ADSP_DW_PAGE_SIZE #define ADSP_DW_SLOT_COUNT 15 +#define ADSP_DW_PAGE0_SLOT_OFFSET 1024 #define ADSP_DW_DESC_COUNT (ADSP_DW_SLOT_COUNT + 1) -/* debug window slots usage, mutually exclusive options can reuse slots */ -#define ADSP_DW_SLOT_NUM_SHELL 0 -#define ADSP_DW_SLOT_NUM_MTRACE 0 -#define ADSP_DW_SLOT_NUM_TRACE 1 -#define ADSP_DW_SLOT_NUM_TELEMETRY 1 -/* this uses remaining space in the first page after descriptors */ -#define ADSP_DW_SLOT_NUM_GDB (ADSP_DW_DESC_COUNT - 1) - /* debug log slot types */ #define ADSP_DW_SLOT_UNUSED 0x00000000 #define ADSP_DW_SLOT_CRITICAL_LOG 0x54524300 @@ -71,9 +86,26 @@ struct adsp_dw_desc { uint32_t vma; } __packed; +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +volatile void *adsp_dw_request_slot(struct adsp_dw_desc *dw_desc, size_t *slot_size); +volatile void *adsp_dw_seize_slot(uint32_t slot_index, struct adsp_dw_desc *dw_desc, + size_t *slot_size); +void adsp_dw_release_slot(uint32_t type); +#else /* CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER */ + +/* debug window slots usage, mutually exclusive options can reuse slots */ +#define ADSP_DW_SLOT_NUM_SHELL 0 +#define ADSP_DW_SLOT_NUM_MTRACE 0 +#define ADSP_DW_SLOT_NUM_TRACE 1 +#define ADSP_DW_SLOT_NUM_TELEMETRY 1 +/* this uses remaining space in the first page after descriptors */ +#define ADSP_DW_SLOT_NUM_GDB (ADSP_DW_DESC_COUNT - 1) + struct adsp_debug_window { struct adsp_dw_desc descs[ADSP_DW_DESC_COUNT]; - uint8_t reserved[ADSP_DW_SLOT_SIZE - ADSP_DW_DESC_COUNT * sizeof(struct adsp_dw_desc)]; + uint8_t reserved[ADSP_DW_PAGE0_SLOT_OFFSET - + ADSP_DW_DESC_COUNT * sizeof(struct adsp_dw_desc)]; + uint8_t partial_page0[ADSP_DW_SLOT_SIZE - ADSP_DW_PAGE0_SLOT_OFFSET]; uint8_t slots[ADSP_DW_SLOT_COUNT][ADSP_DW_SLOT_SIZE]; } __packed; @@ -83,4 +115,6 @@ struct adsp_debug_window { (sys_cache_uncached_ptr_get((__sparse_force void __sparse_cache *) \ (WIN2_MBASE + WIN2_OFFSET)))) +#endif /* CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER */ + #endif diff --git a/soc/intel/intel_adsp/tools/cavstool.py b/soc/intel/intel_adsp/tools/cavstool.py index fcb518c30b3b7..ff3d53b95704f 100755 --- a/soc/intel/intel_adsp/tools/cavstool.py +++ b/soc/intel/intel_adsp/tools/cavstool.py @@ -37,6 +37,7 @@ DEBUG_SLOT_SIZE = 4096 DEBUG_SLOT_SHELL = 0 +DEBUG_SLOT_SHELL_TYPE = 0x73686c6c SHELL_RX_SIZE = 256 SHELL_MAX_VALID_SLOT_SIZE = 16777216 @@ -769,7 +770,7 @@ def debug_slot_offset_by_type(the_type, timeout_s=0.2): return None def shell_base_offset(): - return debug_offset() + DEBUG_SLOT_SIZE * (1 + DEBUG_SLOT_SHELL) + return debug_slot_offset_by_type(DEBUG_SLOT_SHELL_TYPE) def read_from_shell_memwindow_winstream(last_seq): offset = shell_base_offset() + SHELL_RX_SIZE diff --git a/subsys/debug/coredump/coredump_backend_intel_adsp_mem_window.c b/subsys/debug/coredump/coredump_backend_intel_adsp_mem_window.c index 201a2e8a2a439..2092efa4b7aeb 100644 --- a/subsys/debug/coredump/coredump_backend_intel_adsp_mem_window.c +++ b/subsys/debug/coredump/coredump_backend_intel_adsp_mem_window.c @@ -20,12 +20,27 @@ LOG_MODULE_REGISTER(coredump, CONFIG_DEBUG_COREDUMP_LOG_LEVEL); static int error; static uint32_t mem_wptr; +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +static void *coredump_slot_addr; +#endif + static void coredump_mem_window_backend_start(void) { /* Reset error & mem write ptr */ error = 0; mem_wptr = 0; +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_TELEMETRY, }; + + /* Forcably take debug slot 1 */ + coredump_slot_addr = (void *)adsp_dw_seize_slot(1, &slot_desc, NULL); + if (!coredump_slot_addr) { + /* Try to get the first slot if slot 1 is not available as fallback */ + coredump_slot_addr = (void *)adsp_dw_seize_slot(0, &slot_desc, NULL); + } +#else ADSP_DW->descs[1].type = ADSP_DW_SLOT_TELEMETRY; +#endif while (LOG_PROCESS()) { ; @@ -46,10 +61,20 @@ static void coredump_mem_window_backend_end(void) static void coredump_mem_window_backend_buffer_output(uint8_t *buf, size_t buflen) { - uint32_t *mem_window_separator = (uint32_t *)(ADSP_DW->slots[1]); - uint8_t *mem_window_sink = (uint8_t *)(ADSP_DW->slots[1]) + 4 + mem_wptr; uint8_t *coredump_data = buf; size_t data_left; +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + uint32_t *mem_window_separator = (uint32_t *)coredump_slot_addr; + uint8_t *mem_window_sink = (uint8_t *)coredump_slot_addr + 4 + mem_wptr; + + if (!coredump_slot_addr) { + return; + } +#else + uint32_t *mem_window_separator = (uint32_t *)(ADSP_DW->slots[1]); + uint8_t *mem_window_sink = (uint8_t *)(ADSP_DW->slots[1]) + 4 + mem_wptr; +#endif + /* Default place for telemetry dump is in memory window. Each data is easily find using * separator. For telemetry that separator is 0x0DEC0DEB. */ diff --git a/subsys/logging/backends/log_backend_adsp_mtrace.c b/subsys/logging/backends/log_backend_adsp_mtrace.c index 10271c9c8ed98..1553a47262c06 100644 --- a/subsys/logging/backends/log_backend_adsp_mtrace.c +++ b/subsys/logging/backends/log_backend_adsp_mtrace.c @@ -64,19 +64,41 @@ struct adsp_debug_slot { uint8_t data[ADSP_DW_SLOT_SIZE - sizeof(uint32_t) * 2]; } __packed; +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +static struct adsp_debug_slot *slot; +#endif + static void mtrace_init(void) { +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct adsp_dw_desc slot_desc = { .type = MTRACE_LOGGING_SLOT_TYPE(MTRACE_CORE), }; + + if (slot) { + return; + } + + slot = (struct adsp_debug_slot *)adsp_dw_request_slot(&slot_desc, NULL); +#else if (ADSP_DW->descs[ADSP_DW_SLOT_NUM_MTRACE].type == MTRACE_LOGGING_SLOT_TYPE(MTRACE_CORE)) { return; } ADSP_DW->descs[ADSP_DW_SLOT_NUM_MTRACE].type = MTRACE_LOGGING_SLOT_TYPE(MTRACE_CORE); +#endif } static size_t mtrace_out(int8_t *str, size_t len, size_t *space_left) { +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + /* Debug slot is not allocated */ + if (!slot) { + return 0; + } +#else struct adsp_debug_slot *slot = (struct adsp_debug_slot *) ADSP_DW->slots[ADSP_DW_SLOT_NUM_MTRACE]; +#endif + uint8_t *data = slot->data; uint32_t r = slot->host_ptr; uint32_t w = slot->dsp_ptr; diff --git a/subsys/shell/backends/shell_adsp_memory_window.c b/subsys/shell/backends/shell_adsp_memory_window.c index 519e68ea52f04..50730d9b41f77 100644 --- a/subsys/shell/backends/shell_adsp_memory_window.c +++ b/subsys/shell/backends/shell_adsp_memory_window.c @@ -22,6 +22,10 @@ LOG_MODULE_REGISTER(shell_adsp_memory_window); BUILD_ASSERT(RX_WINDOW_SIZE < ADSP_DW_SLOT_SIZE); +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER +static struct adsp_debug_slot_shell *dw_slot; +#endif + struct adsp_debug_slot_shell { uint8_t rx_window[RX_WINDOW_SIZE]; uint8_t tx_window[ADSP_DW_SLOT_SIZE - RX_WINDOW_SIZE]; @@ -44,6 +48,15 @@ static int init(const struct shell_transport *transport, { struct shell_adsp_memory_window *sh_adsp_mw = (struct shell_adsp_memory_window *)transport->ctx; + +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_SHELL, }; + + dw_slot = (struct adsp_debug_slot_shell *)adsp_dw_request_slot(&slot_desc, NULL); + if (!dw_slot) { + return -ENOTSUP; + } +#else struct adsp_debug_slot_shell *dw_slot; if (ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type && @@ -55,10 +68,12 @@ static int init(const struct shell_transport *transport, ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type = ADSP_DW->descs[ADSP_DW_SLOT_NUM_SHELL].type; + dw_slot = (struct adsp_debug_slot_shell *)ADSP_DW->slots[ADSP_DW_SLOT_NUM_SHELL]; +#endif + sh_adsp_mw->shell_handler = evt_handler; sh_adsp_mw->shell_context = context; - dw_slot = (struct adsp_debug_slot_shell *)ADSP_DW->slots[ADSP_DW_SLOT_NUM_SHELL]; sh_adsp_mw->ws_rx = sys_winstream_init(&dw_slot->rx_window[0], sizeof(dw_slot->rx_window)); sh_adsp_mw->ws_tx = sys_winstream_init(&dw_slot->tx_window[0], sizeof(dw_slot->tx_window)); @@ -80,6 +95,11 @@ static int uninit(const struct shell_transport *transport) k_timer_stop(&sh_adsp_mw->timer); +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + adsp_dw_release_slot(ADSP_DW_SLOT_SHELL); + dw_slot = NULL; +#endif + return 0; } diff --git a/subsys/tracing/tracing_backend_adsp_memory_window.c b/subsys/tracing/tracing_backend_adsp_memory_window.c index 43f8229ad9641..5d6e1a6e16b79 100644 --- a/subsys/tracing/tracing_backend_adsp_memory_window.c +++ b/subsys/tracing/tracing_backend_adsp_memory_window.c @@ -29,6 +29,12 @@ static void tracing_backend_adsp_memory_window_output( const struct tracing_backend *backend, uint8_t *data, uint32_t length) { +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + if (!mem_window) { + return; + } +#endif + /* copy data to ring buffer, * to make FW part fast, there's no sync with the data reader * the reader MUST read data before they got overwritten @@ -48,6 +54,15 @@ static void tracing_backend_adsp_memory_window_output( static void tracing_backend_adsp_memory_window_init(void) { +#ifdef CONFIG_INTEL_ADSP_DEBUG_SLOT_MANAGER + struct adsp_dw_desc slot_desc = { .type = ADSP_DW_SLOT_TRACE, }; + + mem_window = (struct tracing_backend_adsp_memory_window *)adsp_dw_request_slot(&slot_desc, + NULL); + if (mem_window) { + mem_window->head_offset = 0; + } +#else volatile struct adsp_debug_window *window = ADSP_DW; window->descs[ADSP_DW_SLOT_NUM_TRACE].type = ADSP_DW_SLOT_TRACE; @@ -56,6 +71,7 @@ static void tracing_backend_adsp_memory_window_init(void) ADSP_DW->slots[ADSP_DW_SLOT_NUM_TRACE]; mem_window->head_offset = 0; +#endif } const struct tracing_backend_api tracing_backend_adsp_memory_window_api = {