From a2e0c2432e4874a0346aa587885657217e965fcb Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 11 Jan 2017 01:14:18 +0800 Subject: [PATCH] esp32: sanity check ISR handler address passed into esp_intr_alloc Return ESP_ERR_INVALID_ARG if the handler is not in IRAM (or RTC fast memory) --- components/esp32/crosscore_int.c | 6 +++-- components/esp32/include/esp_intr_alloc.h | 5 ++++- components/esp32/intr_alloc.c | 6 +++++ components/esp32/test/test_intr_alloc.c | 27 +++++++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/components/esp32/crosscore_int.c b/components/esp32/crosscore_int.c index b58d3d62c5..1e131eeef7 100644 --- a/components/esp32/crosscore_int.c +++ b/components/esp32/crosscore_int.c @@ -73,11 +73,13 @@ void esp_crosscore_int_init() { portENTER_CRITICAL(&reasonSpinlock); reason[xPortGetCoreID()]=0; portEXIT_CRITICAL(&reasonSpinlock); + esp_err_t err; if (xPortGetCoreID()==0) { - esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL); + err = esp_intr_alloc(ETS_FROM_CPU_INTR0_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL); } else { - esp_intr_alloc(ETS_FROM_CPU_INTR1_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL); + err = esp_intr_alloc(ETS_FROM_CPU_INTR1_SOURCE, ESP_INTR_FLAG_IRAM, esp_crosscore_isr, (void*)&reason[xPortGetCoreID()], NULL); } + assert(err == ESP_OK); } void esp_crosscore_int_send_yield(int coreId) { diff --git a/components/esp32/include/esp_intr_alloc.h b/components/esp32/include/esp_intr_alloc.h index c1f91dd2e3..7195d07d87 100644 --- a/components/esp32/include/esp_intr_alloc.h +++ b/components/esp32/include/esp_intr_alloc.h @@ -124,6 +124,9 @@ esp_err_t esp_intr_reserve(int intno, int cpu); * * The interrupt will always be allocated on the core that runs this function. * + * If ESP_INTR_FLAG_IRAM flag is used, and handler address is not in IRAM or + * RTC_FAST_MEM, then ESP_ERR_INVALID_ARG is returned. + * * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux * sources, as defined in soc/soc.h, or one of the internal * ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header. @@ -264,4 +267,4 @@ void esp_intr_noniram_enable(); } #endif -#endif \ No newline at end of file +#endif diff --git a/components/esp32/intr_alloc.c b/components/esp32/intr_alloc.c index 4fdda2f396..1cb2fba5d9 100644 --- a/components/esp32/intr_alloc.c +++ b/components/esp32/intr_alloc.c @@ -446,6 +446,12 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre if ((flags&ESP_INTR_FLAG_SHARED) && (!handler || source<0)) return ESP_ERR_INVALID_ARG; //Statusreg should have a mask if (intrstatusreg && !intrstatusmask) return ESP_ERR_INVALID_ARG; + //If the ISR is marked to be IRAM-resident, the handler must not be in the cached region + if ((flags&ESP_INTR_FLAG_IRAM) && + (ptrdiff_t) handler >= 0x400C0000 && + (ptrdiff_t) handler < 0x50000000 ) { + return ESP_ERR_INVALID_ARG; + } //Default to prio 1 for shared interrupts. Default to prio 1, 2 or 3 for non-shared interrupts. if ((flags&ESP_INTR_FLAG_LEVELMASK)==0) { diff --git a/components/esp32/test/test_intr_alloc.c b/components/esp32/test/test_intr_alloc.c index 329fc9a9e4..a5e6f06834 100644 --- a/components/esp32/test/test_intr_alloc.c +++ b/components/esp32/test/test_intr_alloc.c @@ -201,3 +201,30 @@ TEST_CASE("Intr_alloc test, shared ints", "[esp32]") { timer_test(ESP_INTR_FLAG_SHARED); } + +TEST_CASE("Can allocate IRAM int only with an IRAM handler", "[esp32]") +{ + void dummy(void* arg) + { + } + IRAM_ATTR void dummy_iram(void* arg) + { + } + RTC_IRAM_ATTR void dummy_rtc(void* arg) + { + } + intr_handle_t ih; + esp_err_t err = esp_intr_alloc(ETS_INTERNAL_PROFILING_INTR_SOURCE, + ESP_INTR_FLAG_IRAM, &dummy, NULL, &ih); + TEST_ASSERT_EQUAL_INT(ESP_ERR_INVALID_ARG, err); + err = esp_intr_alloc(ETS_INTERNAL_PROFILING_INTR_SOURCE, + ESP_INTR_FLAG_IRAM, &dummy_iram, NULL, &ih); + TEST_ESP_OK(err); + err = esp_intr_free(ih); + TEST_ESP_OK(err); + err = esp_intr_alloc(ETS_INTERNAL_PROFILING_INTR_SOURCE, + ESP_INTR_FLAG_IRAM, &dummy_rtc, NULL, &ih); + TEST_ESP_OK(err); + err = esp_intr_free(ih); + TEST_ESP_OK(err); +}