mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(spi_flash): disable branch prediction on the parked core during flash ops
This commit is contained in:
@@ -7,6 +7,7 @@
|
|||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
#include "soc/interrupt_reg.h"
|
#include "soc/interrupt_reg.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
#include "esp_cpu.h"
|
||||||
#include "esp_ipc_isr.h"
|
#include "esp_ipc_isr.h"
|
||||||
#include "esp_private/esp_ipc_isr.h"
|
#include "esp_private/esp_ipc_isr.h"
|
||||||
#include "esp_private/esp_system_attr.h"
|
#include "esp_private/esp_system_attr.h"
|
||||||
@@ -46,6 +47,15 @@ void ESP_SYSTEM_IRAM_ATTR esp_ipc_isr_record_interrupted_context(void)
|
|||||||
|
|
||||||
void ESP_SYSTEM_IRAM_ATTR esp_ipc_isr_waiting_for_finish_cmd(void* arg)
|
void ESP_SYSTEM_IRAM_ATTR esp_ipc_isr_waiting_for_finish_cmd(void* arg)
|
||||||
{
|
{
|
||||||
|
#if SOC_BRANCH_PREDICTOR_SUPPORTED
|
||||||
|
/* The branch predictor keeps issuing speculative instruction fetches while
|
||||||
|
* this core spins here. Callers of esp_ipc_isr_stall_other_cpu() may
|
||||||
|
* suspend the external memory cache during the stall (e.g. sleep flows
|
||||||
|
* powering down flash), in which case a speculative fetch into cached
|
||||||
|
* address space raises a cache access-fail interrupt. Keep the predictor
|
||||||
|
* disabled until the stall is released. */
|
||||||
|
esp_cpu_branch_prediction_disable();
|
||||||
|
#endif
|
||||||
esp_ipc_isr_stall_fl = 1;
|
esp_ipc_isr_stall_fl = 1;
|
||||||
while (esp_ipc_isr_stall_args.cmd == ESP_IPC_ISR_CMD_RESET_STATE) {
|
while (esp_ipc_isr_stall_args.cmd == ESP_IPC_ISR_CMD_RESET_STATE) {
|
||||||
if (esp_ipc_isr_stall_args.func != NULL) {
|
if (esp_ipc_isr_stall_args.func != NULL) {
|
||||||
@@ -53,4 +63,7 @@ void ESP_SYSTEM_IRAM_ATTR esp_ipc_isr_waiting_for_finish_cmd(void* arg)
|
|||||||
esp_ipc_isr_stall_args.func = NULL;
|
esp_ipc_isr_stall_args.func = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if SOC_BRANCH_PREDICTOR_SUPPORTED
|
||||||
|
esp_cpu_branch_prediction_enable();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,6 +126,15 @@ static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_exc
|
|||||||
FORCE_INLINE_ATTR __attribute__((__noreturn__))
|
FORCE_INLINE_ATTR __attribute__((__noreturn__))
|
||||||
void busy_wait(void)
|
void busy_wait(void)
|
||||||
{
|
{
|
||||||
|
#if SOC_BRANCH_PREDICTOR_SUPPORTED
|
||||||
|
/* This core parks here while the offending core handles the panic, which
|
||||||
|
* may include flash accesses with the cache suspended (e.g. writing a core
|
||||||
|
* dump). Stop the branch predictor so its speculative fetches cannot latch
|
||||||
|
* spurious cache access-fail errors that would corrupt the cache error
|
||||||
|
* status of the panic being reported. This core never resumes, so the
|
||||||
|
* predictor is not re-enabled. */
|
||||||
|
esp_cpu_branch_prediction_disable();
|
||||||
|
#endif
|
||||||
ESP_INFINITE_LOOP();
|
ESP_INFINITE_LOOP();
|
||||||
}
|
}
|
||||||
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -87,6 +87,13 @@ void IRAM_ATTR spi_flash_op_block_func(void *arg)
|
|||||||
// Restore interrupts that aren't located in IRAM
|
// Restore interrupts that aren't located in IRAM
|
||||||
esp_intr_noniram_disable();
|
esp_intr_noniram_disable();
|
||||||
uint32_t cpuid = (uint32_t) arg;
|
uint32_t cpuid = (uint32_t) arg;
|
||||||
|
#if SOC_BRANCH_PREDICTOR_SUPPORTED
|
||||||
|
/* The branch predictor issues speculative cache requests while this core
|
||||||
|
* spins in IRAM. The flash-op core is about to suspend the (shared) cache,
|
||||||
|
* so speculative fetches into flash would raise a cache access-fail on
|
||||||
|
* this core. spi_flash_restore_cache() below re-enables prediction. */
|
||||||
|
esp_cpu_branch_prediction_disable();
|
||||||
|
#endif
|
||||||
// s_flash_op_complete flag is cleared on *this* CPU, otherwise the other
|
// s_flash_op_complete flag is cleared on *this* CPU, otherwise the other
|
||||||
// CPU may reset the flag back to false before IPC task has a chance to check it
|
// CPU may reset the flag back to false before IPC task has a chance to check it
|
||||||
// (if it is preempted by an ISR taking non-trivial amount of time)
|
// (if it is preempted by an ISR taking non-trivial amount of time)
|
||||||
|
|||||||
Reference in New Issue
Block a user