}
  #endif
  
+ static noinline void no_context(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address)
+ {
+       struct task_struct *tsk = current;
++      unsigned long *stackend;
++
+ #ifdef CONFIG_X86_64
+       unsigned long flags;
+       int sig;
+ #endif
+ 
+       /* Are we prepared to handle this kernel fault?  */
+       if (fixup_exception(regs))
+               return;
+ 
+       /*
+        * X86_32
+        * Valid to do another page fault here, because if this fault
+        * had been triggered by is_prefetch fixup_exception would have
+        * handled it.
+        *
+        * X86_64
+        * Hall of shame of CPU/BIOS bugs.
+        */
+       if (is_prefetch(regs, error_code, address))
+               return;
+ 
+       if (is_errata93(regs, address))
+               return;
+ 
+       /*
+        * Oops. The kernel tried to access some bad page. We'll have to
+        * terminate things with extreme prejudice.
+        */
+ #ifdef CONFIG_X86_32
+       bust_spinlocks(1);
+ #else
+       flags = oops_begin();
+ #endif
+ 
+       show_fault_oops(regs, error_code, address);
+ 
++      stackend = end_of_stack(tsk);
++      if (*stackend != STACK_END_MAGIC)
++              printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
++
+       tsk->thread.cr2 = address;
+       tsk->thread.trap_no = 14;
+       tsk->thread.error_code = error_code;
+ 
+ #ifdef CONFIG_X86_32
+       die("Oops", regs, error_code);
+       bust_spinlocks(0);
+       do_exit(SIGKILL);
+ #else
+       sig = SIGKILL;
+       if (__die("Oops", regs, error_code))
+               sig = 0;
+       /* Executive summary in case the body of the oops scrolled away */
+       printk(KERN_EMERG "CR2: %016lx\n", address);
+       oops_end(flags, regs, sig);
+ #endif
+ }
+ 
+ static void __bad_area_nosemaphore(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address,
+                       int si_code)
+ {
+       struct task_struct *tsk = current;
+ 
+       /* User mode accesses just cause a SIGSEGV */
+       if (error_code & PF_USER) {
+               /*
+                * It's possible to have interrupts off here.
+                */
+               local_irq_enable();
+ 
+               /*
+                * Valid to do another page fault here because this one came
+                * from user space.
+                */
+               if (is_prefetch(regs, error_code, address))
+                       return;
+ 
+               if (is_errata100(regs, address))
+                       return;
+ 
+               if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
+                   printk_ratelimit()) {
+                       printk(
+                       "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+                       task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+                       tsk->comm, task_pid_nr(tsk), address,
+                       (void *) regs->ip, (void *) regs->sp, error_code);
+                       print_vma_addr(" in ", regs->ip);
+                       printk("\n");
+               }
+ 
+               tsk->thread.cr2 = address;
+               /* Kernel addresses are always protection faults */
+               tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+               tsk->thread.trap_no = 14;
+               force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+               return;
+       }
+ 
+       if (is_f00f_bug(regs, address))
+               return;
+ 
+       no_context(regs, error_code, address);
+ }
+ 
+ static noinline void bad_area_nosemaphore(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address)
+ {
+       __bad_area_nosemaphore(regs, error_code, address, SEGV_MAPERR);
+ }
+ 
+ static void __bad_area(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address,
+                       int si_code)
+ {
+       struct mm_struct *mm = current->mm;
+ 
+       /*
+        * Something tried to access memory that isn't in our memory map..
+        * Fix it, but check if it's kernel or user first..
+        */
+       up_read(&mm->mmap_sem);
+ 
+       __bad_area_nosemaphore(regs, error_code, address, si_code);
+ }
+ 
+ static noinline void bad_area(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address)
+ {
+       __bad_area(regs, error_code, address, SEGV_MAPERR);
+ }
+ 
+ static noinline void bad_area_access_error(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address)
+ {
+       __bad_area(regs, error_code, address, SEGV_ACCERR);
+ }
+ 
+ /* TODO: fixup for "mm-invoke-oom-killer-from-page-fault.patch" */
+ static void out_of_memory(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address)
+ {
+       /*
+        * We ran out of memory, call the OOM killer, and return the userspace
+        * (which will retry the fault, or kill us if we got oom-killed).
+        */
+       up_read(¤t->mm->mmap_sem);
+       pagefault_out_of_memory();
+ }
+ 
+ static void do_sigbus(struct pt_regs *regs,
+                       unsigned long error_code, unsigned long address)
+ {
+       struct task_struct *tsk = current;
+       struct mm_struct *mm = tsk->mm;
+ 
+       up_read(&mm->mmap_sem);
+ 
+       /* Kernel mode? Handle exceptions or die */
+       if (!(error_code & PF_USER))
+               no_context(regs, error_code, address);
+ #ifdef CONFIG_X86_32
+       /* User space => ok to do another page fault */
+       if (is_prefetch(regs, error_code, address))
+               return;
+ #endif
+       tsk->thread.cr2 = address;
+       tsk->thread.error_code = error_code;
+       tsk->thread.trap_no = 14;
+       force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
+ }
+ 
+ static noinline void mm_fault_error(struct pt_regs *regs,
+               unsigned long error_code, unsigned long address, unsigned int fault)
+ {
+       if (fault & VM_FAULT_OOM)
+               out_of_memory(regs, error_code, address);
+       else if (fault & VM_FAULT_SIGBUS)
+               do_sigbus(regs, error_code, address);
+       else
+               BUG();
+ }
+ 
  static int spurious_fault_check(unsigned long error_code, pte_t *pte)
  {
        if ((error_code & PF_WRITE) && !pte_write(*pte))