Merge branch 'topic/livepatch' into next
authorMichael Ellerman <mpe@ellerman.id.au>
Mon, 18 Apr 2016 10:45:32 +0000 (20:45 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 18 Apr 2016 10:45:32 +0000 (20:45 +1000)
Merge the support for live patching on ppc64le using mprofile-kernel.
This branch has also been merged into the livepatching tree for v4.7.

1  2 
arch/powerpc/Kconfig
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/setup_64.c
include/linux/ftrace.h
kernel/livepatch/core.c
kernel/trace/ftrace.c

diff --combined arch/powerpc/Kconfig
@@@ -159,7 -159,7 +159,8 @@@ config PP
        select ARCH_HAS_DEVMEM_IS_ALLOWED
        select HAVE_ARCH_SECCOMP_FILTER
        select ARCH_HAS_UBSAN_SANITIZE_ALL
 +      select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
+       select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
  
  config GENERIC_CSUM
        def_bool CPU_LITTLE_ENDIAN
@@@ -305,7 -305,7 +306,7 @@@ config ZONE_DMA3
  config PGTABLE_LEVELS
        int
        default 2 if !PPC64
 -      default 3 if PPC_64K_PAGES
 +      default 3 if PPC_64K_PAGES && !PPC_BOOK3S_64
        default 4
  
  source "init/Kconfig"
@@@ -409,7 -409,7 +410,7 @@@ config SWIOTL
  config HOTPLUG_CPU
        bool "Support for enabling/disabling CPUs"
        depends on SMP && (PPC_PSERIES || \
 -      PPC_PMAC || PPC_POWERNV || (PPC_85xx && !PPC_E500MC))
 +      PPC_PMAC || PPC_POWERNV || FSL_SOC_BOOKE)
        ---help---
          Say Y here to be able to disable and re-enable individual
          CPUs at runtime on SMP machines.
@@@ -577,7 -577,7 +578,7 @@@ choic
  
  config PPC_4K_PAGES
        bool "4k page size"
 -      select HAVE_ARCH_SOFT_DIRTY if CHECKPOINT_RESTORE && PPC_BOOK3S
 +      select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64
  
  config PPC_16K_PAGES
        bool "16k page size"
  config PPC_64K_PAGES
        bool "64k page size"
        depends on !PPC_FSL_BOOK3E && (44x || PPC_STD_MMU_64 || PPC_BOOK3E_64)
 -      select HAVE_ARCH_SOFT_DIRTY if CHECKPOINT_RESTORE && PPC_BOOK3S
 +      select HAVE_ARCH_SOFT_DIRTY if PPC_BOOK3S_64
  
  config PPC_256K_PAGES
        bool "256k page size"
@@@ -605,9 -605,9 +606,9 @@@ endchoic
  
  config FORCE_MAX_ZONEORDER
        int "Maximum zone order"
 -      range 9 64 if PPC64 && PPC_64K_PAGES
 +      range 8 9 if PPC64 && PPC_64K_PAGES
        default "9" if PPC64 && PPC_64K_PAGES
 -      range 13 64 if PPC64 && !PPC_64K_PAGES
 +      range 9 13 if PPC64 && !PPC_64K_PAGES
        default "13" if PPC64 && !PPC_64K_PAGES
        range 9 64 if PPC32 && PPC_16K_PAGES
        default "9" if PPC32 && PPC_16K_PAGES
@@@ -848,10 -848,14 +849,10 @@@ config PCI_826
        select PPC_INDIRECT_PCI
        default y
  
 -source "drivers/pci/pcie/Kconfig"
 -
  source "drivers/pci/Kconfig"
  
  source "drivers/pcmcia/Kconfig"
  
 -source "drivers/pci/hotplug/Kconfig"
 -
  config HAS_RAPIDIO
        bool
        default n
@@@ -1107,3 -1111,5 +1108,5 @@@ config PPC_LIB_RHEA
        bool
  
  source "arch/powerpc/kvm/Kconfig"
+ source "kernel/livepatch/Kconfig"
@@@ -86,6 -86,10 +86,10 @@@ int main(void
        DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
  #endif /* CONFIG_PPC64 */
  
+ #ifdef CONFIG_LIVEPATCH
+       DEFINE(TI_livepatch_sp, offsetof(struct thread_info, livepatch_sp));
+ #endif
        DEFINE(KSP, offsetof(struct thread_struct, ksp));
        DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
  #ifdef CONFIG_BOOKE
        DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fp_state));
        DEFINE(THREAD_FPSAVEAREA, offsetof(struct thread_struct, fp_save_area));
        DEFINE(FPSTATE_FPSCR, offsetof(struct thread_fp_state, fpscr));
 +      DEFINE(THREAD_LOAD_FP, offsetof(struct thread_struct, load_fp));
  #ifdef CONFIG_ALTIVEC
        DEFINE(THREAD_VRSTATE, offsetof(struct thread_struct, vr_state));
        DEFINE(THREAD_VRSAVEAREA, offsetof(struct thread_struct, vr_save_area));
        DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave));
        DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr));
        DEFINE(VRSTATE_VSCR, offsetof(struct thread_vr_state, vscr));
 +      DEFINE(THREAD_LOAD_VEC, offsetof(struct thread_struct, load_vec));
  #endif /* CONFIG_ALTIVEC */
  #ifdef CONFIG_VSX
        DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr));
        DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
        DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
        DEFINE(CPU_SPEC_RESTORE, offsetof(struct cpu_spec, cpu_restore));
 +      DEFINE(CPU_DOWN_FLUSH, offsetof(struct cpu_spec, cpu_down_flush));
  
        DEFINE(pbe_address, offsetof(struct pbe, address));
        DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
@@@ -20,6 -20,7 +20,7 @@@
  
  #include <linux/errno.h>
  #include <linux/err.h>
+ #include <linux/magic.h>
  #include <asm/unistd.h>
  #include <asm/processor.h>
  #include <asm/page.h>
