diff --git a/arch/xtensa/src/esp32s3/esp32s3_isolation.c b/arch/xtensa/src/esp32s3/esp32s3_isolation.c index abd421de6f0..e5e99534277 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_isolation.c +++ b/arch/xtensa/src/esp32s3/esp32s3_isolation.c @@ -146,6 +146,16 @@ static void IRAM_ATTR pms_clear_violations(void) modifyreg32(EXTMEM_CORE0_ACS_CACHE_INT_CLR_REG, EXTMEM_CORE0_IBUS_REJECT_INT_CLR_M | EXTMEM_CORE0_DBUS_REJECT_INT_CLR_M, 0); + + /* The invalid MMU entry monitor. An access that no entry translates never + * reaches the PMS, which checks physical addresses, so without this the + * cache answers it with zeros and nothing is reported. + */ + + modifyreg32(EXTMEM_CACHE_ILG_INT_CLR_REG, 0, + EXTMEM_MMU_ENTRY_FAULT_INT_CLR_M); + modifyreg32(EXTMEM_CACHE_ILG_INT_CLR_REG, + EXTMEM_MMU_ENTRY_FAULT_INT_CLR_M, 0); } #endif @@ -171,6 +181,16 @@ static int IRAM_ATTR pms_violation_isr(int cpuint, void *context, void *arg) { #ifdef CONFIG_ESP32S3_USERFAULT_ABORT uint32_t *regs = (uint32_t *)context; + const char *cause; + + /* Read why before acknowledging, because the clear below drops the latch. + * The two causes are answered the same way and are worth telling apart in + * the log: a PMS violation is a refused translation, an MMU entry fault + * is an access that was never translated at all. + */ + + cause = (getreg32(EXTMEM_CACHE_ILG_INT_ST_REG) & + EXTMEM_MMU_ENTRY_FAULT_ST_M) != 0 ? "MMU entry" : "PMS"; /* Acknowledge and re-arm the monitors first so the level-triggered * interrupt does not immediately re-fire while we handle it. @@ -190,8 +210,8 @@ static int IRAM_ATTR pms_violation_isr(int cpuint, void *context, void *arg) struct tcb_s *tcb = this_task(); siginfo_t info; - _alert("SIGSEGV (PMS) task %s: PC=%08x\n", - get_task_name(tcb), (unsigned)regs[REG_PC]); + _alert("SIGSEGV (%s) task %s: PC=%08x\n", + cause, get_task_name(tcb), (unsigned)regs[REG_PC]); info.si_signo = SIGSEGV; info.si_code = SI_USER; @@ -603,7 +623,8 @@ void esp32s3_isolation_permissions(void) * Name: esp32s3_pmsirqinitialize * * Description: - * Install the handler that reports a permission violation. + * Install the handlers that report a permission violation and an access + * that no MMU entry translates. * * Returned Value: * None. @@ -621,8 +642,21 @@ void esp32s3_pmsirqinitialize(void) VERIFY(esp_setup_irq(ESP32S3_PERIPH_CORE_0_PIF_PMS_MONITOR_VIOLATE, 1, ESP_IRQ_TRIGGER_LEVEL, pms_violation_isr, NULL)); + /* Report an access that no MMU entry translates. The PMS grants and + * refuses physical addresses, so an untranslated access is invisible to + * it: the cache returns zeros and the task carries on with a value it + * never should have had. This monitor is what turns that into a fault. + */ + + VERIFY(esp_setup_irq(ESP32S3_PERIPH_CACHE_IA, + 1, ESP_IRQ_TRIGGER_LEVEL, pms_violation_isr, NULL)); + + modifyreg32(EXTMEM_CACHE_ILG_INT_ENA_REG, 0, + EXTMEM_MMU_ENTRY_FAULT_INT_ENA_M); + up_enable_irq(ESP32S3_IRQ_CORE_0_IRAM0_PMS_MONITOR_VIOLATE); up_enable_irq(ESP32S3_IRQ_CORE_0_DRAM0_PMS_MONITOR_VIOLATE); up_enable_irq(ESP32S3_IRQ_CACHE_CORE0_ACS); up_enable_irq(ESP32S3_IRQ_CORE_0_PIF_PMS_MONITOR_VIOLATE); + up_enable_irq(ESP32S3_IRQ_CACHE_IA); } diff --git a/arch/xtensa/src/esp32s3/esp32s3_user.c b/arch/xtensa/src/esp32s3/esp32s3_user.c index 4a4183feb89..df0c8431e5e 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_user.c +++ b/arch/xtensa/src/esp32s3/esp32s3_user.c @@ -86,9 +86,12 @@ uint32_t *xtensa_user(int exccause, uint32_t *regs) * these to the dispatcher; if serviced, return the register frame so that * the RFE in the exception vector re-executes the faulting instruction. * - * Note: ESP32-S3 PMS (World Controller) memory-protection violations are - * NOT delivered as these precise causes; they raise the asynchronous - * DRAM0/IRAM0 PMS-monitor interrupt instead (handled elsewhere). + * A PMS permission violation does not arrive as one of these causes. It + * raises the asynchronous DRAM0/IRAM0 PMS monitor interrupt, which + * pms_violation_isr() in esp32s3_isolation.c serves. So does an access + * that no MMU entry translates, which the cache reports separately. Both + * are installed by esp32s3_pmsirqinitialize(), in a protected build and in + * a kernel build alike. */ if (exccause == EXCCAUSE_LOAD_PROHIBITED || diff --git a/boards/xtensa/esp32s3/esp32s3-devkit/configs/kernel_oct/defconfig b/boards/xtensa/esp32s3/esp32s3-devkit/configs/kernel_oct/defconfig index 0e515654878..975ecb9fbf3 100644 --- a/boards/xtensa/esp32s3/esp32s3-devkit/configs/kernel_oct/defconfig +++ b/boards/xtensa/esp32s3/esp32s3-devkit/configs/kernel_oct/defconfig @@ -58,6 +58,10 @@ CONFIG_ESP32S3_SPIRAM_MODE_OCT=y CONFIG_ESP32S3_UART0=y CONFIG_ESP32S3_WCL=y CONFIG_EXAMPLES_PFFAULT=y +CONFIG_EXAMPLES_SANDBOX=y +CONFIG_EXAMPLES_SANDBOX_KERNEL_ADDR=0x3fc98000 +CONFIG_EXAMPLES_SANDBOX_PERIPH_ADDR=0x600c5000 +CONFIG_EXAMPLES_SANDBOX_UNMAPPED_ADDR=0x3d800000 CONFIG_FS_PROCFS=y CONFIG_FS_ROMFS=y CONFIG_HAVE_CXX=y