Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 83c54070 authored by Nick Piggin's avatar Nick Piggin Committed by Linus Torvalds
Browse files

mm: fault feedback #2



This patch completes Linus's wish that the fault return codes be made into
bit flags, which I agree makes everything nicer.  This requires requires
all handle_mm_fault callers to be modified (possibly the modifications
should go further and do things like fault accounting in handle_mm_fault --
however that would be for another patch).

[akpm@linux-foundation.org: fix alpha build]
[akpm@linux-foundation.org: fix s390 build]
[akpm@linux-foundation.org: fix sparc build]
[akpm@linux-foundation.org: fix sparc64 build]
[akpm@linux-foundation.org: fix ia64 build]
Signed-off-by: default avatarNick Piggin <npiggin@suse.de>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Ian Molton <spyro@f2s.com>
Cc: Bryan Wu <bryan.wu@analog.com>
Cc: Mikael Starvik <starvik@axis.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Hirokazu Takata <takata@linux-m32r.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Greg Ungerer <gerg@uclinux.org>
Cc: Matthew Wilcox <willy@debian.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Kazumoto Kojima <kkojima@rr.iij4u.or.jp>
Cc: Richard Curnow <rc@rc0.org.uk>
Cc: William Lee Irwin III <wli@holomorphy.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Miles Bader <uclinux-v850@lsi.nec.co.jp>
Cc: Chris Zankel <chris@zankel.net>
Acked-by: default avatarKyle McMartin <kyle@mcmartin.ca>
Acked-by: default avatarHaavard Skinnemoen <hskinnemoen@atmel.com>
Acked-by: default avatarRalf Baechle <ralf@linux-mips.org>
Acked-by: default avatarAndi Kleen <ak@muc.de>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
[ Still apparently needs some ARM and PPC loving - Linus ]
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d0217ac0
Loading
Loading
Loading
Loading
+9 −13
Original line number Diff line number Diff line
@@ -148,21 +148,17 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
	   the fault.  */
	fault = handle_mm_fault(mm, vma, address, cause > 0);
	up_read(&mm->mmap_sem);

	switch (fault) {
	      case VM_FAULT_MINOR:
		current->min_flt++;
		break;
	      case VM_FAULT_MAJOR:
		current->maj_flt++;
		break;
	      case VM_FAULT_SIGBUS:
		goto do_sigbus;
	      case VM_FAULT_OOM:
	if (unlikely(fault & VM_FAULT_ERROR)) {
		if (fault & VM_FAULT_OOM)
			goto out_of_memory;
	      default:
		else if (fault & VM_FAULT_SIGBUS)
			goto do_sigbus;
		BUG();
	}
	if (fault & VM_FAULT_MAJOR)
		current->maj_flt++;
	else
		current->min_flt++;
	return;

	/* Something tried to access memory that isn't in our memory map.
+16 −20
Original line number Diff line number Diff line
@@ -183,20 +183,20 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
	 */
survive:
	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, fsr & (1 << 11));

	/*
	 * Handle the "normal" cases first - successful and sigbus
	 */
	switch (fault) {
	case VM_FAULT_MAJOR:
		tsk->maj_flt++;
	if (unlikely(fault & VM_FAULT_ERROR)) {
		if (fault & VM_FAULT_OOM)
			goto out_of_memory;
		else if (fault & VM_FAULT_SIGBUS)
			return fault;
	case VM_FAULT_MINOR:
		BUG();
	}
	if (fault & VM_FAULT_MAJOR)
		tsk->maj_flt++;
	else
		tsk->min_flt++;
	case VM_FAULT_SIGBUS:
	return fault;
	}

out_of_memory:
	if (!is_init(tsk))
		goto out;