@@@ -210,29 -211,7 +211,29 @@@ system_call:                     /* label this so stack t
        li      r11,-MAX_ERRNO
        andi.   r0,r9,(_TIF_SYSCALL_DOTRACE|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK)
        bne-    syscall_exit_work
 -      cmpld   r3,r11
 +
 +      andi.   r0,r8,MSR_FP
 +      beq 2f
 +#ifdef CONFIG_ALTIVEC
 +      andis.  r0,r8,MSR_VEC@h
 +      bne     3f
 +#endif
 +2:    addi    r3,r1,STACK_FRAME_OVERHEAD
 +#ifdef CONFIG_PPC_BOOK3S
 +      mtmsrd  r10,1           /* Restore RI */
 +#endif
 +      bl      restore_math
 +#ifdef CONFIG_PPC_BOOK3S
 +      ld      r10,PACAKMSR(r13)
 +      li      r9,MSR_RI
 +      andc    r11,r10,r9 /* Re-clear RI */
 +      mtmsrd  r11,1
 +#endif
 +      ld      r8,_MSR(r1)
 +      ld      r3,RESULT(r1)
 +      li      r11,-MAX_ERRNO
 +
 +3:    cmpld   r3,r11
        ld      r5,_CCR(r1)
        bge-    syscall_error
  .Lsyscall_error_cont:
