Skip to content

Commit 6c3faba

Browse files
committed
dram: add temporarily banned DRAM execution
DRAM execution is banned in LL task context, but there are also time intervals during which performance is important. Moreover, sometimes such critical periods aren't certain until a later time. E.g. when processing IPCs, only some of them are performance critical. And those time-critical IPCs should be handled with maximum performance from IPC-entry till IPC-exit, not only while handling that specific IPC. Consider this pseudo-code: void ipc_cmd() { common_pre_processing(); switch (cmd) { case NON_CRITICAL_CMD: handle_non_critical(); break; case CRITICAL_CMD: handle_critical(); } common_post_processing(); } In this case ipc_cmd(), common_pre_processing(), handle_critical() and common_post_processing() cannot be executed in DRAM, while handle_non_critical() can be executed in DRAM. If we place start-critical-debugging and stop-critical-debugging to cover all of ipc_cmd(), we'll be forced to also place handle_non_critical() in SRAM. OTOH if we only surround handle_critical() with those markers, we will miss all the common code. To support such cases we use 3 markers: mem_hot_path_start_watching() mem_hot_path_stop_watching() mem_hot_path_confirm() Then we place start- and stop-watching in the beginning and end of ipc_cmd(), and mem_hot_path_confirm() under the CRITICAL_CMD case. Then if we made common_pre_processing() or common_post_processing() __cold, the fact of them being called while watching will be recorded. Then mem_hot_path_confirm() will set a confirmation flag. Then when watching is stopped, we check if the flag was raised and a cold function was called, in which case we issue an error. Signed-off-by: Guennadi Liakhovetski <guennadi.liakhovetski@linux.intel.com>
1 parent 3195192 commit 6c3faba

File tree

8 files changed

+89
-0
lines changed

8 files changed

+89
-0
lines changed

posix/include/sof/lib/memory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
#endif
2020

2121
#define assert_can_be_cold() do {} while (0)
22+
#define mem_hot_path_confirm() do {} while (0)
2223

2324
#endif /* __SOF_LIB_MEMORY_H__ */

src/debug/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ if(it_is) ### Zephyr ###
1212
add_subdirectory(debug_stream)
1313
add_subdirectory(telemetry)
1414

15+
zephyr_library_sources_ifdef(CONFIG_COLD_STORE_EXECUTE_DEBUG dram.c)
16+
1517
else() ### Not Zephyr ###
1618

1719
add_local_sources(sof panic.c)

src/debug/dram.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2025 Intel Corporation.
4+
5+
#include <rtos/kernel.h>
6+
#include <rtos/symbol.h>
7+
#include <zephyr/logging/log.h>
8+
#include <zephyr/sys/__assert.h>
9+
10+
LOG_MODULE_REGISTER(dram_debug, CONFIG_SOF_LOG_LEVEL);
11+
12+
static struct k_spinlock hot_path_lock;
13+
static unsigned int hot_path_depth;
14+
static const char *cold_path_fn;
15+
static bool hot_path_confirmed;
16+
17+
void mem_cold_path_enter(const char *fn)
18+
{
19+
k_spinlock_key_t key = k_spin_lock(&hot_path_lock);
20+
21+
cold_path_fn = fn;
22+
23+
k_spin_unlock(&hot_path_lock, key);
24+
}
25+
EXPORT_SYMBOL(mem_cold_path_enter);
26+
27+
void mem_hot_path_start_watching(void)
28+
{
29+
k_spinlock_key_t key = k_spin_lock(&hot_path_lock);
30+
31+
if (!hot_path_depth++) {
32+
cold_path_fn = NULL;
33+
hot_path_confirmed = false;
34+
}
35+
36+
k_spin_unlock(&hot_path_lock, key);
37+
}
38+
39+
void mem_hot_path_confirm(void)
40+
{
41+
k_spinlock_key_t key = k_spin_lock(&hot_path_lock);
42+
43+
hot_path_confirmed = true;
44+
45+
k_spin_unlock(&hot_path_lock, key);
46+
}
47+
48+
void mem_hot_path_stop_watching(void)
49+
{
50+
bool underrun, error;
51+
k_spinlock_key_t key = k_spin_lock(&hot_path_lock);
52+
53+
if (hot_path_depth) {
54+
underrun = false;
55+
hot_path_depth--;
56+
error = hot_path_confirmed && cold_path_fn;
57+
} else {
58+
error = underrun = true;
59+
}
60+
61+
k_spin_unlock(&hot_path_lock, key);
62+
63+
if (underrun)
64+
LOG_ERR("Hot path depth underrun!");
65+
else
66+
__ASSERT(!error, "Cold function %s() has run while on hot path!", cold_path_fn);
67+
}

src/idc/idc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,9 @@ void idc_cmd(struct idc_msg *msg)
425425
notifier_notify_remote();
426426
break;
427427
case iTS(IDC_MSG_IPC):
428+
mem_hot_path_start_watching();
428429
idc_ipc();
430+
mem_hot_path_stop_watching();
429431
break;
430432
#if CONFIG_IPC_MAJOR_4
431433
case iTS(IDC_MSG_BIND):

src/ipc/ipc-zephyr.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ enum task_state ipc_platform_do_cmd(struct ipc *ipc)
217217
{
218218
struct ipc_cmd_hdr *hdr;
219219

220+
mem_hot_path_start_watching();
221+
220222
hdr = ipc_compact_read_msg();
221223

222224
/* perform command */
@@ -242,6 +244,8 @@ enum task_state ipc_platform_do_cmd(struct ipc *ipc)
242244
#endif /* CONFIG_PM */
243245
}
244246

247+
mem_hot_path_stop_watching();
248+
245249
return SOF_TASK_STATE_COMPLETED;
246250
}
247251

src/ipc/ipc4/handler.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,8 @@ int ipc4_pipeline_trigger(struct ipc_comp_dev *ppl_icd, uint32_t cmd, bool *dela
477477
return IPC4_INVALID_REQUEST;
478478
}
479479

480+
mem_hot_path_confirm();
481+
480482
/* trigger the component */
481483
ret = pipeline_trigger(host->cd->pipeline, host->cd, cmd);
482484
if (ret < 0) {

xtos/include/sof/lib/memory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
#endif
2020

2121
#define assert_can_be_cold() do {} while (0)
22+
#define mem_hot_path_confirm() do {} while (0)
2223

2324
#endif /* __SOF_LIB_MEMORY_H__ */

zephyr/include/sof/lib/memory.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,22 @@ bool ll_sch_is_current(void);
2525
#define ll_sch_is_current() false
2626
#endif
2727

28+
void mem_hot_path_start_watching(void);
29+
void mem_hot_path_stop_watching(void);
30+
void mem_hot_path_confirm(void);
31+
void mem_cold_path_enter(const char *fn);
32+
2833
static inline void __assert_can_be_cold(const char *fn)
2934
{
3035
__ASSERT(!ll_sch_is_current(), "%s() called from an LL thread!", fn);
36+
mem_cold_path_enter(fn);
3137
}
3238
#define assert_can_be_cold() __assert_can_be_cold(__func__)
3339
#else
40+
#define mem_hot_path_start_watching() do {} while (0)
41+
#define mem_hot_path_stop_watching() do {} while (0)
42+
#define mem_hot_path_confirm() do {} while (0)
43+
#define mem_cold_path_enter() do {} while (0)
3444
#define assert_can_be_cold() do {} while (0)
3545
#endif
3646

0 commit comments

Comments
 (0)