]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'restart-handler-for-v3.18' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Oct 2014 20:38:02 +0000 (16:38 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Oct 2014 20:38:02 +0000 (16:38 -0400)
Pull restart handler infrastructure from Guenter Roeck:
 "This series was supposed to be pulled through various trees using it,
  and I did not plan to send a separate pull request.  As it turns out,
  the pinctrl tree did not merge with it, is now upstream, and uses it,
  meaning there are now build failures.

  Please pull this series directly to fix those build failures"

* tag 'restart-handler-for-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging:
  arm/arm64: unexport restart handlers
  watchdog: sunxi: register restart handler with kernel restart handler
  watchdog: alim7101: register restart handler with kernel restart handler
  watchdog: moxart: register restart handler with kernel restart handler
  arm: support restart through restart handler call chain
  arm64: support restart through restart handler call chain
  power/restart: call machine_restart instead of arm_pm_restart
  kernel: add support for kernel restart handler call chain

1  2 
arch/arm/kernel/process.c
arch/arm64/kernel/process.c

index a0a691d1cbeee0e675e3d18674b15fc1f1224342,250b6f652afcdb8966a89f8285500bf1b0cc49bd..fe972a2f3df398f9eddbf02b25d4edff987b442d
@@@ -114,18 -114,13 +114,13 @@@ void soft_restart(unsigned long addr
        BUG();
  }
  
- static void null_restart(enum reboot_mode reboot_mode, const char *cmd)
- {
- }
  /*
   * Function pointers to optional machine specific functions
   */
  void (*pm_power_off)(void);
  EXPORT_SYMBOL(pm_power_off);
  
- void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd) = null_restart;
- EXPORT_SYMBOL_GPL(arm_pm_restart);
+ void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
  
  /*
   * This is our default idle handler.
@@@ -230,7 -225,10 +225,10 @@@ void machine_restart(char *cmd
        local_irq_disable();
        smp_send_stop();
  
-       arm_pm_restart(reboot_mode, cmd);
+       if (arm_pm_restart)
+               arm_pm_restart(reboot_mode, cmd);
+       else
+               do_kernel_restart(cmd);
  
        /* Give a grace period for failure to restart of 1s */
        mdelay(1000);