@@@ -624,8 -603,8 +625,8 @@@ _GLOBAL(ret_from_except_lite
  
        /* Check current_thread_info()->flags */
        andi.   r0,r4,_TIF_USER_WORK_MASK
 -#ifdef CONFIG_PPC_BOOK3E
        bne     1f
 +#ifdef CONFIG_PPC_BOOK3E
        /*
         * Check to see if the dbcr0 register is set up to debug.
         * Use the internal debug mode bit to do this.
        mtspr   SPRN_DBSR,r10
        b       restore
  #else
 -      beq     restore
 +      addi    r3,r1,STACK_FRAME_OVERHEAD
 +      bl      restore_math
 +      b       restore
  #endif
  1:    andi.   r0,r4,_TIF_NEED_RESCHED
        beq     2f
@@@ -1248,6 -1225,9 +1249,9 @@@ _GLOBAL(ftrace_caller
        addi    r3,r3,function_trace_op@toc@l
        ld      r5,0(r3)
  
+ #ifdef CONFIG_LIVEPATCH
+       mr      r14,r7          /* remember old NIP */
+ #endif
        /* Calculate ip from nip-4 into r3 for call below */
        subi    r3, r7, MCOUNT_INSN_SIZE
  
@@@ -1272,6 -1252,9 +1276,9 @@@ ftrace_call
        /* Load ctr with the possibly modified NIP */
        ld      r3, _NIP(r1)
        mtctr   r3
+ #ifdef CONFIG_LIVEPATCH
+       cmpd    r14,r3          /* has NIP been altered? */
+ #endif
  
        /* Restore gprs */
        REST_8GPRS(0,r1)
        ld      r0, LRSAVE(r1)
        mtlr    r0
  
+ #ifdef CONFIG_LIVEPATCH
+         /* Based on the cmpd above, if the NIP was altered handle livepatch */
+       bne-    livepatch_handler
+ #endif
  #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        stdu    r1, -112(r1)
  .globl ftrace_graph_call
@@@ -1305,6 -1293,91 +1317,91 @@@ _GLOBAL(ftrace_graph_stub
  
  _GLOBAL(ftrace_stub)
        blr
+ #ifdef CONFIG_LIVEPATCH
+       /*
+        * This function runs in the mcount context, between two functions. As
+        * such it can only clobber registers which are volatile and used in
+        * function linkage.
+        *
+        * We get here when a function A, calls another function B, but B has
+        * been live patched with a new function C.
+        *
+        * On entry:
+        *  - we have no stack frame and can not allocate one
+        *  - LR points back to the original caller (in A)
+        *  - CTR holds the new NIP in C
+        *  - r0 & r12 are free
+        *
+        * r0 can't be used as the base register for a DS-form load or store, so
+        * we temporarily shuffle r1 (stack pointer) into r0 and then put it back.
+        */
+ livepatch_handler:
+       CURRENT_THREAD_INFO(r12, r1)
+       /* Save stack pointer into r0 */
+       mr      r0, r1
+       /* Allocate 3 x 8 bytes */
+       ld      r1, TI_livepatch_sp(r12)
+       addi    r1, r1, 24
+       std     r1, TI_livepatch_sp(r12)
+       /* Save toc & real LR on livepatch stack */
+       std     r2,  -24(r1)
+       mflr    r12
+       std     r12, -16(r1)
+       /* Store stack end marker */
+       lis     r12, STACK_END_MAGIC@h
+       ori     r12, r12, STACK_END_MAGIC@l
+       std     r12, -8(r1)
+       /* Restore real stack pointer */
+       mr      r1, r0
+       /* Put ctr in r12 for global entry and branch there */
+       mfctr   r12
+       bctrl
+       /*
+        * Now we are returning from the patched function to the original
+        * caller A. We are free to use r0 and r12, and we can use r2 until we
+        * restore it.
+        */
+       CURRENT_THREAD_INFO(r12, r1)
+       /* Save stack pointer into r0 */
+       mr      r0, r1
+       ld      r1, TI_livepatch_sp(r12)
+       /* Check stack marker hasn't been trashed */
+       lis     r2,  STACK_END_MAGIC@h
+       ori     r2,  r2, STACK_END_MAGIC@l
+       ld      r12, -8(r1)
+ 1:    tdne    r12, r2
+       EMIT_BUG_ENTRY 1b, __FILE__, __LINE__ - 1, 0
+       /* Restore LR & toc from livepatch stack */
+       ld      r12, -16(r1)
+       mtlr    r12
+       ld      r2,  -24(r1)
+       /* Pop livepatch stack frame */
+       CURRENT_THREAD_INFO(r12, r0)
+       subi    r1, r1, 24
+       std     r1, TI_livepatch_sp(r12)
+       /* Restore real stack pointer */
+       mr      r1, r0
+       /* Return to original caller of live patched function */
+       blr
+ #endif
  #else
  _GLOBAL_TOC(_mcount)
        /* Taken from output of objdump from lib64/glibc */
@@@ -38,7 -38,6 +38,7 @@@
  #include <linux/random.h>
  #include <linux/hw_breakpoint.h>
  #include <linux/uaccess.h>
 +#include <linux/elf-randomize.h>
  
  #include <asm/pgtable.h>
  #include <asm/io.h>
@@@ -56,7 -55,8 +56,9 @@@
  #include <asm/firmware.h>
  #endif
  #include <asm/code-patching.h>
 +#include <asm/exec.h>
+ #include <asm/livepatch.h>
  #include <linux/kprobes.h>
  #include <linux/kdebug.h>
  
@@@ -135,16 -135,6 +137,16 @@@ void __msr_check_and_clear(unsigned lon
  EXPORT_SYMBOL(__msr_check_and_clear);
  
  #ifdef CONFIG_PPC_FPU
 +void __giveup_fpu(struct task_struct *tsk)
 +{
 +      save_fpu(tsk);
 +      tsk->thread.regs->msr &= ~MSR_FP;
 +#ifdef CONFIG_VSX
 +      if (cpu_has_feature(CPU_FTR_VSX))
 +              tsk->thread.regs->msr &= ~MSR_VSX;
 +#endif
 +}
 +
  void giveup_fpu(struct task_struct *tsk)
  {
        check_if_tm_restore_required(tsk);
@@@ -199,32 -189,9 +201,32 @@@ void enable_kernel_fp(void
        }
  }
  EXPORT_SYMBOL(enable_kernel_fp);
 +
 +static int restore_fp(struct task_struct *tsk) {
 +      if (tsk->thread.load_fp) {
 +              load_fp_state(&current->thread.fp_state);
 +              current->thread.load_fp++;
 +              return 1;
 +      }
 +      return 0;
 +}
 +#else
 +static int restore_fp(struct task_struct *tsk) { return 0; }
  #endif /* CONFIG_PPC_FPU */
  
  #ifdef CONFIG_ALTIVEC
 +#define loadvec(thr) ((thr).load_vec)
 +
 +static void __giveup_altivec(struct task_struct *tsk)
 +{
 +      save_altivec(tsk);
 +      tsk->thread.regs->msr &= ~MSR_VEC;
 +#ifdef CONFIG_VSX
 +      if (cpu_has_feature(CPU_FTR_VSX))
 +              tsk->thread.regs->msr &= ~MSR_VSX;
 +#endif
 +}
 +
  void giveup_altivec(struct task_struct *tsk)
  {
        check_if_tm_restore_required(tsk);
@@@ -264,49 -231,22 +266,49 @@@ void flush_altivec_to_thread(struct tas
        }
  }
  EXPORT_SYMBOL_GPL(flush_altivec_to_thread);
 +
 +static int restore_altivec(struct task_struct *tsk)
 +{
 +      if (cpu_has_feature(CPU_FTR_ALTIVEC) && tsk->thread.load_vec) {
 +              load_vr_state(&tsk->thread.vr_state);
 +              tsk->thread.used_vr = 1;
 +              tsk->thread.load_vec++;
 +
 +              return 1;
 +      }
 +      return 0;
 +}
 +#else
 +#define loadvec(thr) 0
 +static inline int restore_altivec(struct task_struct *tsk) { return 0; }
  #endif /* CONFIG_ALTIVEC */
  
  #ifdef CONFIG_VSX
 -void giveup_vsx(struct task_struct *tsk)
 +static void __giveup_vsx(struct task_struct *tsk)
  {
 -      check_if_tm_restore_required(tsk);
 -
 -      msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX);
        if (tsk->thread.regs->msr & MSR_FP)
                __giveup_fpu(tsk);
        if (tsk->thread.regs->msr & MSR_VEC)
                __giveup_altivec(tsk);
 +      tsk->thread.regs->msr &= ~MSR_VSX;
 +}
 +
 +static void giveup_vsx(struct task_struct *tsk)
 +{
 +      check_if_tm_restore_required(tsk);
 +
 +      msr_check_and_set(MSR_FP|MSR_VEC|MSR_VSX);
        __giveup_vsx(tsk);
        msr_check_and_clear(MSR_FP|MSR_VEC|MSR_VSX);
  }
 -EXPORT_SYMBOL(giveup_vsx);
 +
 +static void save_vsx(struct task_struct *tsk)
 +{
 +      if (tsk->thread.regs->msr & MSR_FP)
 +              save_fpu(tsk);
 +      if (tsk->thread.regs->msr & MSR_VEC)
 +              save_altivec(tsk);
 +}
  
  void enable_kernel_vsx(void)
  {
@@@ -337,19 -277,6 +339,19 @@@ void flush_vsx_to_thread(struct task_st
        }
  }
  EXPORT_SYMBOL_GPL(flush_vsx_to_thread);
 +
 +static int restore_vsx(struct task_struct *tsk)
 +{
 +      if (cpu_has_feature(CPU_FTR_VSX)) {
 +              tsk->thread.used_vsr = 1;
 +              return 1;
 +      }
 +
 +      return 0;
 +}
 +#else
 +static inline int restore_vsx(struct task_struct *tsk) { return 0; }
 +static inline void save_vsx(struct task_struct *tsk) { }
  #endif /* CONFIG_VSX */
  
  #ifdef CONFIG_SPE
@@@ -449,76 -376,12 +451,76 @@@ void giveup_all(struct task_struct *tsk
  }
  EXPORT_SYMBOL(giveup_all);
  
 +void restore_math(struct pt_regs *regs)
 +{
 +      unsigned long msr;
 +
 +      if (!current->thread.load_fp && !loadvec(current->thread))
 +              return;
 +
 +      msr = regs->msr;
 +      msr_check_and_set(msr_all_available);
 +
 +      /*
 +       * Only reload if the bit is not set in the user MSR, the bit BEING set
 +       * indicates that the registers are hot
 +       */
 +      if ((!(msr & MSR_FP)) && restore_fp(current))
 +              msr |= MSR_FP | current->thread.fpexc_mode;
 +
 +      if ((!(msr & MSR_VEC)) && restore_altivec(current))
 +              msr |= MSR_VEC;
 +
 +      if ((msr & (MSR_FP | MSR_VEC)) == (MSR_FP | MSR_VEC) &&
 +                      restore_vsx(current)) {
 +              msr |= MSR_VSX;
 +      }
 +
 +      msr_check_and_clear(msr_all_available);
 +
 +      regs->msr = msr;
 +}
 +
 +void save_all(struct task_struct *tsk)
 +{
 +      unsigned long usermsr;
 +
 +      if (!tsk->thread.regs)
 +              return;
 +
 +      usermsr = tsk->thread.regs->msr;
 +
 +      if ((usermsr & msr_all_available) == 0)
 +              return;
 +
 +      msr_check_and_set(msr_all_available);
 +
 +      /*
 +       * Saving the way the register space is in hardware, save_vsx boils
 +       * down to a save_fpu() and save_altivec()
 +       */
 +      if (usermsr & MSR_VSX) {
 +              save_vsx(tsk);
 +      } else {
 +              if (usermsr & MSR_FP)
 +                      save_fpu(tsk);
 +
 +              if (usermsr & MSR_VEC)
 +                      save_altivec(tsk);
 +      }
 +
 +      if (usermsr & MSR_SPE)
 +              __giveup_spe(tsk);
 +
 +      msr_check_and_clear(msr_all_available);
 +}
 +
  void flush_all_to_thread(struct task_struct *tsk)
  {
        if (tsk->thread.regs) {
                preempt_disable();
                BUG_ON(tsk != current);
 -              giveup_all(tsk);
 +              save_all(tsk);
  
  #ifdef CONFIG_SPE
                if (tsk->thread.regs->msr & MSR_SPE)
@@@ -971,9 -834,17 +973,9 @@@ void restore_tm_state(struct pt_regs *r
  
        msr_diff = current->thread.ckpt_regs.msr & ~regs->msr;
        msr_diff &= MSR_FP | MSR_VEC | MSR_VSX;
 -      if (msr_diff & MSR_FP) {
 -              msr_check_and_set(MSR_FP);
 -              load_fp_state(&current->thread.fp_state);
 -              msr_check_and_clear(MSR_FP);
 -              regs->msr |= current->thread.fpexc_mode;
 -      }
 -      if (msr_diff & MSR_VEC) {
 -              msr_check_and_set(MSR_VEC);
 -              load_vr_state(&current->thread.vr_state);
 -              msr_check_and_clear(MSR_VEC);
 -      }
 +
 +      restore_math(regs);
 +
        regs->msr |= msr_diff;
  }
  
  static inline void save_sprs(struct thread_struct *t)
  {
  #ifdef CONFIG_ALTIVEC
 -      if (cpu_has_feature(cpu_has_feature(CPU_FTR_ALTIVEC)))
 +      if (cpu_has_feature(CPU_FTR_ALTIVEC))
                t->vrsave = mfspr(SPRN_VRSAVE);
  #endif
  #ifdef CONFIG_PPC_BOOK3S_64
@@@ -1137,10 -1008,6 +1139,10 @@@ struct task_struct *__switch_to(struct 
                batch = this_cpu_ptr(&ppc64_tlb_batch);
                batch->active = 1;
        }
 +
 +      if (current_thread_info()->task->thread.regs)
 +              restore_math(current_thread_info()->task->thread.regs);
 +
  #endif /* CONFIG_PPC_BOOK3S_64 */
  
        return last;
@@@ -1402,13 -1269,15 +1404,15 @@@ int copy_thread(unsigned long clone_fla
        extern void ret_from_kernel_thread(void);
        void (*f)(void);
        unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;
+       struct thread_info *ti = task_thread_info(p);
+       klp_init_thread_info(ti);
  
        /* Copy registers */
        sp -= sizeof(struct pt_regs);
        childregs = (struct pt_regs *) sp;
        if (unlikely(p->flags & PF_KTHREAD)) {
                /* kernel thread */
-               struct thread_info *ti = (void *)task_stack_page(p);
                memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gpr[1] = sp + sizeof(struct pt_regs);
                /* function */
  
                f = ret_from_fork;
        }
 +      childregs->msr &= ~(MSR_FP|MSR_VEC|MSR_VSX);
        sp -= STACK_FRAME_OVERHEAD;
  
        /*
@@@ -1904,9 -1772,9 +1908,9 @@@ static inline unsigned long brk_rnd(voi
  
        /* 8MB for 32bit, 1GB for 64bit */
        if (is_32bit_task())
 -              rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
 +              rnd = (get_random_long() % (1UL<<(23-PAGE_SHIFT)));
        else
 -              rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
 +              rnd = (get_random_long() % (1UL<<(30-PAGE_SHIFT)));
  
        return rnd << PAGE_SHIFT;
  }
@@@ -69,6 -69,7 +69,7 @@@
  #include <asm/kvm_ppc.h>
  #include <asm/hugetlb.h>
  #include <asm/epapr_hcalls.h>
+ #include <asm/livepatch.h>
  
  #ifdef DEBUG
  #define DBG(fmt...) udbg_printf(fmt)
@@@ -255,6 -256,9 +256,6 @@@ void __init early_setup(unsigned long d
        setup_paca(&boot_paca);
        fixup_boot_paca();
  
 -      /* Initialize lockdep early or else spinlocks will blow */
 -      lockdep_init();
 -
        /* -------- printk is now safe to use ------- */
  
        /* Enable early debugging if any specified (see udbg.h) */
@@@ -667,16 -671,16 +668,16 @@@ static void __init emergency_stack_init
        limit = min(safe_stack_limit(), ppc64_rma_size);
  
        for_each_possible_cpu(i) {
-               unsigned long sp;
-               sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
-               sp += THREAD_SIZE;
-               paca[i].emergency_sp = __va(sp);
+               struct thread_info *ti;
+               ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+               klp_init_thread_info(ti);
+               paca[i].emergency_sp = (void *)ti + THREAD_SIZE;
  
  #ifdef CONFIG_PPC_BOOK3S_64
                /* emergency stack for machine check exception handling. */
-               sp  = memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit);
-               sp += THREAD_SIZE;
-               paca[i].mc_emergency_sp = __va(sp);
+               ti = __va(memblock_alloc_base(THREAD_SIZE, THREAD_SIZE, limit));
+               klp_init_thread_info(ti);
+               paca[i].mc_emergency_sp = (void *)ti + THREAD_SIZE;
  #endif
        }
  }
@@@ -700,6 -704,8 +701,8 @@@ void __init setup_arch(char **cmdline_p
        if (ppc_md.panic)
                setup_panic();
  
+       klp_init_thread_info(&init_thread_info);
        init_mm.start_code = (unsigned long)_stext;
        init_mm.end_code = (unsigned long) _etext;
        init_mm.end_data = (unsigned long) _edata;
diff --combined include/linux/ftrace.h
@@@ -455,6 -455,7 +455,7 @@@ int ftrace_update_record(struct dyn_ftr
  int ftrace_test_record(struct dyn_ftrace *rec, int enable);
  void ftrace_run_stop_machine(int command);
  unsigned long ftrace_location(unsigned long ip);
+ unsigned long ftrace_location_range(unsigned long start, unsigned long end);
  unsigned long ftrace_get_addr_new(struct dyn_ftrace *rec);
  unsigned long ftrace_get_addr_curr(struct dyn_ftrace *rec);
  
@@@ -603,7 -604,6 +604,7 @@@ extern int ftrace_arch_read_dyn_info(ch
  
  extern int skip_trace(unsigned long ip);
  extern void ftrace_module_init(struct module *mod);
 +extern void ftrace_module_enable(struct module *mod);
  extern void ftrace_release_mod(struct module *mod);
  
  extern void ftrace_disable_daemon(void);
@@@ -613,9 -613,8 +614,9 @@@ static inline int skip_trace(unsigned l
  static inline int ftrace_force_update(void) { return 0; }
  static inline void ftrace_disable_daemon(void) { }
  static inline void ftrace_enable_daemon(void) { }
 -static inline void ftrace_release_mod(struct module *mod) {}
 -static inline void ftrace_module_init(struct module *mod) {}
 +static inline void ftrace_module_init(struct module *mod) { }
 +static inline void ftrace_module_enable(struct module *mod) { }
 +static inline void ftrace_release_mod(struct module *mod) { }
  static inline __init int register_ftrace_command(struct ftrace_func_command *cmd)
  {
        return -EINVAL;
@@@ -713,18 -712,6 +714,18 @@@ static inline void __ftrace_enabled_res
  #define CALLER_ADDR5 ((unsigned long)ftrace_return_address(5))
  #define CALLER_ADDR6 ((unsigned long)ftrace_return_address(6))
  
 +static inline unsigned long get_lock_parent_ip(void)
 +{
 +      unsigned long addr = CALLER_ADDR0;
 +
 +      if (!in_lock_functions(addr))
 +              return addr;
 +      addr = CALLER_ADDR1;
 +      if (!in_lock_functions(addr))
 +              return addr;
 +      return CALLER_ADDR2;
 +}
 +
  #ifdef CONFIG_IRQSOFF_TRACER
    extern void time_hardirqs_on(unsigned long a0, unsigned long a1);
    extern void time_hardirqs_off(unsigned long a0, unsigned long a1);
@@@ -811,6 -798,16 +812,6 @@@ ftrace_push_return_trace(unsigned long 
   */
  #define __notrace_funcgraph           notrace
  
 -/*
 - * We want to which function is an entrypoint of a hardirq.
 - * That will help us to put a signal on output.
 - */
 -#define __irq_entry            __attribute__((__section__(".irqentry.text")))
 -
 -/* Limits of hardirq entrypoints */
 -extern char __irqentry_text_start[];
 -extern char __irqentry_text_end[];
 -
  #define FTRACE_NOTRACE_DEPTH 65536
  #define FTRACE_RETFUNC_DEPTH 50
  #define FTRACE_RETSTACK_ALLOC_SIZE 32
@@@ -847,6 -844,7 +848,6 @@@ static inline void unpause_graph_tracin
  #else /* !CONFIG_FUNCTION_GRAPH_TRACER */
  
  #define __notrace_funcgraph
 -#define __irq_entry
  #define INIT_FTRACE_GRAPH
  
  static inline void ftrace_graph_init_task(struct task_struct *t) { }
diff --combined kernel/livepatch/core.c
@@@ -99,12 -99,12 +99,12 @@@ static void klp_find_object_module(stru
        /*
         * We do not want to block removal of patched modules and therefore
         * we do not take a reference here. The patches are removed by
 -       * a going module handler instead.
 +       * klp_module_going() instead.
         */
        mod = find_module(obj->name);
        /*
 -       * Do not mess work of the module coming and going notifiers.
 -       * Note that the patch might still be needed before the going handler
 +       * Do not mess work of klp_module_coming() and klp_module_going().
 +       * Note that the patch might still be needed before klp_module_going()
         * is called. Module functions can be called even in the GOING state
         * until mod->exit() finishes. This is especially important for
         * patches that modify semantic of the functions.
@@@ -190,8 -190,8 +190,8 @@@ static int klp_find_object_symbol(cons
        if (args.addr == 0)
                pr_err("symbol '%s' not found in symbol table\n", name);
        else if (args.count > 1 && sympos == 0) {
 -              pr_err("unresolvable ambiguity (%lu matches) on symbol '%s' in object '%s'\n",
 -                     args.count, name, objname);
 +              pr_err("unresolvable ambiguity for symbol '%s' in object '%s'\n",
 +                     name, objname);
        } else if (sympos != args.count && sympos > 0) {
                pr_err("symbol position %lu for symbol '%s' in object '%s' not found\n",
                       sympos, name, objname ? objname : "vmlinux");
@@@ -298,6 -298,19 +298,19 @@@ unlock
        rcu_read_unlock();
  }
  
+ /*
+  * Convert a function address into the appropriate ftrace location.
+  *
+  * Usually this is just the address of the function, but on some architectures
+  * it's more complicated so allow them to provide a custom behaviour.
+  */
+ #ifndef klp_get_ftrace_location
+ static unsigned long klp_get_ftrace_location(unsigned long faddr)
+ {
+       return faddr;
+ }
+ #endif
  static void klp_disable_func(struct klp_func *func)
  {
        struct klp_ops *ops;
                return;
  
        if (list_is_singular(&ops->func_stack)) {
+               unsigned long ftrace_loc;
+               ftrace_loc = klp_get_ftrace_location(func->old_addr);
+               if (WARN_ON(!ftrace_loc))
+                       return;
                WARN_ON(unregister_ftrace_function(&ops->fops));
-               WARN_ON(ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0));
+               WARN_ON(ftrace_set_filter_ip(&ops->fops, ftrace_loc, 1, 0));
  
                list_del_rcu(&func->stack_node);
                list_del(&ops->node);
@@@ -338,6 -357,15 +357,15 @@@ static int klp_enable_func(struct klp_f
  
        ops = klp_find_ops(func->old_addr);
        if (!ops) {
+               unsigned long ftrace_loc;
+               ftrace_loc = klp_get_ftrace_location(func->old_addr);
+               if (!ftrace_loc) {
+                       pr_err("failed to find location for function '%s'\n",
+                               func->old_name);
+                       return -EINVAL;
+               }
                ops = kzalloc(sizeof(*ops), GFP_KERNEL);
                if (!ops)
                        return -ENOMEM;
                INIT_LIST_HEAD(&ops->func_stack);
                list_add_rcu(&func->stack_node, &ops->func_stack);
  
-               ret = ftrace_set_filter_ip(&ops->fops, func->old_addr, 0, 0);
+               ret = ftrace_set_filter_ip(&ops->fops, ftrace_loc, 0, 0);
                if (ret) {
                        pr_err("failed to set ftrace filter for function '%s' (%d)\n",
                               func->old_name, ret);
                if (ret) {
                        pr_err("failed to register ftrace handler for function '%s' (%d)\n",
                               func->old_name, ret);
-                       ftrace_set_filter_ip(&ops->fops, func->old_addr, 1, 0);
+                       ftrace_set_filter_ip(&ops->fops, ftrace_loc, 1, 0);
                        goto err;
                }
  
@@@ -866,108 -894,103 +894,108 @@@ int klp_register_patch(struct klp_patc
  }
  EXPORT_SYMBOL_GPL(klp_register_patch);
  
 -static int klp_module_notify_coming(struct klp_patch *patch,
 -                                   struct klp_object *obj)
 +int klp_module_coming(struct module *mod)
  {
 -      struct module *pmod = patch->mod;
 -      struct module *mod = obj->mod;
        int ret;
 +      struct klp_patch *patch;
 +      struct klp_object *obj;
  
 -      ret = klp_init_object_loaded(patch, obj);
 -      if (ret) {
 -              pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
 -                      pmod->name, mod->name, ret);
 -              return ret;
 -      }
 +      if (WARN_ON(mod->state != MODULE_STATE_COMING))
 +              return -EINVAL;
  
 -      if (patch->state == KLP_DISABLED)
 -              return 0;
 +      mutex_lock(&klp_mutex);
 +      /*
 +       * Each module has to know that klp_module_coming()
 +       * has been called. We never know what module will
 +       * get patched by a new patch.
 +       */
 +      mod->klp_alive = true;
  
 -      pr_notice("applying patch '%s' to loading module '%s'\n",
 -                pmod->name, mod->name);
 +      list_for_each_entry(patch, &klp_patches, list) {
 +              klp_for_each_object(patch, obj) {
 +                      if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
 +                              continue;
  
 -      ret = klp_enable_object(obj);
 -      if (ret)
 -              pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
 -                      pmod->name, mod->name, ret);
 -      return ret;
 -}
 +                      obj->mod = mod;
  
 -static void klp_module_notify_going(struct klp_patch *patch,
 -                                  struct klp_object *obj)
 -{
 -      struct module *pmod = patch->mod;
 -      struct module *mod = obj->mod;
 +                      ret = klp_init_object_loaded(patch, obj);
 +                      if (ret) {
 +                              pr_warn("failed to initialize patch '%s' for module '%s' (%d)\n",
 +                                      patch->mod->name, obj->mod->name, ret);
 +                              goto err;
 +                      }
  
 -      if (patch->state == KLP_DISABLED)
 -              goto disabled;
 +                      if (patch->state == KLP_DISABLED)
 +                              break;
 +
 +                      pr_notice("applying patch '%s' to loading module '%s'\n",
 +                                patch->mod->name, obj->mod->name);
 +
 +                      ret = klp_enable_object(obj);
 +                      if (ret) {
 +                              pr_warn("failed to apply patch '%s' to module '%s' (%d)\n",
 +                                      patch->mod->name, obj->mod->name, ret);
 +                              goto err;
 +                      }
 +
 +                      break;
 +              }
 +      }
  
 -      pr_notice("reverting patch '%s' on unloading module '%s'\n",
 -                pmod->name, mod->name);
 +      mutex_unlock(&klp_mutex);
  
 -      klp_disable_object(obj);
 +      return 0;
  
 -disabled:
 +err:
 +      /*
 +       * If a patch is unsuccessfully applied, return
 +       * error to the module loader.
 +       */
 +      pr_warn("patch '%s' failed for module '%s', refusing to load module '%s'\n",
 +              patch->mod->name, obj->mod->name, obj->mod->name);
 +      mod->klp_alive = false;
        klp_free_object_loaded(obj);
 +      mutex_unlock(&klp_mutex);
 +
 +      return ret;
  }
  
 -static int klp_module_notify(struct notifier_block *nb, unsigned long action,
 -                           void *data)
 +void klp_module_going(struct module *mod)
  {
 -      int ret;
 -      struct module *mod = data;
        struct klp_patch *patch;
        struct klp_object *obj;
  
 -      if (action != MODULE_STATE_COMING && action != MODULE_STATE_GOING)
 -              return 0;
 +      if (WARN_ON(mod->state != MODULE_STATE_GOING &&
 +                  mod->state != MODULE_STATE_COMING))
 +              return;
  
        mutex_lock(&klp_mutex);
 -
        /*
 -       * Each module has to know that the notifier has been called.
 -       * We never know what module will get patched by a new patch.
 +       * Each module has to know that klp_module_going()
 +       * has been called. We never know what module will
 +       * get patched by a new patch.
         */
 -      if (action == MODULE_STATE_COMING)
 -              mod->klp_alive = true;
 -      else /* MODULE_STATE_GOING */
 -              mod->klp_alive = false;
 +      mod->klp_alive = false;
  
        list_for_each_entry(patch, &klp_patches, list) {
                klp_for_each_object(patch, obj) {
                        if (!klp_is_module(obj) || strcmp(obj->name, mod->name))
                                continue;
  
 -                      if (action == MODULE_STATE_COMING) {
 -                              obj->mod = mod;
 -                              ret = klp_module_notify_coming(patch, obj);
 -                              if (ret) {
 -                                      obj->mod = NULL;
 -                                      pr_warn("patch '%s' is in an inconsistent state!\n",
 -                                              patch->mod->name);
 -                              }
 -                      } else /* MODULE_STATE_GOING */
 -                              klp_module_notify_going(patch, obj);
 +                      if (patch->state != KLP_DISABLED) {
 +                              pr_notice("reverting patch '%s' on unloading module '%s'\n",
 +                                        patch->mod->name, obj->mod->name);
 +                              klp_disable_object(obj);
 +                      }
  
 +                      klp_free_object_loaded(obj);
                        break;
                }
        }
  
        mutex_unlock(&klp_mutex);
 -
 -      return 0;
  }
  
 -static struct notifier_block klp_module_nb = {
 -      .notifier_call = klp_module_notify,
 -      .priority = INT_MIN+1, /* called late but before ftrace notifier */
 -};
 -
  static int __init klp_init(void)
  {
        int ret;
                return -EINVAL;
        }
  
 -      ret = register_module_notifier(&klp_module_nb);
 -      if (ret)
 -              return ret;
 -
        klp_root_kobj = kobject_create_and_add("livepatch", kernel_kobj);
 -      if (!klp_root_kobj) {
 -              ret = -ENOMEM;
 -              goto unregister;
 -      }
 +      if (!klp_root_kobj)
 +              return -ENOMEM;
  
        return 0;
 -
 -unregister:
 -      unregister_module_notifier(&klp_module_nb);
 -      return ret;
  }
  
  module_init(klp_init);
diff --combined kernel/trace/ftrace.c
@@@ -1030,7 -1030,8 +1030,7 @@@ static __init void ftrace_profile_trace
        for_each_possible_cpu(cpu) {
                stat = &per_cpu(ftrace_profile_stats, cpu);
  
 -              /* allocate enough for function name + cpu number */
 -              name = kmalloc(32, GFP_KERNEL);
 +              name = kasprintf(GFP_KERNEL, "function%d", cpu);
                if (!name) {
                        /*
                         * The files created are permanent, if something happens
                        return;
                }
                stat->stat = function_stats;
 -              snprintf(name, 32, "function%d", cpu);
                stat->stat.name = name;
                ret = register_stat_tracer(&stat->stat);
                if (ret) {
        entry = tracefs_create_file("function_profile_enabled", 0644,
                                    d_tracer, NULL, &ftrace_profile_fops);
        if (!entry)
 -              pr_warning("Could not create tracefs "
 -                         "'function_profile_enabled' entry\n");
 +              pr_warn("Could not create tracefs 'function_profile_enabled' entry\n");
  }
  
  #else /* CONFIG_FUNCTION_PROFILER */
@@@ -1530,7 -1533,19 +1530,19 @@@ static int ftrace_cmp_recs(const void *
        return 0;
  }
  
- static unsigned long ftrace_location_range(unsigned long start, unsigned long end)
+ /**
+  * ftrace_location_range - return the first address of a traced location
+  *    if it touches the given ip range
+  * @start: start of range to search.
+  * @end: end of range to search (inclusive). @end points to the last byte
+  *    to check.
+  *
+  * Returns rec->ip if the related ftrace location is a least partly within
+  * the given address range. That is, the first address of the instruction
+  * that is either a NOP or call to the function tracer. It checks the ftrace
+  * internal tables to determine if the address belongs or not.
+  */
+ unsigned long ftrace_location_range(unsigned long start, unsigned long end)
  {
        struct ftrace_page *pg;
        struct dyn_ftrace *rec;
@@@ -1607,7 -1622,7 +1619,7 @@@ static bool test_rec_ops_needs_regs(str
        return  keep_regs;
  }
  
 -static void __ftrace_hash_rec_update(struct ftrace_ops *ops,
 +static bool __ftrace_hash_rec_update(struct ftrace_ops *ops,
                                     int filter_hash,
                                     bool inc)
  {
        struct ftrace_hash *other_hash;
        struct ftrace_page *pg;
        struct dyn_ftrace *rec;
 +      bool update = false;
        int count = 0;
        int all = 0;
  
        /* Only update if the ops has been registered */
        if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
 -              return;
 +              return false;
  
        /*
         * In the filter_hash case:
                 * then there's nothing to do.
                 */
                if (ftrace_hash_empty(hash))
 -                      return;
 +                      return false;
        }
  
        do_for_each_ftrace_rec(pg, rec) {
                if (inc) {
                        rec->flags++;
                        if (FTRACE_WARN_ON(ftrace_rec_count(rec) == FTRACE_REF_MAX))
 -                              return;
 +                              return false;
  
                        /*
                         * If there's only a single callback registered to a
                                rec->flags |= FTRACE_FL_REGS;
                } else {
                        if (FTRACE_WARN_ON(ftrace_rec_count(rec) == 0))
 -                              return;
 +                              return false;
                        rec->flags--;
  
                        /*
                         */
                }
                count++;
 +
 +              /* Must match FTRACE_UPDATE_CALLS in ftrace_modify_all_code() */
 +              update |= ftrace_test_record(rec, 1) != FTRACE_UPDATE_IGNORE;
 +
                /* Shortcut, if we handled all records, we are done. */
                if (!all && count == hash->count)
 -                      return;
 +                      return update;
        } while_for_each_ftrace_rec();
 +
 +      return update;
  }
  
 -static void ftrace_hash_rec_disable(struct ftrace_ops *ops,
 +static bool ftrace_hash_rec_disable(struct ftrace_ops *ops,
                                    int filter_hash)
  {
 -      __ftrace_hash_rec_update(ops, filter_hash, 0);
 +      return __ftrace_hash_rec_update(ops, filter_hash, 0);
  }
  
 -static void ftrace_hash_rec_enable(struct ftrace_ops *ops,
 +static bool ftrace_hash_rec_enable(struct ftrace_ops *ops,
                                   int filter_hash)
  {
 -      __ftrace_hash_rec_update(ops, filter_hash, 1);
 +      return __ftrace_hash_rec_update(ops, filter_hash, 1);
  }
  
  static void ftrace_hash_rec_update_modify(struct ftrace_ops *ops,
@@@ -2318,8 -2326,8 +2330,8 @@@ unsigned long ftrace_get_addr_curr(stru
        if (rec->flags & FTRACE_FL_TRAMP_EN) {
                ops = ftrace_find_tramp_ops_curr(rec);
                if (FTRACE_WARN_ON(!ops)) {
 -                      pr_warning("Bad trampoline accounting at: %p (%pS)\n",
 -                                  (void *)rec->ip, (void *)rec->ip);
 +                      pr_warn("Bad trampoline accounting at: %p (%pS)\n",
 +                              (void *)rec->ip, (void *)rec->ip);
                        /* Ftrace is shutting down, return anything */
                        return (unsigned long)FTRACE_ADDR;
                }
@@@ -2648,6 -2656,7 +2660,6 @@@ static int ftrace_startup(struct ftrace
                return ret;
  
        ftrace_start_up++;
 -      command |= FTRACE_UPDATE_CALLS;
  
        /*
         * Note that ftrace probes uses this to start up
                return ret;
        }
  
 -      ftrace_hash_rec_enable(ops, 1);
 +      if (ftrace_hash_rec_enable(ops, 1))
 +              command |= FTRACE_UPDATE_CALLS;
  
        ftrace_startup_enable(command);
  
@@@ -2699,11 -2707,11 +2711,11 @@@ static int ftrace_shutdown(struct ftrac
  
        /* Disabling ipmodify never fails */
        ftrace_hash_ipmodify_disable(ops);
 -      ftrace_hash_rec_disable(ops, 1);
  
 -      ops->flags &= ~FTRACE_OPS_FL_ENABLED;
 +      if (ftrace_hash_rec_disable(ops, 1))
 +              command |= FTRACE_UPDATE_CALLS;
  
 -      command |= FTRACE_UPDATE_CALLS;
 +      ops->flags &= ~FTRACE_OPS_FL_ENABLED;
  
        if (saved_ftrace_func != ftrace_trace_function) {
                saved_ftrace_func = ftrace_trace_function;
@@@ -4965,7 -4973,7 +4977,7 @@@ void ftrace_release_mod(struct module *
        mutex_unlock(&ftrace_lock);
  }
  
 -static void ftrace_module_enable(struct module *mod)
 +void ftrace_module_enable(struct module *mod)
  {
        struct dyn_ftrace *rec;
        struct ftrace_page *pg;
@@@ -5042,8 -5050,38 +5054,8 @@@ void ftrace_module_init(struct module *
        ftrace_process_locs(mod, mod->ftrace_callsites,
                            mod->ftrace_callsites + mod->num_ftrace_callsites);
  }
 -
 -static int ftrace_module_notify(struct notifier_block *self,
 -                              unsigned long val, void *data)
 -{
 -      struct module *mod = data;
 -
 -      switch (val) {
 -      case MODULE_STATE_COMING:
 -              ftrace_module_enable(mod);
 -              break;
 -      case MODULE_STATE_GOING:
 -              ftrace_release_mod(mod);
 -              break;
 -      default:
 -              break;
 -      }
 -
 -      return 0;
 -}
 -#else
 -static int ftrace_module_notify(struct notifier_block *self,
 -                              unsigned long val, void *data)
 -{
 -      return 0;
 -}
  #endif /* CONFIG_MODULES */
  
 -struct notifier_block ftrace_module_nb = {
 -      .notifier_call = ftrace_module_notify,
 -      .priority = INT_MIN,    /* Run after anything that can remove kprobes */
 -};
 -
  void __init ftrace_init(void)
  {
        extern unsigned long __start_mcount_loc[];
                                  __start_mcount_loc,
                                  __stop_mcount_loc);
  
 -      ret = register_module_notifier(&ftrace_module_nb);
 -      if (ret)
 -              pr_warning("Failed to register trace ftrace module exit notifier\n");
 -
        set_ftrace_early_filters();
  
        return;