]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/commitdiff
Merge branch 'topic/livepatch' of git://git.kernel.org/pub/scm/linux/kernel/git/power...
authorJiri Kosina <jkosina@suse.cz>
Fri, 15 Apr 2016 09:31:51 +0000 (11:31 +0200)
committerJiri Kosina <jkosina@suse.cz>
Fri, 15 Apr 2016 09:42:51 +0000 (11:42 +0200)
Pull livepatching support for ppc64 architecture from Michael Ellerman.

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
1  2 
arch/powerpc/Kconfig
arch/powerpc/kernel/module_64.c
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
index 832cc461d0afab57046ef6b7e1b68b471a9ce69c,926c0eafbee3c4ef0721cfc4e112e0047a97f1a9..944a79a2768ff49d34d7fe2678c6e69212b31742
@@@ -94,6 -94,7 +94,7 @@@ config PP
        select OF_RESERVED_MEM
        select HAVE_FTRACE_MCOUNT_RECORD
        select HAVE_DYNAMIC_FTRACE
+       select HAVE_DYNAMIC_FTRACE_WITH_REGS if MPROFILE_KERNEL
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_GRAPH_TRACER
        select SYSCTL_EXCEPTION_TRACE
        select ARCH_HAS_DEVMEM_IS_ALLOWED
        select HAVE_ARCH_SECCOMP_FILTER
        select ARCH_HAS_UBSAN_SANITIZE_ALL
+       select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS
  
  config GENERIC_CSUM
        def_bool CPU_LITTLE_ENDIAN
@@@ -373,6 -375,24 +375,24 @@@ config PPC_TRANSACTIONAL_ME
         ---help---
           Support user-mode Transactional Memory on POWERPC.
  
+ config DISABLE_MPROFILE_KERNEL
+       bool "Disable use of mprofile-kernel for kernel tracing"
+       depends on PPC64 && CPU_LITTLE_ENDIAN
+       default y
+       help
+         Selecting this options disables use of the mprofile-kernel ABI for
+         kernel tracing. That will cause options such as live patching
+         (CONFIG_LIVEPATCH) which depend on CONFIG_DYNAMIC_FTRACE_WITH_REGS to
+         be disabled also.
+         If you have a toolchain which supports mprofile-kernel, then you can
+         enable this. Otherwise leave it disabled. If you're not sure, say
+         "N".
+ config MPROFILE_KERNEL
+       depends on PPC64 && CPU_LITTLE_ENDIAN
+       def_bool !DISABLE_MPROFILE_KERNEL
  config IOMMU_HELPER
        def_bool PPC64
  
@@@ -557,7 -577,7 +577,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"
@@@ -828,10 -848,14 +848,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
@@@ -1087,3 -1111,5 +1107,5 @@@ config PPC_LIB_RHEA
        bool
  
  source "arch/powerpc/kvm/Kconfig"
+ source "kernel/livepatch/Kconfig"
index 08b7a40de5f85ab1c6f7e5ed205ca52edd5ab12c,848b47499a270662494f24be096e87b885c28787..9ce9a25f58b556c139ff14a616021180a846dff0
@@@ -31,6 -31,7 +31,7 @@@
  #include <asm/code-patching.h>
  #include <linux/sort.h>
  #include <asm/setup.h>
+ #include <asm/sections.h>
  
  /* FIXME: We don't do .init separately.  To do this, we'd need to have
     a separate r2 value in the init and core section, and stub between
@@@ -41,7 -42,6 +42,6 @@@
     --RR.  */
  
  #if defined(_CALL_ELF) && _CALL_ELF == 2
- #define R2_STACK_OFFSET 24
  
  /* An address is simply the address of the function. */
  typedef unsigned long func_desc_t;
@@@ -73,7 -73,6 +73,6 @@@ static unsigned int local_entry_offset(
        return PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
  }
  #else
- #define R2_STACK_OFFSET 40
  
  /* An address is address of the OPD entry, which contains address of fn. */
  typedef struct ppc64_opd_entry func_desc_t;
@@@ -96,6 -95,8 +95,8 @@@ static unsigned int local_entry_offset(
  }
  #endif
  
+ #define STUB_MAGIC 0x73747562 /* stub */
  /* Like PPC32, we need little trampolines to do > 24-bit jumps (into
     the kernel itself).  But on PPC64, these need to be used for every
     jump, actually, to reset r2 (TOC+0x8000). */
@@@ -105,7 -106,8 +106,8 @@@ struct ppc64_stub_entr
         * need 6 instructions on ABIv2 but we always allocate 7 so
         * so we don't have to modify the trampoline load instruction. */
        u32 jump[7];
-       u32 unused;
+       /* Used by ftrace to identify stubs */
+       u32 magic;
        /* Data for the above code */
        func_desc_t funcdata;
  };
@@@ -139,70 -141,39 +141,39 @@@ static u32 ppc64_stub_insns[] = 
  };
  
  #ifdef CONFIG_DYNAMIC_FTRACE
- static u32 ppc64_stub_mask[] = {
-       0xffff0000,
-       0xffff0000,
-       0xffffffff,
-       0xffffffff,
- #if !defined(_CALL_ELF) || _CALL_ELF != 2
-       0xffffffff,
- #endif
-       0xffffffff,
-       0xffffffff
- };
- bool is_module_trampoline(u32 *p)
+ int module_trampoline_target(struct module *mod, unsigned long addr,
+                            unsigned long *target)
  {
-       unsigned int i;
-       u32 insns[ARRAY_SIZE(ppc64_stub_insns)];
-       BUILD_BUG_ON(sizeof(ppc64_stub_insns) != sizeof(ppc64_stub_mask));
+       struct ppc64_stub_entry *stub;
+       func_desc_t funcdata;
+       u32 magic;
  
-       if (probe_kernel_read(insns, p, sizeof(insns)))
+       if (!within_module_core(addr, mod)) {
+               pr_err("%s: stub %lx not in module %s\n", __func__, addr, mod->name);
                return -EFAULT;
-       for (i = 0; i < ARRAY_SIZE(ppc64_stub_insns); i++) {
-               u32 insna = insns[i];
-               u32 insnb = ppc64_stub_insns[i];
-               u32 mask = ppc64_stub_mask[i];
-               if ((insna & mask) != (insnb & mask))
-                       return false;
        }
  
-       return true;
- }
- int module_trampoline_target(struct module *mod, u32 *trampoline,
-                            unsigned long *target)
- {
-       u32 buf[2];
-       u16 upper, lower;
-       long offset;
-       void *toc_entry;
+       stub = (struct ppc64_stub_entry *)addr;
  
-       if (probe_kernel_read(buf, trampoline, sizeof(buf)))
+       if (probe_kernel_read(&magic, &stub->magic, sizeof(magic))) {
+               pr_err("%s: fault reading magic for stub %lx for %s\n", __func__, addr, mod->name);
                return -EFAULT;
+       }
  
-       upper = buf[0] & 0xffff;
-       lower = buf[1] & 0xffff;
-       /* perform the addis/addi, both signed */
-       offset = ((short)upper << 16) + (short)lower;
+       if (magic != STUB_MAGIC) {
+               pr_err("%s: bad magic for stub %lx for %s\n", __func__, addr, mod->name);
+               return -EFAULT;
+       }
  
-       /*
-        * Now get the address this trampoline jumps to. This
-        * is always 32 bytes into our trampoline stub.
-        */
-       toc_entry = (void *)mod->arch.toc + offset + 32;
+       if (probe_kernel_read(&funcdata, &stub->funcdata, sizeof(funcdata))) {
+               pr_err("%s: fault reading funcdata for stub %lx for %s\n", __func__, addr, mod->name);
+                 return -EFAULT;
+       }
  
-       if (probe_kernel_read(target, toc_entry, sizeof(*target)))
-               return -EFAULT;
+       *target = stub_func_addr(funcdata);
  
        return 0;
  }
  #endif
  
  /* Count how many different 24-bit relocations (different symbol,
@@@ -340,7 -311,7 +311,7 @@@ static void dedotify(Elf64_Sym *syms, u
                        if (name[0] == '.') {
                                if (strcmp(name+1, "TOC.") == 0)
                                        syms[i].st_shndx = SHN_ABS;
 -                              memmove(name, name+1, strlen(name));
 +                              syms[i].st_name++;
                        }
                }
        }
@@@ -413,7 -384,7 +384,7 @@@ int module_frob_arch_sections(Elf64_Ehd
  /* r2 is the TOC pointer: it actually points 0x8000 into the TOC (this
     gives the value maximum span in an instruction which uses a signed
     offset) */
- static inline unsigned long my_r2(Elf64_Shdr *sechdrs, struct module *me)
+ static inline unsigned long my_r2(const Elf64_Shdr *sechdrs, struct module *me)
  {
        return sechdrs[me->arch.toc_section].sh_addr + 0x8000;
  }
  #define PPC_HA(v) PPC_HI ((v) + 0x8000)
  
  /* Patch stub to reference function and correct r2 value. */
- static inline int create_stub(Elf64_Shdr *sechdrs,
+ static inline int create_stub(const Elf64_Shdr *sechdrs,
                              struct ppc64_stub_entry *entry,
                              unsigned long addr,
                              struct module *me)
        entry->jump[0] |= PPC_HA(reladdr);
        entry->jump[1] |= PPC_LO(reladdr);
        entry->funcdata = func_desc(addr);
+       entry->magic = STUB_MAGIC;
        return 1;
  }
  
  /* Create stub to jump to function described in this OPD/ptr: we need the
     stub to set up the TOC ptr (r2) for the function. */
- static unsigned long stub_for_addr(Elf64_Shdr *sechdrs,
+ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs,
                                   unsigned long addr,
                                   struct module *me)
  {
        return (unsigned long)&stubs[i];
  }
  
+ #ifdef CC_USING_MPROFILE_KERNEL
+ static bool is_early_mcount_callsite(u32 *instruction)
+ {
+       /*
+        * Check if this is one of the -mprofile-kernel sequences.
+        */
+       if (instruction[-1] == PPC_INST_STD_LR &&
+           instruction[-2] == PPC_INST_MFLR)
+               return true;
+       if (instruction[-1] == PPC_INST_MFLR)
+               return true;
+       return false;
+ }
+ /*
+  * In case of _mcount calls, do not save the current callee's TOC (in r2) into
+  * the original caller's stack frame. If we did we would clobber the saved TOC
+  * value of the original caller.
+  */
+ static void squash_toc_save_inst(const char *name, unsigned long addr)
+ {
+       struct ppc64_stub_entry *stub = (struct ppc64_stub_entry *)addr;
+       /* Only for calls to _mcount */
+       if (strcmp("_mcount", name) != 0)
+               return;
+       stub->jump[2] = PPC_INST_NOP;
+ }
+ #else
+ static void squash_toc_save_inst(const char *name, unsigned long addr) { }
+ /* without -mprofile-kernel, mcount calls are never early */
+ static bool is_early_mcount_callsite(u32 *instruction)
+ {
+       return false;
+ }
+ #endif
  /* We expect a noop next: if it is, replace it with instruction to
     restore r2. */
  static int restore_r2(u32 *instruction, struct module *me)
  {
        if (*instruction != PPC_INST_NOP) {
+               if (is_early_mcount_callsite(instruction - 1))
+                       return 1;
                pr_err("%s: Expect noop after relocate, got %08x\n",
                       me->name, *instruction);
                return 0;
        }
        /* ld r2,R2_STACK_OFFSET(r1) */
-       *instruction = 0xe8410000 | R2_STACK_OFFSET;
+       *instruction = PPC_INST_LD_TOC;
        return 1;
  }
  
@@@ -611,6 -627,8 +627,8 @@@ int apply_relocate_add(Elf64_Shdr *sech
                                        return -ENOENT;
                                if (!restore_r2((u32 *)location + 1, me))
                                        return -ENOEXEC;
+                               squash_toc_save_inst(strtab + sym->st_name, value);
                        } else
                                value += local_entry_offset(sym);
  
                }
        }
  
