This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new f164840ff3f arch/armv7-a: End the process of a user fault, not the
system.
f164840ff3f is described below
commit f164840ff3f46d05baab144cf1ff5b63db6bfd02
Author: Marco Casaroli <[email protected]>
AuthorDate: Wed Oct 21 14:20:13 2026 +0200
arch/armv7-a: End the process of a user fault, not the system.
A data abort, a prefetch abort or an undefined instruction of user code
caused a panic of the whole system, also in the kernel build. As on
arm64 and RISC-V, it now ends only the task with SIGSEGV: the exception
returns to _exit() in SYS mode, on the kernel stack of the task if it
has one. A fault of the kernel, also of a system call, is fatal as
before.
Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <[email protected]>
---
arch/arm/src/armv7-a/CMakeLists.txt | 1 +
arch/arm/src/armv7-a/Make.defs | 2 +-
arch/arm/src/armv7-a/arm.h | 11 ++++
arch/arm/src/armv7-a/arm_dataabort.c | 5 +-
arch/arm/src/armv7-a/arm_prefetchabort.c | 5 +-
arch/arm/src/armv7-a/arm_undefinedinsn.c | 11 +++-
.../{arm_undefinedinsn.c => arm_userfault.c} | 67 ++++++++++++++++------
7 files changed, 79 insertions(+), 23 deletions(-)
diff --git a/arch/arm/src/armv7-a/CMakeLists.txt
b/arch/arm/src/armv7-a/CMakeLists.txt
index 27cfd8bbb82..029fdfecf9b 100644
--- a/arch/arm/src/armv7-a/CMakeLists.txt
+++ b/arch/arm/src/armv7-a/CMakeLists.txt
@@ -46,6 +46,7 @@ list(
arm_syscall.c
arm_tcbinfo.c
arm_undefinedinsn.c
+ arm_userfault.c
arm_perf.c
cp15_cacheops.c)
diff --git a/arch/arm/src/armv7-a/Make.defs b/arch/arm/src/armv7-a/Make.defs
index 07154bda712..4bcc3938d43 100644
--- a/arch/arm/src/armv7-a/Make.defs
+++ b/arch/arm/src/armv7-a/Make.defs
@@ -39,7 +39,7 @@ CMN_CSRCS += arm_cache.c arm_cpuinfo.c arm_dataabort.c
CMN_CSRCS += arm_doirq.c arm_gicv2.c arm_gicv2_dump.c
CMN_CSRCS += arm_initialstate.c arm_mmu.c arm_prefetchabort.c
CMN_CSRCS += arm_syscall.c arm_tcbinfo.c arm_undefinedinsn.c
-CMN_CSRCS += arm_perf.c cp15_cacheops.c
+CMN_CSRCS += arm_perf.c arm_userfault.c cp15_cacheops.c
ifeq ($(CONFIG_ENABLE_ALL_SIGNALS),y)
CMN_CSRCS += arm_schedulesigaction.c arm_sigdeliver.c
diff --git a/arch/arm/src/armv7-a/arm.h b/arch/arm/src/armv7-a/arm.h
index d9d78aec777..4593fab6463 100644
--- a/arch/arm/src/armv7-a/arm.h
+++ b/arch/arm/src/armv7-a/arm.h
@@ -111,6 +111,17 @@ extern "C"
void arm_data_initialize(void);
+/****************************************************************************
+ * Name: arm_fault_kill
+ *
+ * Description:
+ * End the task of a fault of user code with SIGSEGV. Return false if
+ * the fault is fatal. See arm_userfault.c.
+ *
+ ****************************************************************************/
+
+bool arm_fault_kill(uint32_t *regs);
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/arch/arm/src/armv7-a/arm_dataabort.c
b/arch/arm/src/armv7-a/arm_dataabort.c
index 5609b7bc7ee..cd707aa4373 100644
--- a/arch/arm/src/armv7-a/arm_dataabort.c
+++ b/arch/arm/src/armv7-a/arm_dataabort.c
@@ -26,6 +26,7 @@
#include <nuttx/config.h>
+#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
@@ -33,12 +34,12 @@
#include <nuttx/irq.h>
#include "mmu.h"
+#include "arm.h"
#include "sched/sched.h"
#include "arm_internal.h"
#ifdef CONFIG_LEGACY_PAGING
# include <nuttx/page.h>
-# include "arm.h"
#endif
/****************************************************************************
@@ -169,7 +170,7 @@ uint32_t *arm_dataabort(uint32_t *regs, uint32_t dfar,
uint32_t dfsr)
{
arm_dbgmonitor(0, (void *)dfar, regs);
}
- else
+ else if (!arm_fault_kill(regs))
{
PANIC_WITH_REGS("panic", regs);
}
diff --git a/arch/arm/src/armv7-a/arm_prefetchabort.c
b/arch/arm/src/armv7-a/arm_prefetchabort.c
index ab59f0fa069..e02a1fa1f4f 100644
--- a/arch/arm/src/armv7-a/arm_prefetchabort.c
+++ b/arch/arm/src/armv7-a/arm_prefetchabort.c
@@ -26,6 +26,7 @@
#include <nuttx/config.h>
+#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
@@ -36,6 +37,7 @@
#endif
#include "mmu.h"
+#include "arm.h"
#include "sched/sched.h"
#include "arm_internal.h"
@@ -91,6 +93,7 @@ uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar,
uint32_t ifsr)
*/
struct tcb_s *tcb = this_task();
+
tcb->xcp.far = regs[REG_R15];
/* Call pg_miss() to schedule the page fill. A consequences of this
@@ -140,7 +143,7 @@ uint32_t *arm_prefetchabort(uint32_t *regs, uint32_t ifar,
uint32_t ifsr)
{
arm_dbgmonitor(0, (void *)regs[REG_PC], regs);
}
- else
+ else if (!arm_fault_kill(regs))
{
PANIC_WITH_REGS("panic", regs);
}
diff --git a/arch/arm/src/armv7-a/arm_undefinedinsn.c
b/arch/arm/src/armv7-a/arm_undefinedinsn.c
index 7eb882448e0..cfd3d9d3b31 100644
--- a/arch/arm/src/armv7-a/arm_undefinedinsn.c
+++ b/arch/arm/src/armv7-a/arm_undefinedinsn.c
@@ -26,6 +26,7 @@
#include <nuttx/config.h>
+#include <stdbool.h>
#include <stdint.h>
#include <assert.h>
#include <nuttx/debug.h>
@@ -33,6 +34,7 @@
#include <nuttx/arch.h>
#include <sched/sched.h>
+#include "arm.h"
#include "arm_internal.h"
/****************************************************************************
@@ -60,6 +62,11 @@ uint32_t *arm_undefinedinsn(uint32_t *regs)
_alert("Undefined instruction at 0x%" PRIx32 "\n", regs[REG_PC]);
}
- PANIC_WITH_REGS("panic", regs);
- return regs; /* To keep the compiler happy */
+ if (!arm_fault_kill(regs))
+ {
+ PANIC_WITH_REGS("panic", regs);
+ }
+
+ up_set_interrupt_context(false);
+ return regs;
}
diff --git a/arch/arm/src/armv7-a/arm_undefinedinsn.c
b/arch/arm/src/armv7-a/arm_userfault.c
similarity index 53%
copy from arch/arm/src/armv7-a/arm_undefinedinsn.c
copy to arch/arm/src/armv7-a/arm_userfault.c
index 7eb882448e0..96a890a9b9b 100644
--- a/arch/arm/src/armv7-a/arm_undefinedinsn.c
+++ b/arch/arm/src/armv7-a/arm_userfault.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/arm/src/armv7-a/arm_undefinedinsn.c
+ * arch/arm/src/armv7-a/arm_userfault.c
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -26,13 +26,16 @@
#include <nuttx/config.h>
+#include <stdbool.h>
#include <stdint.h>
-#include <assert.h>
-#include <nuttx/debug.h>
+#include <signal.h>
+#include <unistd.h>
-#include <nuttx/arch.h>
-#include <sched/sched.h>
+#include <nuttx/debug.h>
+#include <nuttx/irq.h>
+#include "arm.h"
+#include "sched/sched.h"
#include "arm_internal.h"
/****************************************************************************
@@ -40,26 +43,56 @@
****************************************************************************/
/****************************************************************************
- * Name: arm_undefinedinsn
+ * Name: arm_fault_kill
+ *
+ * Description:
+ * A fault of user code ends the process (SIGSEGV), not the system: the
+ * abort returns to _exit() in SYS mode, on the kernel stack of the task
+ * if it has one. A fault of the kernel (also of a system call) is not
+ * handled here.
+ *
+ * Input Parameters:
+ * regs - The register state of the abort
+ *
+ * Returned Value:
+ * True if the task ends; false if the abort is fatal.
+ *
****************************************************************************/
-uint32_t *arm_undefinedinsn(uint32_t *regs)
+bool arm_fault_kill(uint32_t *regs)
{
struct tcb_s *tcb = this_task();
+ struct tcb_s *ptcb;
- tcb->xcp.regs = regs;
- up_set_interrupt_context(true);
-
- if (regs[REG_PC] >= (uint32_t)_stext && regs[REG_PC] < (uint32_t)_etext)
+ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_KERNEL ||
+ (tcb->flags & TCB_FLAG_SYSCALL) != 0 ||
+ (regs[REG_CPSR] & PSR_MODE_MASK) != PSR_MODE_USR)
{
- _alert("Undefined instruction at 0x%" PRIx32 ": 0x%" PRIx32 "\n",
- regs[REG_PC], *(uint32_t *)regs[REG_PC]);
+ return false;
}
- else
+
+ ptcb = nxsched_get_tcb(tcb->group->tg_pid);
+ _alert("Segmentation fault in %s (PID %d: %s)\n",
+ ptcb != NULL ? get_task_name(ptcb) : "<gone>",
+ tcb->pid, get_task_name(tcb));
+
+ tcb->flags |= TCB_FLAG_FORCED_CANCEL;
+
+ regs[REG_PC] = (uint32_t)_exit;
+ regs[REG_R0] = SIGSEGV;
+ regs[REG_CPSR] = PSR_MODE_SYS;
+#ifdef CONFIG_ARM_THUMB
+ regs[REG_CPSR] |= PSR_T_BIT;
+#endif
+
+#ifdef CONFIG_ARCH_KERNEL_STACK
+ /* The frames on the kernel stack are no longer needed */
+
+ if (tcb->xcp.kstack != NULL)
{
- _alert("Undefined instruction at 0x%" PRIx32 "\n", regs[REG_PC]);
+ regs[REG_SP] = (uint32_t)tcb->xcp.kstack + ARCH_KERNEL_STACKSIZE;
}
+#endif
- PANIC_WITH_REGS("panic", regs);
- return regs; /* To keep the compiler happy */
+ return true;
}