X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fsh64%2Fmm%2Ffault.c;h=e3e90bf3187c739c6c8cf41adfc3ad4a012d1e23;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=d1190b4158d8acbfbf340d2b56c2cc79865f6ab5;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c index d1190b415..e3e90bf31 100644 --- a/arch/sh64/mm/fault.c +++ b/arch/sh64/mm/fault.c @@ -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;