Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 26 Aug 2018 18:25:21 +0000 (11:25 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 26 Aug 2018 18:25:21 +0000 (11:25 -0700)
Pull perf updates from Thomas Gleixner:
 "Kernel:
   - Improve kallsyms coverage
   - Add x86 entry trampolines to kcore
   - Fix ARM SPE handling
   - Correct PPC event post processing

  Tools:
   - Make the build system more robust
   - Small fixes and enhancements all over the place
   - Update kernel ABI header copies
   - Preparatory work for converting libtraceevnt to a shared library
   - License cleanups"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (100 commits)
  tools arch: Update arch/x86/lib/memcpy_64.S copy used in 'perf bench mem memcpy'
  tools arch x86: Update tools's copy of cpufeatures.h
  perf python: Fix pyrf_evlist__read_on_cpu() interface
  perf mmap: Store real cpu number in 'struct perf_mmap'
  perf tools: Remove ext from struct kmod_path
  perf tools: Add gzip_is_compressed function
  perf tools: Add lzma_is_compressed function
  perf tools: Add is_compressed callback to compressions array
  perf tools: Move the temp file processing into decompress_kmodule
  perf tools: Use compression id in decompress_kmodule()
  perf tools: Store compression id into struct dso
  perf tools: Add compression id into 'struct kmod_path'
  perf tools: Make is_supported_compression() static
  perf tools: Make decompress_to_file() function static
  perf tools: Get rid of dso__needs_decompress() call in __open_dso()
  perf tools: Get rid of dso__needs_decompress() call in symbol__disassemble()
  perf tools: Get rid of dso__needs_decompress() call in read_object_code()
  tools lib traceevent: Change to SPDX License format
  perf llvm: Allow passing options to llc in addition to clang
  perf parser: Improve error message for PMU address filters
  ...

1  2 
fs/proc/kcore.c
include/linux/kcore.h
tools/arch/x86/include/asm/cpufeatures.h

diff --cc fs/proc/kcore.c
@@@ -291,148 -448,53 +291,151 @@@ static ssize_
  read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)
  {
        char *buf = file->private_data;
 -      ssize_t acc = 0;
 -      size_t size, tsz;
 -      size_t elf_buflen;
 +      size_t phdrs_offset, notes_offset, data_offset;
 +      size_t phdrs_len, notes_len;
 +      struct kcore_list *m;
 +      size_t tsz;
        int nphdr;
        unsigned long start;
 +      size_t orig_buflen = buflen;
 +      int ret = 0;
  
 -      read_lock(&kclist_lock);
 -      size = get_kcore_size(&nphdr, &elf_buflen);
 +      down_read(&kclist_lock);
 +
 +      get_kcore_size(&nphdr, &phdrs_len, &notes_len, &data_offset);
 +      phdrs_offset = sizeof(struct elfhdr);
 +      notes_offset = phdrs_offset + phdrs_len;
 +
 +      /* ELF file header. */
 +      if (buflen && *fpos < sizeof(struct elfhdr)) {
 +              struct elfhdr ehdr = {
 +                      .e_ident = {
 +                              [EI_MAG0] = ELFMAG0,
 +                              [EI_MAG1] = ELFMAG1,
 +                              [EI_MAG2] = ELFMAG2,
 +                              [EI_MAG3] = ELFMAG3,
 +                              [EI_CLASS] = ELF_CLASS,
 +                              [EI_DATA] = ELF_DATA,
 +                              [EI_VERSION] = EV_CURRENT,
 +                              [EI_OSABI] = ELF_OSABI,
 +                      },
 +                      .e_type = ET_CORE,
 +                      .e_machine = ELF_ARCH,
 +                      .e_version = EV_CURRENT,
 +                      .e_phoff = sizeof(struct elfhdr),
 +                      .e_flags = ELF_CORE_EFLAGS,
 +                      .e_ehsize = sizeof(struct elfhdr),
 +                      .e_phentsize = sizeof(struct elf_phdr),
 +                      .e_phnum = nphdr,
 +              };
 +
 +              tsz = min_t(size_t, buflen, sizeof(struct elfhdr) - *fpos);
 +              if (copy_to_user(buffer, (char *)&ehdr + *fpos, tsz)) {
 +                      ret = -EFAULT;
 +                      goto out;
 +              }
  
 -      if (buflen == 0 || *fpos >= size) {
 -              read_unlock(&kclist_lock);
 -              return 0;
 +              buffer += tsz;
 +              buflen -= tsz;
 +              *fpos += tsz;
        }
  
 -      /* trim buflen to not go beyond EOF */
 -      if (buflen > size - *fpos)
 -              buflen = size - *fpos;
 -
 -      /* construct an ELF core header if we'll need some of it */
 -      if (*fpos < elf_buflen) {
 -              char * elf_buf;
 -
 -              tsz = elf_buflen - *fpos;
 -              if (buflen < tsz)
 -                      tsz = buflen;
 -              elf_buf = kzalloc(elf_buflen, GFP_ATOMIC);
 -              if (!elf_buf) {
 -                      read_unlock(&kclist_lock);
 -                      return -ENOMEM;
 +      /* ELF program headers. */
 +      if (buflen && *fpos < phdrs_offset + phdrs_len) {
 +              struct elf_phdr *phdrs, *phdr;
 +
 +              phdrs = kzalloc(phdrs_len, GFP_KERNEL);
 +              if (!phdrs) {
 +                      ret = -ENOMEM;
 +                      goto out;
                }
 -              elf_kcore_store_hdr(elf_buf, nphdr, elf_buflen);
 -              read_unlock(&kclist_lock);
 -              if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
 -                      kfree(elf_buf);
 -                      return -EFAULT;
 +
 +              phdrs[0].p_type = PT_NOTE;
 +              phdrs[0].p_offset = notes_offset;
 +              phdrs[0].p_filesz = notes_len;
 +
 +              phdr = &phdrs[1];
 +              list_for_each_entry(m, &kclist_head, list) {
 +                      phdr->p_type = PT_LOAD;
 +                      phdr->p_flags = PF_R | PF_W | PF_X;
 +                      phdr->p_offset = kc_vaddr_to_offset(m->addr) + data_offset;
-                       phdr->p_vaddr = (size_t)m->addr;
-                       if (m->type == KCORE_RAM)
++                      if (m->type == KCORE_REMAP)
++                              phdr->p_vaddr = (size_t)m->vaddr;
++                      else
++                              phdr->p_vaddr = (size_t)m->addr;
++                      if (m->type == KCORE_RAM || m->type == KCORE_REMAP)
 +                              phdr->p_paddr = __pa(m->addr);
 +                      else if (m->type == KCORE_TEXT)
 +                              phdr->p_paddr = __pa_symbol(m->addr);
 +                      else
 +                              phdr->p_paddr = (elf_addr_t)-1;
 +                      phdr->p_filesz = phdr->p_memsz = m->size;
 +                      phdr->p_align = PAGE_SIZE;
 +                      phdr++;
                }
 -              kfree(elf_buf);
 +
 +              tsz = min_t(size_t, buflen, phdrs_offset + phdrs_len - *fpos);
 +              if (copy_to_user(buffer, (char *)phdrs + *fpos - phdrs_offset,
 +                               tsz)) {
 +                      kfree(phdrs);
 +                      ret = -EFAULT;
 +                      goto out;
 +              }
 +              kfree(phdrs);
 +
 +              buffer += tsz;
                buflen -= tsz;
                *fpos += tsz;
 -              buffer += tsz;
 -              acc += tsz;
 +      }
 +
 +      /* ELF note segment. */
 +      if (buflen && *fpos < notes_offset + notes_len) {
 +              struct elf_prstatus prstatus = {};
 +              struct elf_prpsinfo prpsinfo = {
 +                      .pr_sname = 'R',
 +                      .pr_fname = "vmlinux",
 +              };
 +              char *notes;
 +              size_t i = 0;
 +
 +              strlcpy(prpsinfo.pr_psargs, saved_command_line,
 +                      sizeof(prpsinfo.pr_psargs));
 +
 +              notes = kzalloc(notes_len, GFP_KERNEL);
 +              if (!notes) {
 +                      ret = -ENOMEM;
 +                      goto out;
 +              }
 +
 +              append_kcore_note(notes, &i, CORE_STR, NT_PRSTATUS, &prstatus,
 +                                sizeof(prstatus));
 +              append_kcore_note(notes, &i, CORE_STR, NT_PRPSINFO, &prpsinfo,
 +                                sizeof(prpsinfo));
 +              append_kcore_note(notes, &i, CORE_STR, NT_TASKSTRUCT, current,
 +                                arch_task_struct_size);
 +              /*
 +               * vmcoreinfo_size is mostly constant after init time, but it
 +               * can be changed by crash_save_vmcoreinfo(). Racing here with a
 +               * panic on another CPU before the machine goes down is insanely
 +               * unlikely, but it's better to not leave potential buffer
 +               * overflows lying around, regardless.
 +               */
 +              append_kcore_note(notes, &i, VMCOREINFO_NOTE_NAME, 0,
 +                                vmcoreinfo_data,
 +                                min(vmcoreinfo_size, notes_len - i));
 +
 +              tsz = min_t(size_t, buflen, notes_offset + notes_len - *fpos);
 +              if (copy_to_user(buffer, notes + *fpos - notes_offset, tsz)) {
 +                      kfree(notes);
 +                      ret = -EFAULT;
 +                      goto out;
 +              }
 +              kfree(notes);
  
 -              /* leave now if filled buffer already */
 -              if (buflen == 0)
 -                      return acc;
 -      } else
 -              read_unlock(&kclist_lock);
 +              buffer += tsz;
 +              buflen -= tsz;
 +              *fpos += tsz;
 +      }
  
        /*
         * Check to see if our file offset matches with any of
@@@ -35,7 -37,13 +37,13 @@@ struct vmcoredd_node 
  };
  
  #ifdef CONFIG_PROC_KCORE
 -extern void kclist_add(struct kcore_list *, void *, size_t, int type);
 +void __init kclist_add(struct kcore_list *, void *, size_t, int type);
+ static inline
+ void kclist_add_remap(struct kcore_list *m, void *addr, void *vaddr, size_t sz)
+ {
+       m->vaddr = (unsigned long)vaddr;
+       kclist_add(m, addr, sz, KCORE_REMAP);
+ }
  #else
  static inline
  void kclist_add(struct kcore_list *new, void *addr, size_t size, int type)
  #define X86_FEATURE_IBPB              ( 7*32+26) /* Indirect Branch Prediction Barrier */
  #define X86_FEATURE_STIBP             ( 7*32+27) /* Single Thread Indirect Branch Predictors */
  #define X86_FEATURE_ZEN                       ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
 -#define X86_FEATURE_IBRS_ENHANCED     ( 7*32+29) /* Enhanced IBRS */
 +#define X86_FEATURE_L1TF_PTEINV               ( 7*32+29) /* "" L1TF workaround PTE inversion */
++#define X86_FEATURE_IBRS_ENHANCED     ( 7*32+30) /* Enhanced IBRS */
  
  /* Virtualization flags: Linux defined, word 8 */
  #define X86_FEATURE_TPR_SHADOW                ( 8*32+ 0) /* Intel TPR Shadow */