Merge branch 'fix/dualcore_branch_predictor_cache_race_v6.0' into 'release/v6.0'

fix(spi_flash): disable branch prediction on the parked core during flash ops (v6.0)

See merge request espressif/esp-idf!52202
This commit is contained in:
morris
2026-09-04 17:57:09 +08:00
7 changed files with 94 additions and 23 deletions
@@ -7,6 +7,7 @@
#include "stdint.h"
#include "soc/interrupt_reg.h"
#include "soc/soc_caps.h"
#include "esp_cpu.h"
#include "esp_ipc_isr.h"
#include "esp_private/esp_ipc_isr.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)
{
#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;
while (esp_ipc_isr_stall_args.cmd == ESP_IPC_ISR_CMD_RESET_STATE) {
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;
}
}
#if SOC_BRANCH_PREDICTOR_SUPPORTED
esp_cpu_branch_prediction_enable();
#endif
}
@@ -120,6 +120,15 @@ static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_exc
FORCE_INLINE_ATTR __attribute__((__noreturn__))
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();
}
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE