diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index 718a01116b..b2278dacb7 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -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; } diff --git a/components/esp_system/port/soc/esp32p4/cache_err_int.c b/components/esp_system/port/soc/esp32p4/cache_err_int.c index c1a20bbee1..24904c2d5a 100644 --- a/components/esp_system/port/soc/esp32p4/cache_err_int.c +++ b/components/esp_system/port/soc/esp32p4/cache_err_int.c @@ -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; + } } diff --git a/components/hal/esp32p4/include/hal/cache_ll.h b/components/hal/esp32p4/include/hal/cache_ll.h index c2f4bbd2f0..5e1a07130e 100644 --- a/components/hal/esp32p4/include/hal/cache_ll.h +++ b/components/hal/esp32p4/include/hal/cache_ll.h @@ -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 #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 diff --git a/components/riscv/include/esp_private/panic_reason.h b/components/riscv/include/esp_private/panic_reason.h index 252f6de9c0..fdbee96fa3 100644 --- a/components/riscv/include/esp_private/panic_reason.h +++ b/components/riscv/include/esp_private/panic_reason.h @@ -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 diff --git a/components/soc/esp32p4/include/soc/cache_struct.h b/components/soc/esp32p4/include/soc/cache_struct.h index 0c6fb056d5..67e57371b2 100644 --- a/components/soc/esp32p4/include/soc/cache_struct.h +++ b/components/soc/esp32p4/include/soc/cache_struct.h @@ -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"); diff --git a/components/soc/esp32p4/ld/esp32p4.peripherals.ld b/components/soc/esp32p4/ld/esp32p4.peripherals.ld index f8aaaf3fef..82b7bd46b7 100644 --- a/components/soc/esp32p4/ld/esp32p4.peripherals.ld +++ b/components/soc/esp32p4/ld/esp32p4.peripherals.ld @@ -117,3 +117,5 @@ PROVIDE ( USB_UTMI = 0x5009C000 ); PROVIDE ( EMAC_MAC = 0x50098000 ); PROVIDE ( EMAC_DMA = 0x50099000 ); + +PROVIDE ( CACHE = 0x3FF10000); diff --git a/tools/test_apps/system/panic/pytest_panic.py b/tools/test_apps/system/panic/pytest_panic.py index e3193670ad..5287f5dde3 100644 --- a/tools/test_apps/system/panic/pytest_panic.py +++ b/tools/test_apps/system/panic/pytest_panic.py @@ -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)