+       return 0;
+ }
  #ifdef CONFIG_DYNAMIC_FTRACE
-       me->arch.toc = my_r2(sechdrs, me);
-       me->arch.tramp = stub_for_addr(sechdrs,
-                                      (unsigned long)ftrace_caller,
-                                      me);
+ #ifdef CC_USING_MPROFILE_KERNEL
+ #define PACATOC offsetof(struct paca_struct, kernel_toc)
+ /*
+  * For mprofile-kernel we use a special stub for ftrace_caller() because we
+  * can't rely on r2 containing this module's TOC when we enter the stub.
+  *
+  * That can happen if the function calling us didn't need to use the toc. In
+  * that case it won't have setup r2, and the r2 value will be either the
+  * kernel's toc, or possibly another modules toc.
+  *
+  * To deal with that this stub uses the kernel toc, which is always accessible
+  * via the paca (in r13). The target (ftrace_caller()) is responsible for
+  * saving and restoring the toc before returning.
+  */
+ static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me)
+ {
+       struct ppc64_stub_entry *entry;
+       unsigned int i, num_stubs;
+       static u32 stub_insns[] = {
+               0xe98d0000 | PACATOC,   /* ld      r12,PACATOC(r13)     */
+               0x3d8c0000,             /* addis   r12,r12,<high>       */
+               0x398c0000,             /* addi    r12,r12,<low>        */
+               0x7d8903a6,             /* mtctr   r12                  */
+               0x4e800420,             /* bctr                         */
+       };
+       long reladdr;
+       num_stubs = sechdrs[me->arch.stubs_section].sh_size / sizeof(*entry);
+       /* Find the next available stub entry */
+       entry = (void *)sechdrs[me->arch.stubs_section].sh_addr;
+       for (i = 0; i < num_stubs && stub_func_addr(entry->funcdata); i++, entry++);
+       if (i >= num_stubs) {
+               pr_err("%s: Unable to find a free slot for ftrace stub.\n", me->name);
+               return 0;
+       }
+       memcpy(entry->jump, stub_insns, sizeof(stub_insns));
+       /* Stub uses address relative to kernel toc (from the paca) */
+       reladdr = (unsigned long)ftrace_caller - kernel_toc_addr();
+       if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
+               pr_err("%s: Address of ftrace_caller out of range of kernel_toc.\n", me->name);
+               return 0;
+       }
+       entry->jump[1] |= PPC_HA(reladdr);
+       entry->jump[2] |= PPC_LO(reladdr);
+       /* Eventhough we don't use funcdata in the stub, it's needed elsewhere. */
+       entry->funcdata = func_desc((unsigned long)ftrace_caller);
+       entry->magic = STUB_MAGIC;
+       return (unsigned long)entry;
+ }
+ #else
+ static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me)
+ {
+       return stub_for_addr(sechdrs, (unsigned long)ftrace_caller, me);
+ }
  #endif
  
