Merge branch 'feat/cache_panic_p4_v5.3' into 'release/v5.3'

cache:cache panic p4 (v5.3)

See merge request espressif/esp-idf!32110
This commit is contained in:
Marius Vikhammer
2024-07-25 18:56:39 +08:00
7 changed files with 83 additions and 30 deletions

View File

@@ -39,7 +39,6 @@
*/
static inline void print_cache_err_details(const void *frame)
{
#if !CONFIG_IDF_TARGET_ESP32P4
const char* cache_err_msg = esp_cache_err_panic_string();
if (cache_err_msg) {
panic_print_str(cache_err_msg);
@@ -47,7 +46,6 @@ static inline void print_cache_err_details(const void *frame)
panic_print_str("Cache error active, but failed to find a corresponding error message");
}
panic_print_str("\r\n");
#endif
}
#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
@@ -195,7 +193,7 @@ bool panic_soc_check_pseudo_cause(void *f, panic_info_t *info)
/* Cache errors when reading instructions will result in an illegal instructions,
before any cache error interrupts trigger. We override the exception cause if
any cache errors are active to more accurately report the actual reason */
if (esp_cache_err_has_active_err() && (frame->mcause == MCAUSE_ILLEGAL_INSTRUCTION)) {
if (esp_cache_err_has_active_err() && ((frame->mcause == MCAUSE_ILLEGAL_INSTRUCTION) || (frame->mcause == MCAUSE_ILLIGAL_INSTRUCTION_ACCESS) || (frame->mcause == MCAUSE_LOAD_ACCESS_FAULT))) {
pseudo_cause = true;
frame->mcause = ETS_CACHEERR_INUM;
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,19 +20,24 @@
static const char *TAG = "CACHE_ERR";
//TODO: IDF-7515
const char cache_error_msg[] = "Cache access error";
const char *esp_cache_err_panic_string(void)
{
return NULL;
uint32_t access_err_status = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK) | cache_ll_l2_get_access_error_intr_status(0, CACHE_LL_L2_ACCESS_EVENT_MASK);
/* Return the error string if a cache error is active */
const char* err_str = access_err_status ? cache_error_msg : NULL;
return err_str;
}
//TODO: IDF-7515
bool esp_cache_err_has_active_err(void)
{
return false;
bool has_active_err = cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_ACCESS_EVENT_MASK) | cache_ll_l2_get_access_error_intr_status(0, CACHE_LL_L2_ACCESS_EVENT_MASK);
return has_active_err;
}
//TODO: IDF-7515
void esp_cache_err_int_init(void)
{
const uint32_t core_id = 0;
@@ -56,10 +61,13 @@ void esp_cache_err_int_init(void)
esprv_int_set_priority(ETS_CACHEERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
ESP_DRAM_LOGV(TAG, "access error intr clr & ena mask is: 0x%x", CACHE_LL_L1_ACCESS_EVENT_MASK);
/* On the hardware side, start by clearing all the bits reponsible for cache access error */
/* On the hardware side, start by clearing all the bits responsible for cache access error */
cache_ll_l1_clear_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
cache_ll_l2_clear_access_error_intr(0, CACHE_LL_L2_ACCESS_EVENT_MASK);
/* Then enable cache access error interrupts. */
cache_ll_l1_enable_access_error_intr(0, CACHE_LL_L1_ACCESS_EVENT_MASK);
cache_ll_l2_enable_access_error_intr(0, CACHE_LL_L2_ACCESS_EVENT_MASK);
/* Enable the interrupts for cache error. */
ESP_INTR_ENABLE(ETS_CACHEERR_INUM);
@@ -67,7 +75,11 @@ void esp_cache_err_int_init(void)
int esp_cache_err_get_cpuid(void)
{
//TODO: IDF-7515
//Should return hart ID according to the cache error
return 0;
if (cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_CORE0_EVENT_MASK)) {
return 0;
} else if (cache_ll_l1_get_access_error_intr_status(0, CACHE_LL_L1_CORE1_EVENT_MASK)) {
return 1;
} else {
return -1;
}
}

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,6 +10,7 @@
#include <stdbool.h>
#include "soc/cache_reg.h"
#include "soc/cache_struct.h"
#include "soc/ext_mem_defs.h"
#include "hal/cache_types.h"
#include "hal/assert.h"
@@ -47,8 +48,10 @@ extern "C" {
#define CACHE_LL_DEFAULT_IBUS_MASK (CACHE_BUS_IBUS0 | CACHE_BUS_IBUS1 | CACHE_BUS_IBUS2)
#define CACHE_LL_DEFAULT_DBUS_MASK (CACHE_BUS_DBUS0 | CACHE_BUS_DBUS1 | CACHE_BUS_DBUS2)
//TODO: IDF-7515
#define CACHE_LL_L1_ACCESS_EVENT_MASK (0x3f)
#define CACHE_LL_L1_ACCESS_EVENT_MASK (0x1f)
#define CACHE_LL_L2_ACCESS_EVENT_MASK (1<<6)
#define CACHE_LL_L1_CORE0_EVENT_MASK (1<<0)
#define CACHE_LL_L1_CORE1_EVENT_MASK (1<<1)
/*------------------------------------------------------------------------------
* Autoload
@@ -1019,27 +1022,29 @@ static inline bool cache_ll_vaddr_to_cache_level_id(uint32_t vaddr_start, uint32
* Interrupt
*----------------------------------------------------------------------------*/
/**
* @brief Enable Cache access error interrupt
* @brief Enable L1 Cache access error interrupt
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l1_enable_access_error_intr(uint32_t cache_id, uint32_t mask)
{
CACHE.l1_cache_acs_fail_int_ena.val |= mask;
}
/**
* @brief Clear Cache access error interrupt status
* @brief Clear L1 Cache access error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l1_clear_access_error_intr(uint32_t cache_id, uint32_t mask)
{
CACHE.l1_cache_acs_fail_int_clr.val = mask;
}
/**
* @brief Get Cache access error interrupt status
* @brief Get L1 Cache access error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
@@ -1048,7 +1053,42 @@ static inline void cache_ll_l1_clear_access_error_intr(uint32_t cache_id, uint32
*/
static inline uint32_t cache_ll_l1_get_access_error_intr_status(uint32_t cache_id, uint32_t mask)
{
return 0;
return CACHE.l1_cache_acs_fail_int_st.val & mask;
}
/**
* @brief Enable L2 Cache access error interrupt
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l2_enable_access_error_intr(uint32_t cache_id, uint32_t mask)
{
CACHE.l2_cache_acs_fail_int_ena.val |= mask;
}
/**
* @brief Clear L2 Cache access error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*/
static inline void cache_ll_l2_clear_access_error_intr(uint32_t cache_id, uint32_t mask)
{
CACHE.l2_cache_acs_fail_int_clr.val = mask;
}
/**
* @brief Get L2 Cache access error interrupt status
*
* @param cache_id Cache ID
* @param mask Interrupt mask
*
* @return Status mask
*/
static inline uint32_t cache_ll_l2_get_access_error_intr_status(uint32_t cache_id, uint32_t mask)
{
return CACHE.l2_cache_acs_fail_int_st.val & mask;
}
#ifdef __cplusplus

View File

@@ -19,4 +19,6 @@
#define PANIC_RSN_CACHEERR 3
#define MCAUSE_ILLEGAL_INSTRUCTION 2
#define MCAUSE_ILLIGAL_INSTRUCTION_ACCESS 1
#define MCAUSE_ILLEGAL_INSTRUCTION 2
#define MCAUSE_LOAD_ACCESS_FAULT 5

View File

@@ -1,5 +1,5 @@
/**
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -5269,12 +5269,12 @@ typedef union {
struct {
/** l1_icache0_unalloc_clr : R/W; bitpos: [0]; default: 0;
* The bit is used to clear the unallocate request buffer of l1 icache0 where the
* unallocate request is responsed but not completed.
* unallocate request is responded but not completed.
*/
uint32_t l1_icache0_unalloc_clr:1;
/** l1_icache1_unalloc_clr : R/W; bitpos: [1]; default: 0;
* The bit is used to clear the unallocate request buffer of l1 icache1 where the
* unallocate request is responsed but not completed.
* unallocate request is responded but not completed.
*/
uint32_t l1_icache1_unalloc_clr:1;
/** l1_icache2_unalloc_clr : HRO; bitpos: [2]; default: 0;
@@ -5287,7 +5287,7 @@ typedef union {
uint32_t l1_icache3_unalloc_clr:1;
/** l1_dcache_unalloc_clr : R/W; bitpos: [4]; default: 0;
* The bit is used to clear the unallocate request buffer of l1 dcache where the
* unallocate request is responsed but not completed.
* unallocate request is responded but not completed.
*/
uint32_t l1_dcache_unalloc_clr:1;
uint32_t reserved_5:27;
@@ -5303,7 +5303,7 @@ typedef union {
uint32_t reserved_0:5;
/** l2_cache_unalloc_clr : R/W; bitpos: [5]; default: 0;
* The bit is used to clear the unallocate request buffer of l2 icache where the
* unallocate request is responsed but not completed.
* unallocate request is responded but not completed.
*/
uint32_t l2_cache_unalloc_clr:1;
uint32_t reserved_6:26;
@@ -5548,7 +5548,7 @@ typedef union {
} cache_date_reg_t;
typedef struct {
typedef struct cache_dev_t {
volatile cache_l1_icache_ctrl_reg_t l1_icache_ctrl;
volatile cache_l1_dcache_ctrl_reg_t l1_dcache_ctrl;
volatile cache_l1_bypass_cache_conf_reg_t l1_bypass_cache_conf;
@@ -5799,6 +5799,7 @@ typedef struct {
volatile cache_date_reg_t date;
} cache_dev_t;
extern cache_dev_t CACHE;
#ifndef __cplusplus
_Static_assert(sizeof(cache_dev_t) == 0x400, "Invalid size of cache_dev_t structure");

View File

@@ -117,3 +117,5 @@ PROVIDE ( USB_UTMI = 0x5009C000 );
PROVIDE ( EMAC_MAC = 0x50098000 );
PROVIDE ( EMAC_DMA = 0x50099000 );
PROVIDE ( CACHE = 0x3FF10000);

View File

@@ -267,14 +267,12 @@ def test_cache_error(dut: PanicTestDut, config: str, test_func_name: str) -> Non
if dut.target in ['esp32c3', 'esp32c2']:
dut.expect_gme('Cache error')
dut.expect_exact('Cached memory region accessed while ibus or cache is disabled')
elif dut.target in ['esp32c6', 'esp32h2']:
elif dut.target in ['esp32c6', 'esp32h2', 'esp32p4']:
dut.expect_gme('Cache error')
dut.expect_exact('Cache access error')
elif dut.target in ['esp32s2']:
# Cache error interrupt is not enabled, IDF-1558
dut.expect_gme('IllegalInstruction')
elif dut.target in ['esp32p4']: # TODO IDF-7515
dut.expect_gme('Instruction access fault')
else:
dut.expect_gme('Cache disabled but cached memory region accessed')
dut.expect_reg_dump(0)