aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/mm/fault.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 16:07:55 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 16:07:55 -0400
commitb278240839e20fa9384ea430df463b367b90e04e (patch)
treef99f0c8cdd4cc7f177cd75440e6bd181cded7fb3 /arch/i386/mm/fault.c
parentdd77a4ee0f3981693d4229aa1d57cea9e526ff47 (diff)
parent3f75f42d7733e73aca5c78326489efd4189e0111 (diff)
Merge branch 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6
* 'for-linus' of git://one.firstfloor.org/home/andi/git/linux-2.6: (225 commits) [PATCH] Don't set calgary iommu as default y [PATCH] i386/x86-64: New Intel feature flags [PATCH] x86: Add a cumulative thermal throttle event counter. [PATCH] i386: Make the jiffies compares use the 64bit safe macros. [PATCH] x86: Refactor thermal throttle processing [PATCH] Add 64bit jiffies compares (for use with get_jiffies_64) [PATCH] Fix unwinder warning in traps.c [PATCH] x86: Allow disabling early pci scans with pci=noearly or disallowing conf1 [PATCH] x86: Move direct PCI scanning functions out of line [PATCH] i386/x86-64: Make all early PCI scans dependent on CONFIG_PCI [PATCH] Don't leak NT bit into next task [PATCH] i386/x86-64: Work around gcc bug with noreturn functions in unwinder [PATCH] Fix some broken white space in ia32_signal.c [PATCH] Initialize argument registers for 32bit signal handlers. [PATCH] Remove all traces of signal number conversion [PATCH] Don't synchronize time reading on single core AMD systems [PATCH] Remove outdated comment in x86-64 mmconfig code [PATCH] Use string instructions for Core2 copy/clear [PATCH] x86: - restore i8259A eoi status on resume [PATCH] i386: Split multi-line printk in oops output. ...
Diffstat (limited to 'arch/i386/mm/fault.c')
-rw-r--r--arch/i386/mm/fault.c25
1 files changed, 8 insertions, 17 deletions
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index f7279468323a..5e17a3f43b41 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -27,21 +27,24 @@
27#include <asm/uaccess.h> 27#include <asm/uaccess.h>
28#include <asm/desc.h> 28#include <asm/desc.h>
29#include <asm/kdebug.h> 29#include <asm/kdebug.h>
30#include <asm/segment.h>
30 31
31extern void die(const char *,struct pt_regs *,long); 32extern void die(const char *,struct pt_regs *,long);
32 33
33#ifdef CONFIG_KPROBES 34static ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain);
34ATOMIC_NOTIFIER_HEAD(notify_page_fault_chain); 35
35int register_page_fault_notifier(struct notifier_block *nb) 36int register_page_fault_notifier(struct notifier_block *nb)
36{ 37{
37 vmalloc_sync_all(); 38 vmalloc_sync_all();
38 return atomic_notifier_chain_register(&notify_page_fault_chain, nb); 39 return atomic_notifier_chain_register(&notify_page_fault_chain, nb);
39} 40}
41EXPORT_SYMBOL_GPL(register_page_fault_notifier);
40 42
41int unregister_page_fault_notifier(struct notifier_block *nb) 43int unregister_page_fault_notifier(struct notifier_block *nb)
42{ 44{
43 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb); 45 return atomic_notifier_chain_unregister(&notify_page_fault_chain, nb);
44} 46}
47EXPORT_SYMBOL_GPL(unregister_page_fault_notifier);
45 48
46static inline int notify_page_fault(enum die_val val, const char *str, 49static inline int notify_page_fault(enum die_val val, const char *str,
47 struct pt_regs *regs, long err, int trap, int sig) 50 struct pt_regs *regs, long err, int trap, int sig)
@@ -55,14 +58,6 @@ static inline int notify_page_fault(enum die_val val, const char *str,
55 }; 58 };
56 return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args); 59 return atomic_notifier_call_chain(&notify_page_fault_chain, val, &args);
57} 60}
58#else
59static inline int notify_page_fault(enum die_val val, const char *str,
60 struct pt_regs *regs, long err, int trap, int sig)
61{
62 return NOTIFY_DONE;
63}
64#endif
65
66 61
67/* 62/*
68 * Unlock any spinlocks which will prevent us from getting the 63 * Unlock any spinlocks which will prevent us from getting the
@@ -119,10 +114,10 @@ static inline unsigned long get_segment_eip(struct pt_regs *regs,
119 } 114 }
120 115
121 /* The standard kernel/user address space limit. */ 116 /* The standard kernel/user address space limit. */
122 *eip_limit = (seg & 3) ? USER_DS.seg : KERNEL_DS.seg; 117 *eip_limit = user_mode(regs) ? USER_DS.seg : KERNEL_DS.seg;
123 118
124 /* By far the most common cases. */ 119 /* By far the most common cases. */
125 if (likely(seg == __USER_CS || seg == __KERNEL_CS)) 120 if (likely(SEGMENT_IS_FLAT_CODE(seg)))
126 return eip; 121 return eip;
127 122
128 /* Check the segment exists, is within the current LDT/GDT size, 123 /* Check the segment exists, is within the current LDT/GDT size,
@@ -436,11 +431,7 @@ good_area:
436 write = 0; 431 write = 0;
437 switch (error_code & 3) { 432 switch (error_code & 3) {
438 default: /* 3: write, present */ 433 default: /* 3: write, present */
439#ifdef TEST_VERIFY_AREA 434 /* fall through */
440 if (regs->cs == KERNEL_CS)
441 printk("WP fault at %08lx\n", regs->eip);
442#endif
443 /* fall through */
444 case 2: /* write, not present */ 435 case 2: /* write, not present */
445 if (!(vma->vm_flags & VM_WRITE)) 436 if (!(vma->vm_flags & VM_WRITE))
446 goto bad_area; 437 goto bad_area;