From 5224f8bd9e0b61325b82f746dfa6958ece1cc381 Mon Sep 17 00:00:00 2001 From: Liam Girdwood Date: Sun, 19 Jul 2026 16:42:52 +0100 Subject: [PATCH] library_manager: Guard DRAM store/restore with CONFIG_ADSP_IMR_CONTEXT_SAVE When ADSP IMR context save is disabled (CONFIG_ADSP_IMR_CONTEXT_SAVE=n), the HP-SRAM and L3 heap memory are lost during PM runtime suspend/resume. However, the LLEXT library manager state `lib_manager_dram` resides in the persistent IMR data section (`__imrdata`) and retains stale pointers (such as `lib_manager_dram.ctx` pointing to the now-invalid L3 heap address from the first boot). On resume, `llext_manager_restore_from_dram()` would try to restore libraries from these stale pointers, causing register window underflows and fatal exceptions (EXCCAUSE_ILLEGAL) when executing scheduler work queues on subsequent IPC handling. Guard `llext_manager_store_to_dram()` and `llext_manager_restore_from_dram()` with `IS_ENABLED(CONFIG_ADSP_IMR_CONTEXT_SAVE)`. If context save is disabled, the library manager cleanly re-initializes on resume boot, forcing libraries to reload correctly. Signed-off-by: Liam Girdwood --- src/library_manager/llext_manager_dram.c | 18 ++++++++++++++++++ zephyr/lib/alloc.c | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/library_manager/llext_manager_dram.c b/src/library_manager/llext_manager_dram.c index 2f6cff2b3501..d3401952f443 100644 --- a/src/library_manager/llext_manager_dram.c +++ b/src/library_manager/llext_manager_dram.c @@ -35,6 +35,15 @@ __imrdata static struct lib_manager_dram_storage lib_manager_dram; /* Store LLEXT manager context in DRAM to be restored during the next boot. */ int llext_manager_store_to_dram(void) { + /* + * If IMR context save is disabled, HP-SRAM and L3 heap memory are lost + * on suspend/resume, but IMR remains persistent. Skip saving to avoid + * restoring stale pointers. + */ + if (!IS_ENABLED(CONFIG_ADSP_IMR_CONTEXT_SAVE)) { + return 0; + } + struct ext_library *_ext_lib = ext_lib_get(); unsigned int i, j, k, l, n_lib, n_mod, n_llext, n_sect, n_sym; size_t buf_size; @@ -161,6 +170,15 @@ int llext_manager_store_to_dram(void) int llext_manager_restore_from_dram(void) { + /* + * If IMR context save is disabled, the L3 heap and HP-SRAM memory were lost. + * The saved context will contain stale pointers, so cleanly re-initialize instead. + */ + if (!IS_ENABLED(CONFIG_ADSP_IMR_CONTEXT_SAVE)) { + lib_manager_init(); + return 0; + } + lib_manager_init(); struct ext_library *_ext_lib = ext_lib_get(); diff --git a/zephyr/lib/alloc.c b/zephyr/lib/alloc.c index 031b31673be8..fd8d0e960b4b 100644 --- a/zephyr/lib/alloc.c +++ b/zephyr/lib/alloc.c @@ -838,7 +838,11 @@ static int heap_init(void) arch_mem_map(l3_heap_start, va, l3_heap_size, K_MEM_PERM_RW | K_MEM_CACHE_WB); #endif - if (l3_heap_copy.heap.heap) { + /* + * If IMR context save is disabled, the L3 heap memory is lost during + * suspend/resume, so do not restore from the stale copy. + */ + if (IS_ENABLED(CONFIG_ADSP_IMR_CONTEXT_SAVE) && l3_heap_copy.heap.heap) { l3_heap = l3_heap_copy; } else { l3_heap.heap.init_mem = l3_heap_start;