mirror of
https://github.com/apache/nuttx.git
synced 2026-10-04 12:48:09 +00:00
xtensa/esp32s3: Report an access through an invalid MMU entry.
The PMS grants and refuses physical addresses, so it never sees an access that no MMU entry translates. The cache answered such an access with zeros and raised nothing, and the task carried on with a value it never should have had. Enable EXTMEM_MMU_ENTRY_FAULT and route the Cache Invalid Access interrupt to the handler that already serves the PMS monitors. An unprivileged task that makes the access is terminated with SIGSEGV; a privileged one still panics. The latch is level triggered, so it is cleared with the others. Read the cause before the clear, so the log tells the two apart: a PMS violation is a refused translation, an MMU entry fault is an access that was never translated. Give the kernel_oct configuration the addresses that examples/sandbox needs to name its targets. Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
parent
df782bd1e5
commit
1b59698bde
3 changed files with 47 additions and 6 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 ||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue