tree 9924bec3f5646b6fe6eaa597ccd2f2dc6aa05673
parent baaa2c512dc1c47e3afeb9d558c5323c9240bd21
author [EMAIL PROTECTED] <[EMAIL PROTECTED]> Sun, 17 Apr 2005 05:23:55 -0700
committer Linus Torvalds <[EMAIL PROTECTED]> Sun, 17 Apr 2005 05:23:55 -0700
[PATCH] arm: fix SIGBUS handling
)
From: Russell King <[EMAIL PROTECTED]>
ARM wasn't raising a SIGBUS with a siginfo structure. Fix
__do_user_fault() to allow us to use it for SIGBUS conditions, and arrange
for the sigbus path to use this.
We need to prevent the siginfo code being called if we do not have a user
space context to call it, so consolidate the "user_mode()" tests.
Thanks to Ian Campbell who spotted this oversight.
Signed-off-by: Russell King <[EMAIL PROTECTED]>
Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
arm/mm/fault.c | 80 +++++++++++++++++++++++++--------------------------------
1 files changed, 36 insertions(+), 44 deletions(-)
Index: arch/arm/mm/fault.c
===================================================================
--- b4a3fcd63090a3c5a5ba7e13c1c01897318eb948/arch/arm/mm/fault.c (mode:100644
sha1:29be1c018949b6ef379216000dc45031c46521db)
+++ 9924bec3f5646b6fe6eaa597ccd2f2dc6aa05673/arch/arm/mm/fault.c (mode:100644
sha1:e25b4fd8412cb4f0c4f0c51c09ea30bc57a9c50d)
@@ -108,14 +108,15 @@
*/
static void
__do_user_fault(struct task_struct *tsk, unsigned long addr,
- unsigned int fsr, int code, struct pt_regs *regs)
+ unsigned int fsr, unsigned int sig, int code,
+ struct pt_regs *regs)
{
struct siginfo si;
#ifdef CONFIG_DEBUG_USER
if (user_debug & UDBG_SEGV) {
- printk(KERN_DEBUG "%s: unhandled page fault at 0x%08lx, code
0x%03x\n",
- tsk->comm, addr, fsr);
+ printk(KERN_DEBUG "%s: unhandled page fault (%d) at 0x%08lx,
code 0x%03x\n",
+ tsk->comm, sig, addr, fsr);
show_pte(tsk->mm, addr);
show_regs(regs);
}
@@ -124,11 +125,11 @@
tsk->thread.address = addr;
tsk->thread.error_code = fsr;
tsk->thread.trap_no = 14;
- si.si_signo = SIGSEGV;
+ si.si_signo = sig;
si.si_errno = 0;
si.si_code = code;
si.si_addr = (void __user *)addr;
- force_sig_info(SIGSEGV, &si, tsk);
+ force_sig_info(sig, &si, tsk);
}
void
@@ -140,7 +141,7 @@
* have no context to handle this fault with.
*/
if (user_mode(regs))
- __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
+ __do_user_fault(tsk, addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
else
__do_kernel_fault(mm, addr, fsr, regs);
}
@@ -201,10 +202,11 @@
goto out;
/*
- * If we are out of memory for pid1,
- * sleep for a while and retry
+ * If we are out of memory for pid1, sleep for a while and retry
*/
+ up_read(&mm->mmap_sem);
yield();
+ down_read(&mm->mmap_sem);
goto survive;
check_stack:
@@ -219,7 +221,7 @@
{
struct task_struct *tsk;
struct mm_struct *mm;
- int fault;
+ int fault, sig, code;
tsk = current;
mm = tsk->mm;
@@ -242,55 +244,45 @@
return 0;
/*
- * We had some memory, but were unable to
- * successfully fix up this page fault.
- */
- if (fault == 0)
- goto do_sigbus;
-
- /*
* If we are in kernel mode at this point, we
* have no context to handle this fault with.
*/
if (!user_mode(regs))
goto no_context;
- if (fault == VM_FAULT_OOM) {
+ switch (fault) {
+ case VM_FAULT_OOM:
/*
- * We ran out of memory, or some other thing happened to
- * us that made us unable to handle the page fault gracefully.
+ * We ran out of memory, or some other thing
+ * happened to us that made us unable to handle
+ * the page fault gracefully.
*/
printk("VM: killing process %s\n", tsk->comm);
do_exit(SIGKILL);
- } else
- __do_user_fault(tsk, addr, fsr, fault == VM_FAULT_BADACCESS ?
- SEGV_ACCERR : SEGV_MAPERR, regs);
- return 0;
+ return 0;
+ case 0:
+ /*
+ * We had some memory, but were unable to
+ * successfully fix up this page fault.
+ */
+ sig = SIGBUS;
+ code = BUS_ADRERR;
+ break;
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
-do_sigbus:
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- tsk->thread.address = addr;
- tsk->thread.error_code = fsr;
- tsk->thread.trap_no = 14;
- force_sig(SIGBUS, tsk);
-#ifdef CONFIG_DEBUG_USER
- if (user_debug & UDBG_BUS) {
- printk(KERN_DEBUG "%s: sigbus at 0x%08lx, pc=0x%08lx\n",
- current->comm, addr, instruction_pointer(regs));
+ default:
+ /*
+ * Something tried to access memory that
+ * isn't in our memory map..
+ */
+ sig = SIGSEGV;
+ code = fault == VM_FAULT_BADACCESS ?
+ SEGV_ACCERR : SEGV_MAPERR;
+ break;
}
-#endif
- /* Kernel mode? Handle exceptions or die */
- if (user_mode(regs))
- return 0;
+ __do_user_fault(tsk, addr, fsr, sig, code, regs);
+ return 0;
no_context:
__do_kernel_fault(mm, addr, fsr, regs);
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html