@@ -249,7 +249,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
	/*
	 * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
	 */
	if (fault >= VM_FAULT_MINOR)
	if (likely(!(fault & VM_FAULT_ERROR)))
		return 0;

	/*
@@ -259,8 +259,7 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
	if (!user_mode(regs))
		goto no_context;

	switch (fault) {
	case VM_FAULT_OOM:
	if (fault & VM_FAULT_OOM) {
		/*
		 * We ran out of memory, or some other thing
		 * happened to us that made us unable to handle
@@ -269,17 +268,15 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
		printk("VM: killing process %s\n", tsk->comm);
		do_exit(SIGKILL);
		return 0;

	case VM_FAULT_SIGBUS:
	}
	if (fault & VM_FAULT_SIGBUS) {
		/*
		 * We had some memory, but were unable to
		 * successfully fix up this page fault.
		 */
		sig = SIGBUS;
		code = BUS_ADRERR;
		break;

	default:
	} else {
		/*
		 * Something tried to access memory that
		 * isn't in our memory map..
@@ -287,7 +284,6 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
		sig = SIGSEGV;
		code = fault == VM_FAULT_BADACCESS ?
			SEGV_ACCERR : SEGV_MAPERR;
		break;
	}

	__do_user_fault(tsk, addr, fsr, sig, code, regs);
+14 −16
Original line number Diff line number Diff line
@@ -170,20 +170,20 @@ __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
	 */
survive:
	fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, DO_COW(fsr));

	/*
	 * Handle the "normal" cases first - successful and sigbus
	 */
	switch (fault) {
	case VM_FAULT_MAJOR:
		tsk->maj_flt++;
	if (unlikely(fault & VM_FAULT_ERROR)) {
		if (fault & VM_FAULT_OOM)
			goto out_of_memory;
		else if (fault & VM_FAULT_SIGBUS)
			return fault;
	case VM_FAULT_MINOR:
		BUG();
	}
	if (fault & VM_FAULT_MAJOR)
		tsk->maj_flt++;
	else
		tsk->min_flt++;
	case VM_FAULT_SIGBUS:
	return fault;
	}

out_of_memory:
	fault = -3; /* out of memory */
	if (!is_init(tsk))
		goto out;
@@ -225,13 +225,11 @@ int do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
	/*
	 * Handle the "normal" case first
	 */
	switch (fault) {
	case VM_FAULT_MINOR:
	case VM_FAULT_MAJOR:
	if (likely(!(fault & VM_FAULT_ERROR)))
		return 0;
	case VM_FAULT_SIGBUS:
	if (fault & VM_FAULT_SIGBUS)
		goto do_sigbus;
	}
	/* else VM_FAULT_OOM */

	/*
	 * If we are in kernel mode at this point, we
+11 −12
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
	int writeaccess;
	long signr;
	int code;
	int fault;

	if (notify_page_fault(regs, ecr))
		return;
@@ -132,20 +133,18 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
	 * fault.
	 */
survive:
	switch (handle_mm_fault(mm, vma, address, writeaccess)) {
	case VM_FAULT_MINOR:
		tsk->min_flt++;
		break;
	case VM_FAULT_MAJOR:
		tsk->maj_flt++;
		break;
	case VM_FAULT_SIGBUS:
		goto do_sigbus;
	case VM_FAULT_OOM:
	fault = handle_mm_fault(mm, vma, address, writeaccess);
	if (unlikely(fault & VM_FAULT_ERROR)) {
		if (fault & VM_FAULT_OOM)
			goto out_of_memory;
	default:
		else if (fault & VM_FAULT_SIGBUS)
			goto do_sigbus;
		BUG();
	}
	if (fault & VM_FAULT_MAJOR)
		tsk->maj_flt++;
	else
		tsk->min_flt++;

	up_read(&mm->mmap_sem);
	return;
+12 −11
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
	struct mm_struct *mm;
	struct vm_area_struct * vma;
	siginfo_t info;
	int fault;

        D(printk("Page fault for %lX on %X at %lX, prot %d write %d\n",
                 address, smp_processor_id(), instruction_pointer(regs),
@@ -283,18 +284,18 @@ do_page_fault(unsigned long address, struct pt_regs *regs,
	 * the fault.
	 */

	switch (handle_mm_fault(mm, vma, address, writeaccess & 1)) {
	case VM_FAULT_MINOR:
		tsk->min_flt++;
		break;
	case VM_FAULT_MAJOR:
		tsk->maj_flt++;
		break;
	case VM_FAULT_SIGBUS:
		goto do_sigbus;
	default:
	fault = handle_mm_fault(mm, vma, address, writeaccess & 1);
	if (unlikely(fault & VM_FAULT_ERROR)) {
		if (fault & VM_FAULT_OOM)
			goto out_of_memory;
		else if (fault & VM_FAULT_SIGBUS)
			goto do_sigbus;
		BUG();
	}
	if (fault & VM_FAULT_MAJOR)
		tsk->maj_flt++;
	else
		tsk->min_flt++;

	up_read(&mm->mmap_sem);
	return;
Loading