Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf fixes from Thomas Gleixner:
"A couple of fixes for perf and kprobes:

- Add he missing exclude_kernel attribute for the precise_ip level so
!CAP_SYS_ADMIN users get the proper results.

- Warn instead of failing completely when perf has no unwind support
for a particular architectiure built in.

- Ensure that jprobes are at function entry and not at some random
place"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
kprobes: Ensure that jprobe probepoints are at function entry
kprobes: Simplify register_jprobes()
kprobes: Rename [arch_]function_offset_within_entry() to [arch_]kprobe_on_func_entry()
perf unwind: Do not fail due to missing unwind support
perf evsel: Set attr.exclude_kernel when probing max attr.precise_ip

+30 -23
+1 -1
arch/powerpc/kernel/kprobes.c
··· 217 217 kcb->kprobe_saved_msr = regs->msr; 218 218 } 219 219 220 - bool arch_function_offset_within_entry(unsigned long offset) 220 + bool arch_kprobe_on_func_entry(unsigned long offset) 221 221 { 222 222 #ifdef PPC64_ELF_ABI_v2 223 223 #ifdef CONFIG_KPROBES_ON_FTRACE
+2 -2
include/linux/kprobes.h
··· 267 267 extern void show_registers(struct pt_regs *regs); 268 268 extern void kprobes_inc_nmissed_count(struct kprobe *p); 269 269 extern bool arch_within_kprobe_blacklist(unsigned long addr); 270 - extern bool arch_function_offset_within_entry(unsigned long offset); 271 - extern bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); 270 + extern bool arch_kprobe_on_func_entry(unsigned long offset); 271 + extern bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset); 272 272 273 273 extern bool within_kprobe_blacklist(unsigned long addr); 274 274
+24 -18
kernel/kprobes.c
··· 1771 1771 1772 1772 int register_jprobes(struct jprobe **jps, int num) 1773 1773 { 1774 - struct jprobe *jp; 1775 1774 int ret = 0, i; 1776 1775 1777 1776 if (num <= 0) 1778 1777 return -EINVAL; 1779 - for (i = 0; i < num; i++) { 1780 - unsigned long addr, offset; 1781 - jp = jps[i]; 1782 - addr = arch_deref_entry_point(jp->entry); 1783 1778 1784 - /* Verify probepoint is a function entry point */ 1785 - if (kallsyms_lookup_size_offset(addr, NULL, &offset) && 1786 - offset == 0) { 1787 - jp->kp.pre_handler = setjmp_pre_handler; 1788 - jp->kp.break_handler = longjmp_break_handler; 1789 - ret = register_kprobe(&jp->kp); 1790 - } else 1791 - ret = -EINVAL; 1779 + for (i = 0; i < num; i++) { 1780 + ret = register_jprobe(jps[i]); 1792 1781 1793 1782 if (ret < 0) { 1794 1783 if (i > 0) ··· 1785 1796 break; 1786 1797 } 1787 1798 } 1799 + 1788 1800 return ret; 1789 1801 } 1790 1802 EXPORT_SYMBOL_GPL(register_jprobes); 1791 1803 1792 1804 int register_jprobe(struct jprobe *jp) 1793 1805 { 1794 - return register_jprobes(&jp, 1); 1806 + unsigned long addr, offset; 1807 + struct kprobe *kp = &jp->kp; 1808 + 1809 + /* 1810 + * Verify probepoint as well as the jprobe handler are 1811 + * valid function entry points. 1812 + */ 1813 + addr = arch_deref_entry_point(jp->entry); 1814 + 1815 + if (kallsyms_lookup_size_offset(addr, NULL, &offset) && offset == 0 && 1816 + kprobe_on_func_entry(kp->addr, kp->symbol_name, kp->offset)) { 1817 + kp->pre_handler = setjmp_pre_handler; 1818 + kp->break_handler = longjmp_break_handler; 1819 + return register_kprobe(kp); 1820 + } 1821 + 1822 + return -EINVAL; 1795 1823 } 1796 1824 EXPORT_SYMBOL_GPL(register_jprobe); 1797 1825 ··· 1894 1888 } 1895 1889 NOKPROBE_SYMBOL(pre_handler_kretprobe); 1896 1890 1897 - bool __weak arch_function_offset_within_entry(unsigned long offset) 1891 + bool __weak arch_kprobe_on_func_entry(unsigned long offset) 1898 1892 { 1899 1893 return !offset; 1900 1894 } 1901 1895 1902 - bool function_offset_within_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) 1896 + bool kprobe_on_func_entry(kprobe_opcode_t *addr, const char *sym, unsigned long offset) 1903 1897 { 1904 1898 kprobe_opcode_t *kp_addr = _kprobe_addr(addr, sym, offset); 1905 1899 ··· 1907 1901 return false; 1908 1902 1909 1903 if (!kallsyms_lookup_size_offset((unsigned long)kp_addr, NULL, &offset) || 1910 - !arch_function_offset_within_entry(offset)) 1904 + !arch_kprobe_on_func_entry(offset)) 1911 1905 return false; 1912 1906 1913 1907 return true; ··· 1920 1914 int i; 1921 1915 void *addr; 1922 1916 1923 - if (!function_offset_within_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset)) 1917 + if (!kprobe_on_func_entry(rp->kp.addr, rp->kp.symbol_name, rp->kp.offset)) 1924 1918 return -EINVAL; 1925 1919 1926 1920 if (kretprobe_blacklist_size) {
+1 -1
kernel/trace/trace_kprobe.c
··· 720 720 return ret; 721 721 } 722 722 if (offset && is_return && 723 - !function_offset_within_entry(NULL, symbol, offset)) { 723 + !kprobe_on_func_entry(NULL, symbol, offset)) { 724 724 pr_info("Given offset is not valid for return probe.\n"); 725 725 return -EINVAL; 726 726 }
+1
tools/perf/util/evsel.c
··· 273 273 struct perf_event_attr attr = { 274 274 .type = PERF_TYPE_HARDWARE, 275 275 .config = PERF_COUNT_HW_CPU_CYCLES, 276 + .exclude_kernel = 1, 276 277 }; 277 278 struct perf_evsel *evsel; 278 279
+1 -1
tools/perf/util/unwind-libunwind.c
··· 50 50 51 51 if (!ops) { 52 52 pr_err("unwind: target platform=%s is not supported\n", arch); 53 - return -1; 53 + return 0; 54 54 } 55 55 out_register: 56 56 unwind__register_ops(thread, ops);