Merge branch 'x86/mm' into core/percpu
authorIngo Molnar <mingo@elte.hu>
Wed, 21 Jan 2009 09:39:51 +0000 (10:39 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 21 Jan 2009 09:39:51 +0000 (10:39 +0100)
Conflicts:
arch/x86/mm/fault.c

1  2 
arch/powerpc/kernel/vmlinux.lds.S
arch/powerpc/sysdev/mpic.c
arch/x86/mm/fault.c
arch/x86/mm/pat.c
arch/x86/mm/tlb.c
include/linux/magic.h
kernel/exit.c
kernel/fork.c
kernel/sched.c

Simple merge
Simple merge
@@@ -430,6 -429,190 +430,196 @@@ static noinline void pgtable_bad(struc
  }
  #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(&current->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))
Simple merge
@@@ -42,10 -46,10 +42,10 @@@ union smp_flush_state 
                struct mm_struct *flush_mm;
                unsigned long flush_va;
                spinlock_t tlbstate_lock;
 +              DECLARE_BITMAP(flush_cpumask, NR_CPUS);
        };
-       char pad[SMP_CACHE_BYTES];
- } ____cacheline_aligned;
+       char pad[CONFIG_X86_INTERNODE_CACHE_BYTES];
+ } ____cacheline_internodealigned_in_smp;
  
  /* State is put into the per CPU data section, but padded
     to a full cache line because other CPUs can access it and we don't
@@@ -135,9 -129,9 +135,9 @@@ void smp_invalidate_interrupt(struct pt
         * Use that to determine where the sender put the data.
         */
        sender = ~regs->orig_ax - INVALIDATE_TLB_VECTOR_START;
-       f = &per_cpu(flush_state, sender);
+       f = &flush_state[sender];
  
 -      if (!cpu_isset(cpu, f->flush_cpumask))
 +      if (!cpumask_test_cpu(cpu, to_cpumask(f->flush_cpumask)))
                goto out;
                /*
                 * This was a BUG() but until someone can quote me the
Simple merge
diff --cc kernel/exit.c
Simple merge
diff --cc kernel/fork.c
Simple merge
diff --cc kernel/sched.c
Simple merge