+ int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
+ {
+       mod->arch.toc = my_r2(sechdrs, mod);
+       mod->arch.tramp = create_ftrace_stub(sechdrs, mod);
+       if (!mod->arch.tramp)
+               return -ENOENT;
        return 0;
  }
+ #endif
index 3c5736e52a14b7d42dd0c28425e709b0a7147c3c,a38ce49648cb76e5bf184291ce5b73f11551314d..a290ee374aa042dca1059d6e32e2f5ba66621c3b
@@@ -55,6 -55,8 +55,8 @@@
  #include <asm/firmware.h>
  #endif
  #include <asm/code-patching.h>
+ #include <asm/livepatch.h>
  #include <linux/kprobes.h>
  #include <linux/kdebug.h>
  
@@@ -1267,13 -1269,15 +1269,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 */
@@@ -1768,9 -1772,9 +1772,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;
  }
index f98be8383a39994868ba41d0f8492e99f48eb1fe,e37b92ebb3157335bb513eb6f04918edfc7de447..96d4a2b23d0fe233a5f84849c92ada268d5d0451
@@@ -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
index 6d9df3f7e334c3a942728237dca471f7bb602f98,3481a8e405f9e6d613571097344adb2c632f4206..93230e97e897be6ee14beab7d6bbf0016256ec8c
@@@ -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);
diff --combined kernel/livepatch/core.c
index 28c37fa3d3f951230ddafd1a2973ff7bd3d6bfe8,35ee2c5b717663d889c7cbf58227cee5f73569db..a19f1954f4ac7c1f9fde0af0bc0905547b4a8aef
@@@ -28,8 -28,6 +28,8 @@@
  #include <linux/list.h>
  #include <linux/kallsyms.h>
  #include <linux/livepatch.h>
 +#include <linux/elf.h>
 +#include <linux/moduleloader.h>
  #include <asm/cacheflush.h>
  
  /**
@@@ -101,12 -99,12 +101,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.
@@@ -192,8 -190,8 +192,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");
        return -EINVAL;
  }
  
 -/*
 - * external symbols are located outside the parent object (where the parent
 - * object is either vmlinux or the kmod being patched).
 - */
 -static int klp_find_external_symbol(struct module *pmod, const char *name,
 -                                  unsigned long *addr)
 +static int klp_resolve_symbols(Elf_Shdr *relasec, struct module *pmod)
  {
 -      const struct kernel_symbol *sym;
 -
 -      /* first, check if it's an exported symbol */
 -      preempt_disable();
 -      sym = find_symbol(name, NULL, NULL, true, true);
 -      if (sym) {
 -              *addr = sym->value;
 -              preempt_enable();
 -              return 0;
 -      }
 -      preempt_enable();
 +      int i, cnt, vmlinux, ret;
 +      char objname[MODULE_NAME_LEN];
 +      char symname[KSYM_NAME_LEN];
 +      char *strtab = pmod->core_kallsyms.strtab;
 +      Elf_Rela *relas;
 +      Elf_Sym *sym;
 +      unsigned long sympos, addr;
  
        /*
 -       * Check if it's in another .o within the patch module. This also
 -       * checks that the external symbol is unique.
 +       * Since the field widths for objname and symname in the sscanf()
 +       * call are hard-coded and correspond to MODULE_NAME_LEN and
 +       * KSYM_NAME_LEN respectively, we must make sure that MODULE_NAME_LEN
 +       * and KSYM_NAME_LEN have the values we expect them to have.
 +       *
 +       * Because the value of MODULE_NAME_LEN can differ among architectures,
 +       * we use the smallest/strictest upper bound possible (56, based on
 +       * the current definition of MODULE_NAME_LEN) to prevent overflows.
         */
 -      return klp_find_object_symbol(pmod->name, name, 0, addr);
 +      BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128);
 +
 +      relas = (Elf_Rela *) relasec->sh_addr;
 +      /* For each rela in this klp relocation section */
 +      for (i = 0; i < relasec->sh_size / sizeof(Elf_Rela); i++) {
 +              sym = pmod->core_kallsyms.symtab + ELF_R_SYM(relas[i].r_info);
 +              if (sym->st_shndx != SHN_LIVEPATCH) {
 +                      pr_err("symbol %s is not marked as a livepatch symbol",
 +                             strtab + sym->st_name);
 +                      return -EINVAL;
 +              }
 +
 +              /* Format: .klp.sym.objname.symname,sympos */
 +              cnt = sscanf(strtab + sym->st_name,
 +                           ".klp.sym.%55[^.].%127[^,],%lu",
 +                           objname, symname, &sympos);
 +              if (cnt != 3) {
 +                      pr_err("symbol %s has an incorrectly formatted name",
 +                             strtab + sym->st_name);
 +                      return -EINVAL;
 +              }
 +
 +              /* klp_find_object_symbol() treats a NULL objname as vmlinux */
 +              vmlinux = !strcmp(objname, "vmlinux");
 +              ret = klp_find_object_symbol(vmlinux ? NULL : objname,
 +                                           symname, sympos, &addr);
 +              if (ret)
 +                      return ret;
 +
 +              sym->st_value = addr;
 +      }
 +
 +      return 0;
  }
  
  static int klp_write_object_relocations(struct module *pmod,
                                        struct klp_object *obj)
  {
 -      int ret = 0;
 -      unsigned long val;
 -      struct klp_reloc *reloc;
 +      int i, cnt, ret = 0;
 +      const char *objname, *secname;
 +      char sec_objname[MODULE_NAME_LEN];
 +      Elf_Shdr *sec;
  
        if (WARN_ON(!klp_is_object_loaded(obj)))
                return -EINVAL;
  
 -      if (WARN_ON(!obj->relocs))
 -              return -EINVAL;
 +      objname = klp_is_module(obj) ? obj->name : "vmlinux";
  
        module_disable_ro(pmod);
 +      /* For each klp relocation section */
 +      for (i = 1; i < pmod->klp_info->hdr.e_shnum; i++) {
 +              sec = pmod->klp_info->sechdrs + i;
 +              secname = pmod->klp_info->secstrings + sec->sh_name;
 +              if (!(sec->sh_flags & SHF_RELA_LIVEPATCH))
 +                      continue;
  
 -      for (reloc = obj->relocs; reloc->name; reloc++) {
 -              /* discover the address of the referenced symbol */
 -              if (reloc->external) {
 -                      if (reloc->sympos > 0) {
 -                              pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n",
 -                                     reloc->name);
 -                              ret = -EINVAL;
 -                              goto out;
 -                      }
 -                      ret = klp_find_external_symbol(pmod, reloc->name, &val);
 -              } else
 -                      ret = klp_find_object_symbol(obj->name,
 -                                                   reloc->name,
 -                                                   reloc->sympos,
 -                                                   &val);
 +              /*
 +               * Format: .klp.rela.sec_objname.section_name
 +               * See comment in klp_resolve_symbols() for an explanation
 +               * of the selected field width value.
 +               */
 +              cnt = sscanf(secname, ".klp.rela.%55[^.]", sec_objname);
 +              if (cnt != 1) {
 +                      pr_err("section %s has an incorrectly formatted name",
 +                             secname);
 +                      ret = -EINVAL;
 +                      break;
 +              }
 +
 +              if (strcmp(objname, sec_objname))
 +                      continue;
 +
 +              ret = klp_resolve_symbols(sec, pmod);
                if (ret)
 -                      goto out;
 +                      break;
  
 -              ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc,
 -                                           val + reloc->addend);
 -              if (ret) {
 -                      pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n",
 -                             reloc->name, val, ret);
 -                      goto out;
 -              }
 +              ret = apply_relocate_add(pmod->klp_info->sechdrs,
 +                                       pmod->core_kallsyms.strtab,
 +                                       pmod->klp_info->symndx, i, pmod);
 +              if (ret)
 +                      break;
        }
  
 -out:
        module_enable_ro(pmod);
        return ret;
  }
