Skip to content

zephyr: alloc: place L3 heap after the firmware image in IMR - #11335

Open
kv2019i wants to merge 1 commit into
thesofproject:mainfrom
kv2019i:202610-l3-heap-calc-offset
Open

kv2019i wants to merge 1 commit into
thesofproject:mainfrom
kv2019i:202610-l3-heap-calc-offset

Conversation

@kv2019i

@kv2019i kv2019i commented Oct 22, 2026

Copy link
Copy Markdown
Collaborator

The L3 heap started at the fixed IMR_L3_HEAP_BASE offset. The firmware image stays in IMR after boot, and when the DSP is resumed from IMR, the boot loader copies the image to SRAM again from there. If the image extends beyond IMR_L3_HEAP_BASE, heap initialization and L3 allocations (e.g. the LLEXT context saved before D3) overwrite the tail of the image and the next IMR boot hangs before the firmware is ready.

This happens with LL userspace enabled on NVL, where the image ends at L3 base + 0x185000 while the heap started at L3 base + 0x151000. The host reports "Firmware boot failure due to timeout" when the stream is started after the DSP has been suspended.

Calculate the end of the image from the preload page count in the firmware manifest and start the heap after it, if that is beyond IMR_L3_HEAP_BASE. Leave the L3 heap uninitialized if there is no IMR space left after the image, and fail L3 allocations in that case.

Copilot AI balanced review requested due to automatic review settings October 22, 2026 16:35
@kv2019i
kv2019i requested a review from dabekjakub as a code owner October 22, 2026 16:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Boot-critical manifest access and heap relocation need platform validation covering MMU/cache behavior, exhausted IMR space, and D3 suspend/resume.

No open issues 🎉

What changed in this PR

This PR prevents L3 heap allocations from overwriting the firmware image retained in IMR, addressing suspend/resume boot failures with LL userspace enabled on NVL.

Changes:

  • Calculate the heap start from the manifest’s preload page count, keeping it at or beyond the existing fixed base.
  • Calculate available heap space from the adjusted start.
  • Skip heap initialization and reject L3 allocations when no usable IMR space remains.
File Description
zephyr/​lib/​alloc.c Places the L3 heap after the retained firmware image and handles exhausted IMR space.

Review effort: Balanced

@intel-sofci

Copy link
Copy Markdown

PR 11335: test results

Run date: 2026-10-22 17:07 UTC

Tested commit: 8b94716f02622d0d6c1eccc2f172e6307e83e5da

mtl pass rate lnl pass rate ptl pass rate wcl pass rate nvl pass rate

Comment thread zephyr/lib/alloc.c Outdated
image_end = IMR_BOOT_LDR_MANIFEST_BASE +
desc->header.preload_page_count * HOST_PAGE_SIZE;

return ROUND_UP(MAX(IMR_L3_HEAP_BASE, image_end), L3_MEM_PAGE_SIZE);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should just get rid of IMR_L3_HEAP_BASE. The define is marked with "FIXME"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack @wjablon1 , it seems it's not used anywhere else, so indeed, let's just drop it. I'll updated this to V2. Once merged, we can post a PR to remove the definition from Zephyr side.

Comment thread zephyr/lib/alloc.c Outdated
*/
size_t offset = IMR_L3_HEAP_BASE - L3_MEM_BASE_ADDR;
uintptr_t imr_end = L3_MEM_BASE_ADDR + ace_imr_get_mem_size();
uintptr_t start = get_l3_heap_start();

@wjablon1 wjablon1 Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: Since the calculation is now more complicated, I would consider renaming those functions to calc_heap_start and calc_heap_size and call them only upon heap creation. After that the size could be obtain from heap global structure.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack, addressed in V2.

The L3 heap started at the fixed IMR_L3_HEAP_BASE offset. The firmware
image stays in IMR after boot, and when the DSP is resumed from IMR,
the boot loader copies the image to SRAM again from there. If the image
extends beyond IMR_L3_HEAP_BASE, heap initialization and L3 allocations
(e.g. the LLEXT context saved before D3) overwrite the tail of the image
and the next IMR boot hangs before the firmware is ready.

This happens with LL userspace enabled on NVL, where the image ends at
L3 base + 0x185000 while the heap started at L3 base + 0x151000. The
host reports "Firmware boot failure due to timeout" when the stream is
started after the DSP has been suspended.

Drop the fixed IMR_L3_HEAP_BASE and calculate the end of the image from
the preload page count in the firmware manifest and start the heap after
it. Leave the L3 heap uninitialized if there is no IMR space left after
the image, and fail L3 allocations in that case.

Rename get_l3_heap_start() and get_l3_heap_size() and only call
the new calc_l3_heap_*() functions at l3 heap init time.

Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com>
@kv2019i
kv2019i force-pushed the 202610-l3-heap-calc-offset branch from 8b94716 to 1181ba7 Compare October 23, 2026 08:07
@kv2019i

kv2019i commented Oct 23, 2026

Copy link
Copy Markdown
Collaborator Author

V2 pushed:

  • addressed review feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants