mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(esp32): Fix access to MALLOC_CAP_IRAM_8BIT byte array in loop
The Xtensa load/store handler did not properly handle 8/16-bit memory access to IRAM regions configured with MALLOC_CAP_IRAM_8BIT (and CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY=y) from a loop (LBEG/LEND/LCOUNT) context. This caused the loop to exit after the first access, instead of continuing to iterate as intended. Closes https://github.com/espressif/esp-idf/issues/14127
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Zero-overhead loop adjustment helpers for Xtensa assembly code.
|
||||
*
|
||||
* Used by exception handlers to emulate loop hardware when an exception
|
||||
* occurs at LEND so execution resumes at LBEG with LCOUNT decremented.
|
||||
*/
|
||||
|
||||
#ifndef XTENSA_ZOL_MACROS_H
|
||||
#define XTENSA_ZOL_MACROS_H
|
||||
|
||||
#if __XTENSA__
|
||||
#include "xtensa/config/core-isa.h"
|
||||
#include "xtensa/config/xt_specreg.h"
|
||||
|
||||
/**
|
||||
* Adjust loop counter and return address for exceptions at LEND.
|
||||
*
|
||||
* When an exception occurs on instruction at LEND address of a zero-overhead loop,
|
||||
* we must decrement LCOUNT and set EPC back to LBEG so the loop continues
|
||||
* iterating after the exception is handled. Otherwise, the loop exits prematurely.
|
||||
*
|
||||
* if (EPC == LEND && LCOUNT != 0) {
|
||||
* LCOUNT--;
|
||||
* EPC = LBEG;
|
||||
* }
|
||||
*
|
||||
* param[in/out] epc_reg - register containing EPC, updated to LBEG if needed
|
||||
* param[in/out] tmp_reg - temporary register for intermediate values
|
||||
*
|
||||
* Return: Use epc_reg to set corrected EPC value.
|
||||
*/
|
||||
.macro XT_ZOL_EPC_LCOUNT_RESTORE epc_reg tmp_reg
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
rsr \tmp_reg, XT_REG_LEND
|
||||
bne \epc_reg, \tmp_reg, 1f
|
||||
rsr \tmp_reg, XT_REG_LCOUNT
|
||||
beqz \tmp_reg, 1f
|
||||
addi \tmp_reg, \tmp_reg, -1
|
||||
wsr \tmp_reg, XT_REG_LCOUNT
|
||||
rsr \epc_reg, XT_REG_LBEG
|
||||
1:
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#endif /* __XTENSA__ */
|
||||
|
||||
#endif /* XTENSA_ZOL_MACROS_H */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -37,6 +37,7 @@
|
||||
*/
|
||||
|
||||
#include "xtensa_rtos.h"
|
||||
#include "xtensa/xtensa_zol_macros.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
@@ -124,10 +125,11 @@ LoadStoreErrorHandler:
|
||||
|
||||
2:
|
||||
/* a4 contains the value */
|
||||
wsr a0, sar
|
||||
rsr a3, epc1
|
||||
addi a3, a3, 3
|
||||
XT_ZOL_EPC_LCOUNT_RESTORE a3, a0 // If faulted at LEND, rewinds loop and leaves adjusted PC in a3
|
||||
wsr a3, epc1
|
||||
wsr a0, sar
|
||||
rsr a0, excsave1
|
||||
|
||||
extui a2, a2, 3, 5
|
||||
@@ -169,6 +171,7 @@ LoadStoreErrorHandler:
|
||||
/* a4 contains the value */
|
||||
rsr a6, epc1
|
||||
addi a6, a6, 3
|
||||
XT_ZOL_EPC_LCOUNT_RESTORE a6, a5 // If faulted at LEND, rewinds loop and leaves adjusted PC in a6
|
||||
wsr a6, epc1
|
||||
|
||||
ssa8b a3
|
||||
@@ -321,8 +324,9 @@ AlignmentErrorHandler:
|
||||
srai a4, a4, 16 // a4 contains the value
|
||||
|
||||
1:
|
||||
wsr a3, epc1
|
||||
wsr a0, sar
|
||||
XT_ZOL_EPC_LCOUNT_RESTORE a3, a0 // If faulted at LEND, rewinds loop and leaves adjusted PC in a3
|
||||
wsr a3, epc1
|
||||
rsr a0, excsave1
|
||||
|
||||
extui a2, a2, 4, 4
|
||||
@@ -379,6 +383,7 @@ AlignmentErrorHandler:
|
||||
slli a6, a5, 16 // 0xffff0000
|
||||
|
||||
1:
|
||||
XT_ZOL_EPC_LCOUNT_RESTORE a7, a5 // If faulted at LEND, rewinds loop and leaves adjusted PC in a7
|
||||
wsr a7, epc1
|
||||
movi a5, ~3
|
||||
and a5, a3, a5 // a5 has the aligned address
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
*/
|
||||
|
||||
#include "xtensa_rtos.h"
|
||||
#include "xtensa/xtensa_zol_macros.h"
|
||||
#include "esp_private/panic_reason.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
@@ -904,22 +905,13 @@ _xt_syscall_exc:
|
||||
#endif
|
||||
|
||||
/*
|
||||
Grab the interruptee's PC and skip over the 'syscall' instruction.
|
||||
If it's at the end of a zero-overhead loop and it's not on the last
|
||||
iteration, decrement loop counter and skip to beginning of loop.
|
||||
Adjust EPC to point to next instruction, so when we return to user code
|
||||
it will be at the instruction after the 'syscall' that caused the exception.
|
||||
*/
|
||||
rsr a2, EPC_1 /* a2 = PC of 'syscall' */
|
||||
addi a3, a2, 3 /* ++PC */
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
rsr a0, LEND /* if (PC == LEND */
|
||||
bne a3, a0, 1f
|
||||
rsr a0, LCOUNT /* && LCOUNT != 0) */
|
||||
beqz a0, 1f /* { */
|
||||
addi a0, a0, -1 /* --LCOUNT */
|
||||
rsr a3, LBEG /* PC = LBEG */
|
||||
wsr a0, LCOUNT /* } */
|
||||
#endif
|
||||
1: wsr a3, EPC_1 /* update PC */
|
||||
XT_ZOL_EPC_LCOUNT_RESTORE a3, a0 /* If faulted at LEND, rewinds loop and leaves adjusted PC in a3 */
|
||||
wsr a3, EPC_1 /* update PC to next instruction */
|
||||
|
||||
/* Restore interruptee's context and return from exception. */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
|
||||
Reference in New Issue
Block a user