@@@ -334,6 -298,19 +334,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);
@@@ -374,6 -357,15 +393,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;
                }
  
@@@ -739,9 -731,11 +767,9 @@@ static int klp_init_object_loaded(struc
        struct klp_func *func;
        int ret;
  
 -      if (obj->relocs) {
 -              ret = klp_write_object_relocations(patch->mod, obj);
 -              if (ret)
 -                      return ret;
 -      }
 +      ret = klp_write_object_relocations(patch->mod, obj);
 +      if (ret)
 +              return ret;
  
        klp_for_each_func(obj, func) {
                ret = klp_find_object_symbol(obj->name, func->old_name,
@@@ -876,18 -870,12 +904,18 @@@ int klp_register_patch(struct klp_patc
  {
        int ret;
  
 -      if (!klp_initialized())
 -              return -ENODEV;
 -
        if (!patch || !patch->mod)
                return -EINVAL;
  
 +      if (!is_livepatch_module(patch->mod)) {
 +              pr_err("module %s is not marked as a livepatch module",
 +                     patch->mod->name);
 +              return -EINVAL;
 +      }
 +
 +      if (!klp_initialized())
 +              return -ENODEV;
 +
        /*
         * A reference is taken on the patch module to prevent it from being
         * unloaded.  Right now, we don't allow patch modules to unload since
  }
  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;
 +
 +      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;
  
 -      pr_notice("applying patch '%s' to loading module '%s'\n",
 -                pmod->name, mod->name);
 +                      obj->mod = mod;
  
 -      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;
 -}
 +                      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;
 +                      }
  
 -static void klp_module_notify_going(struct klp_patch *patch,
 -                                  struct klp_object *obj)
 -{
 -      struct module *pmod = patch->mod;
 -      struct module *mod = obj->mod;
 +                      if (patch->state == KLP_DISABLED)
 +                              break;
  
 -      if (patch->state == KLP_DISABLED)
 -              goto disabled;
 +                      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
index 57a6eea8469408e7aba78669107eb3a1740362e4,e1b3f2312db0107a74b1441f2dbb1c6a132da209..f4e6aae6ebe76cd2e7b0d27bcc3be90a7cdf1247
@@@ -1533,7 -1533,19 +1533,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;
@@@ -4961,7 -4973,7 +4973,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;
@@@ -5038,8 -5050,38 +5050,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;