fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / sh64 / mm / fault.c
index d1190b4..e3e90bf 100644 (file)
@@ -82,7 +82,7 @@ static inline void print_vma(struct vm_area_struct *vma)
 
 static inline void print_task(struct task_struct *tsk)
 {
-       printk("Task pid %d\n", tsk->pid);
+       printk("Task pid %d:#%u\n", tsk->pid, tsk->xid);
 }
 
 static pte_t *lookup_pte(struct mm_struct *mm, unsigned long address)
@@ -148,13 +148,13 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
        mm = tsk->mm;
 
        /* Not an IO address, so reenable interrupts */
-       sti();
+       local_irq_enable();
 
        /*
         * If we're in an interrupt or have no user
         * context, we must not take the fault..
         */
-       if (in_interrupt() || !mm)
+       if (in_atomic() || !mm)
                goto no_context;
 
        /* TLB misses upon some cache flushes get done under cli() */
@@ -203,17 +203,17 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess,
  * we can handle it..
  */
 good_area:
-       if (writeaccess) {
-               if (!(vma->vm_flags & VM_WRITE))
-                       goto bad_area;
-       } else {
-               if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
-                       goto bad_area;
-       }
-
        if (textaccess) {
                if (!(vma->vm_flags & VM_EXEC))
                        goto bad_area;
+       } else {
+               if (writeaccess) {
+                       if (!(vma->vm_flags & VM_WRITE))
+                               goto bad_area;
+               } else {
+                       if (!(vma->vm_flags & VM_READ))
+                               goto bad_area;
+               }
        }
 
        /*
@@ -223,13 +223,13 @@ good_area:
         */
 survive:
        switch (handle_mm_fault(mm, vma, address, writeaccess)) {
-       case 1:
+       case VM_FAULT_MINOR:
                tsk->min_flt++;
                break;
-       case 2:
+       case VM_FAULT_MAJOR:
                tsk->maj_flt++;
                break;
-       case 0:
+       case VM_FAULT_SIGBUS:
                goto do_sigbus;
        default:
                goto out_of_memory;
@@ -264,17 +264,28 @@ bad_area:
        up_read(&mm->mmap_sem);
 
        if (user_mode(regs)) {
-               printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx opcode=%08lx\n",
-                       address, current->pid, current->comm,
-                       (unsigned long) regs->pc,
-                       *(unsigned long *)(u32)(regs->pc & ~3));
-               show_regs(regs);
-               if (tsk->pid == 1) {
+               static int count=0;
+               siginfo_t info;
+               if (count < 4) {
+                       /* This is really to help debug faults when starting
+                        * usermode, so only need a few */
+                       count++;
+                       printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx\n",
+                               address, current->pid, current->comm,
+                               (unsigned long) regs->pc);
+#if 0
+                       show_regs(regs);
+#endif
+               }
+               if (is_init(tsk)) {
                        panic("INIT had user mode bad_area\n");
                }
                tsk->thread.address = address;
                tsk->thread.error_code = writeaccess;
-               force_sig(SIGSEGV, tsk);
+               info.si_signo = SIGSEGV;
+               info.si_errno = 0;
+               info.si_addr = (void *) address;
+               force_sig_info(SIGSEGV, &info, tsk);
                return;
        }
 
@@ -308,19 +319,20 @@ no_context:
  * us unable to handle the page fault gracefully.
  */
 out_of_memory:
-       if (current->pid == 1) {
+       if (is_init(current)) {
                panic("INIT out of memory\n");
                yield();
                goto survive;
        }
        printk("fault:Out of memory\n");
        up_read(&mm->mmap_sem);
-       if (current->pid == 1) {
+       if (is_init(current)) {
                yield();
                down_read(&mm->mmap_sem);
                goto survive;
        }
-       printk("VM: killing process %s\n", tsk->comm);
+       printk("VM: killing process %s(%d:#%u)\n",
+               tsk->comm, tsk->pid, tsk->xid);
        if (user_mode(regs))
                do_exit(SIGKILL);
        goto no_context;