Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 23:30:45 +0000 (16:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 1 Aug 2012 23:30:45 +0000 (16:30 -0700)
Pull ARM fixes from Russell King:
 "This fixes various issues found during July"

* 'fixes' of git://git.linaro.org/people/rmk/linux-arm:
  ARM: 7479/1: mm: avoid NULL dereference when flushing gate_vma with VIVT caches
  ARM: Fix undefined instruction exception handling
  ARM: 7480/1: only call smp_send_stop() on SMP
  ARM: 7478/1: errata: extend workaround for erratum #720789
  ARM: 7477/1: vfp: Always save VFP state in vfp_pm_suspend on UP
  ARM: 7476/1: vfp: only clear vfp state for current cpu in vfp_pm_suspend
  ARM: 7468/1: ftrace: Trace function entry before updating index
  ARM: 7467/1: mutex: use generic xchg-based implementation for ARMv6+
  ARM: 7466/1: disable interrupt before spinning endlessly
  ARM: 7465/1: Handle >4GB memory sizes in device tree and mem=size@start option

1  2 
arch/arm/kernel/traps.c
arch/arm/vfp/vfphw.S

diff --combined arch/arm/kernel/traps.c
index 8b97d739b17b1040f4f3e4bb7fe069d84808fa72,c7cae6b9a4d913f4940dfaa186aa56d3eb5b9450..7978d4f0f3aef59ee177a0525db44c6819110ed6
@@@ -233,9 -233,9 +233,9 @@@ void show_stack(struct task_struct *tsk
  #define S_ISA " ARM"
  #endif
  
 -static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
 +static int __die(const char *str, int err, struct pt_regs *regs)
  {
 -      struct task_struct *tsk = thread->task;
 +      struct task_struct *tsk = current;
        static int die_counter;
        int ret;
  
        /* trap and error numbers are mostly meaningless on ARM */
        ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
        if (ret == NOTIFY_STOP)
 -              return ret;
 +              return 1;
  
        print_modules();
        __show_regs(regs);
        printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
 -              TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
 +              TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk));
  
        if (!user_mode(regs) || in_interrupt()) {
                dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp,
                dump_instr(KERN_EMERG, regs);
        }
  
 -      return ret;
 +      return 0;
  }
  
 -static DEFINE_RAW_SPINLOCK(die_lock);
 +static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 +static int die_owner = -1;
 +static unsigned int die_nest_count;
  
 -/*
 - * This function is protected against re-entrancy.
 - */
 -void die(const char *str, struct pt_regs *regs, int err)
 +static unsigned long oops_begin(void)
  {
 -      struct thread_info *thread = current_thread_info();
 -      int ret;
 -      enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE;
 +      int cpu;
 +      unsigned long flags;
  
        oops_enter();
  
 -      raw_spin_lock_irq(&die_lock);
 +      /* racy, but better than risking deadlock. */
 +      raw_local_irq_save(flags);
 +      cpu = smp_processor_id();
 +      if (!arch_spin_trylock(&die_lock)) {
 +              if (cpu == die_owner)
 +                      /* nested oops. should stop eventually */;
 +              else
 +                      arch_spin_lock(&die_lock);
 +      }
 +      die_nest_count++;
 +      die_owner = cpu;
        console_verbose();
        bust_spinlocks(1);
 -      if (!user_mode(regs))
 -              bug_type = report_bug(regs->ARM_pc, regs);
 -      if (bug_type != BUG_TRAP_TYPE_NONE)
 -              str = "Oops - BUG";
 -      ret = __die(str, err, thread, regs);
 +      return flags;
 +}
  
 -      if (regs && kexec_should_crash(thread->task))
 +static void oops_end(unsigned long flags, struct pt_regs *regs, int signr)
 +{
 +      if (regs && kexec_should_crash(current))
                crash_kexec(regs);
  
        bust_spinlocks(0);
 +      die_owner = -1;
        add_taint(TAINT_DIE);
 -      raw_spin_unlock_irq(&die_lock);
 +      die_nest_count--;
 +      if (!die_nest_count)
 +              /* Nest count reaches zero, release the lock. */
 +              arch_spin_unlock(&die_lock);
 +      raw_local_irq_restore(flags);
        oops_exit();
  
        if (in_interrupt())
                panic("Fatal exception in interrupt");
        if (panic_on_oops)
                panic("Fatal exception");
 -      if (ret != NOTIFY_STOP)
 -              do_exit(SIGSEGV);
 +      if (signr)
 +              do_exit(signr);
 +}
 +
 +/*
 + * This function is protected against re-entrancy.
 + */
 +void die(const char *str, struct pt_regs *regs, int err)
 +{
 +      enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE;
 +      unsigned long flags = oops_begin();
 +      int sig = SIGSEGV;
 +
 +      if (!user_mode(regs))
 +              bug_type = report_bug(regs->ARM_pc, regs);
 +      if (bug_type != BUG_TRAP_TYPE_NONE)
 +              str = "Oops - BUG";
 +
 +      if (__die(str, err, regs))
 +              sig = 0;
 +
 +      oops_end(flags, regs, sig);
  }
  
  void arm_notify_die(const char *str, struct pt_regs *regs,
@@@ -402,18 -370,10 +402,10 @@@ static int call_undef_hook(struct pt_re
  
  asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
  {
-       unsigned int correction = thumb_mode(regs) ? 2 : 4;
        unsigned int instr;
        siginfo_t info;
        void __user *pc;
  
-       /*
-        * According to the ARM ARM, PC is 2 or 4 bytes ahead,
-        * depending whether we're in Thumb mode or not.
-        * Correct this offset.
-        */
-       regs->ARM_pc -= correction;
        pc = (void __user *)instruction_pointer(regs);
  
        if (processor_mode(regs) == SVC_MODE) {
diff --combined arch/arm/vfp/vfphw.S
index d50f0e486cf2b322b6e8eff1baa7c73272e66c70,3a0efaad6090c4ff0f5413faa7501fbb1853c5ce..ea0349f6358658065b52aa1473e877ee4fa8f5ba
@@@ -16,7 -16,6 +16,7 @@@
   */
  #include <asm/thread_info.h>
  #include <asm/vfpmacros.h>
 +#include <linux/kern_levels.h>
  #include "../kernel/entry-header.S"
  
        .macro  DBGSTR, str
@@@ -25,7 -24,7 +25,7 @@@
        add     r0, pc, #4
        bl      printk
        b       1f
 -      .asciz  "<7>VFP: \str\n"
 +      .asciz  KERN_DEBUG "VFP: \str\n"
        .balign 4
  1:    ldmfd   sp!, {r0-r3, ip, lr}
  #endif
@@@ -38,7 -37,7 +38,7 @@@
        add     r0, pc, #4
        bl      printk
        b       1f
 -      .asciz  "<7>VFP: \str\n"
 +      .asciz  KERN_DEBUG "VFP: \str\n"
        .balign 4
  1:    ldmfd   sp!, {r0-r3, ip, lr}
  #endif
@@@ -53,7 -52,7 +53,7 @@@
        add     r0, pc, #4
        bl      printk
        b       1f
 -      .asciz  "<7>VFP: \str\n"
 +      .asciz  KERN_DEBUG "VFP: \str\n"
        .balign 4
  1:    ldmfd   sp!, {r0-r3, ip, lr}
  #endif
  
  @ VFP hardware support entry point.
  @
- @  r0  = faulted instruction
- @  r2  = faulted PC+4
- @  r9  = successful return
+ @  r0  = instruction opcode (32-bit ARM or two 16-bit Thumb)
+ @  r2  = PC value to resume execution after successful emulation
+ @  r9  = normal "successful" return address
  @  r10 = vfp_state union
  @  r11 = CPU number
- @  lr  = failure return
+ @  lr  = unrecognised instruction return address
+ @  IRQs enabled.
  ENTRY(vfp_support_entry)
        DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10
  
@@@ -162,9 -161,12 +162,12 @@@ vfp_hw_state_valid
                                        @ exception before retrying branch
                                        @ out before setting an FPEXC that
                                        @ stops us reading stuff
-       VFPFMXR FPEXC, r1               @ restore FPEXC last
-       sub     r2, r2, #4
-       str     r2, [sp, #S_PC]         @ retry the instruction
+       VFPFMXR FPEXC, r1               @ Restore FPEXC last
+       sub     r2, r2, #4              @ Retry current instruction - if Thumb
+       str     r2, [sp, #S_PC]         @ mode it's two 16-bit instructions,
+                                       @ else it's one 32-bit instruction, so
+                                       @ always subtract 4 from the following
+                                       @ instruction address.
  #ifdef CONFIG_PREEMPT
        get_thread_info r10
        ldr     r4, [r10, #TI_PREEMPT]  @ get preempt count