@@@ -306,6 -304,7 +304,6 @@@ void __show_regs(struct pt_regs *regs
  
  void show_regs(struct pt_regs * regs)
  {
 -      printk("\n");
        __show_regs(regs);
        dump_stack();
  }
@@@ -333,8 -332,6 +331,8 @@@ void flush_thread(void
        memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
        memset(&thread->fpstate, 0, sizeof(union fp_state));
  
 +      flush_tls();
 +
        thread_notify(THREAD_NOTIFY_FLUSH, thread);
  }
  
@@@ -473,57 -470,19 +471,57 @@@ int in_gate_area_no_mm(unsigned long ad
  
  const char *arch_vma_name(struct vm_area_struct *vma)
  {
 -      return is_gate_vma(vma) ? "[vectors]" :
 -              (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage) ?
 -               "[sigpage]" : NULL;
 +      return is_gate_vma(vma) ? "[vectors]" : NULL;
 +}
 +
 +/* If possible, provide a placement hint at a random offset from the
 + * stack for the signal page.
 + */
 +static unsigned long sigpage_addr(const struct mm_struct *mm,
 +                                unsigned int npages)
 +{
 +      unsigned long offset;
 +      unsigned long first;
 +      unsigned long last;
 +      unsigned long addr;
 +      unsigned int slots;
 +
 +      first = PAGE_ALIGN(mm->start_stack);
 +
 +      last = TASK_SIZE - (npages << PAGE_SHIFT);
 +
 +      /* No room after stack? */
 +      if (first > last)
 +              return 0;
 +
 +      /* Just enough room? */
 +      if (first == last)
 +              return first;
 +
 +      slots = ((last - first) >> PAGE_SHIFT) + 1;
 +
 +      offset = get_random_int() % slots;
 +
 +      addr = first + (offset << PAGE_SHIFT);
 +
 +      return addr;
  }
  
  static struct page *signal_page;
  extern struct page *get_signal_page(void);
  
 +static const struct vm_special_mapping sigpage_mapping = {
 +      .name = "[sigpage]",
 +      .pages = &signal_page,
 +};
 +
  int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
  {
        struct mm_struct *mm = current->mm;
 +      struct vm_area_struct *vma;
        unsigned long addr;
 -      int ret;
 +      unsigned long hint;
 +      int ret = 0;
  
        if (!signal_page)
                signal_page = get_signal_page();
                return -ENOMEM;
  
        down_write(&mm->mmap_sem);
 -      addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
 +      hint = sigpage_addr(mm, 1);
 +      addr = get_unmapped_area(NULL, hint, PAGE_SIZE, 0, 0);
        if (IS_ERR_VALUE(addr)) {
                ret = addr;
                goto up_fail;
        }
  
 -      ret = install_special_mapping(mm, addr, PAGE_SIZE,
 +      vma = _install_special_mapping(mm, addr, PAGE_SIZE,
                VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
 -              &signal_page);
 +              &sigpage_mapping);
 +
 +      if (IS_ERR(vma)) {
 +              ret = PTR_ERR(vma);
 +              goto up_fail;
 +      }
  
 -      if (ret == 0)
 -              mm->context.sigpage = addr;
 +      mm->context.sigpage = addr;
  
   up_fail:
        up_write(&mm->mmap_sem);
index 89f41f7d27dd2bc54da37bd850f5437f86b19630,398ab05081b437438d41fabf6691aee5c76e1361..c3065dbc4fa269bafbb0b93f5a458d0534ae2bc5
@@@ -57,10 -57,36 +57,10 @@@ unsigned long __stack_chk_guard __read_
  EXPORT_SYMBOL(__stack_chk_guard);
  #endif
  
 -static void setup_restart(void)
 -{
 -      /*
 -       * Tell the mm system that we are going to reboot -
 -       * we may need it to insert some 1:1 mappings so that
 -       * soft boot works.
 -       */
 -      setup_mm_for_reboot();
 -
 -      /* Clean and invalidate caches */
 -      flush_cache_all();
 -
 -      /* Turn D-cache off */
 -      cpu_cache_off();
 -
 -      /* Push out any further dirty data, and ensure cache is empty */
 -      flush_cache_all();
 -}
 -
  void soft_restart(unsigned long addr)
  {
 -      typedef void (*phys_reset_t)(unsigned long);
 -      phys_reset_t phys_reset;
 -
 -      setup_restart();
 -
 -      /* Switch to the identity mapping */
 -      phys_reset = (phys_reset_t)virt_to_phys(cpu_reset);
 -      phys_reset(addr);
 -
 +      setup_mm_for_reboot();
 +      cpu_soft_restart(virt_to_phys(cpu_reset), addr);
        /* Should never get here */
        BUG();
  }
@@@ -72,7 -98,6 +72,6 @@@ void (*pm_power_off)(void)
  EXPORT_SYMBOL_GPL(pm_power_off);
  
  void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
- EXPORT_SYMBOL_GPL(arm_pm_restart);
  
  /*
   * This is our default idle handler.
@@@ -154,6 -179,8 +153,8 @@@ void machine_restart(char *cmd
        /* Now call the architecture specific reboot code. */
        if (arm_pm_restart)
                arm_pm_restart(reboot_mode, cmd);
+       else
+               do_kernel_restart(cmd);
  
        /*
         * Whoops - the architecture was unable to reboot.
@@@ -204,27 -231,9 +205,27 @@@ void exit_thread(void
  {
  }
  
 +static void tls_thread_flush(void)
 +{
 +      asm ("msr tpidr_el0, xzr");
 +
 +      if (is_compat_task()) {
 +              current->thread.tp_value = 0;
 +
 +              /*
 +               * We need to ensure ordering between the shadow state and the
 +               * hardware state, so that we don't corrupt the hardware state
 +               * with a stale shadow state during context switch.
 +               */
 +              barrier();
 +              asm ("msr tpidrro_el0, xzr");
 +      }
 +}
 +
  void flush_thread(void)
  {
        fpsimd_flush_thread();
 +      tls_thread_flush();
        flush_ptrace_hw_breakpoint(current);
  }