• Thomas Richter's avatar
    perf annotate: Fix s390 gap between kernel end and module start · b9c0a649
    Thomas Richter authored
    During execution of command 'perf top' the error message:
    
       Not enough memory for annotating '__irf_end' symbol!)
    
    is emitted from this call sequence:
      __cmd_top
        perf_top__mmap_read
          perf_top__mmap_read_idx
            perf_event__process_sample
              hist_entry_iter__add
                hist_iter__top_callback
                  perf_top__record_precise_ip
                    hist_entry__inc_addr_samples
                      symbol__inc_addr_samples
                        symbol__get_annotation
                          symbol__alloc_hist
    
    In this function the size of symbol __irf_end is calculated. The size of
    a symbol is the difference between its start and end address.
    
    When the symbol was read the first time, its start and end was set to:
    
       symbol__new: __irf_end 0xe954d0-0xe954d0
    
    which is correct and maps with /proc/kallsyms:
    
       root@s8360046:~/linux-4.15.0/tools/perf# fgrep _irf_end /proc/kallsyms
       0000000000e954d0 t __irf_end
       root@s8360046:~/linux-4.15.0/tools/perf#
    
    In function symbol__alloc_hist() the end of symbol __irf_end is
    
      symbol__alloc_hist sym:__irf_end start:0xe954d0 end:0x3ff80045a8
    
    which is identical with the first module entry in /proc/kallsyms
    
    This results in a symbol size of __irf_req for histogram analyses of
    70334140059072 bytes and a malloc() for this requested size fails.
    
    The root cause of this is function
      __dso__load_kallsyms()
      +-> symbols__fixup_end()
    
    Function symbols__fixup_end() enlarges the last symbol in the kallsyms
    map:
    
       # fgrep __irf_end /proc/kallsyms
       0000000000e954d0 t __irf_end
       #
    
    to the start address of the first module:
       # cat /proc/kallsyms | sort  | egrep ' [tT] '
       ....
       0000000000e952d0 T __security_initcall_end
       0000000000e954d0 T __initramfs_size
       0000000000e954d0 t __irf_end
       000003ff800045a8 T fc_get_event_number       [scsi_transport_fc]
       000003ff800045d0 t store_fc_vport_disable    [scsi_transport_fc]
       000003ff800046a8 T scsi_is_fc_rport  [scsi_transport_fc]
       000003ff800046d0 t fc_target_setup   [scsi_transport_fc]
    
    On s390 the kernel is located around memory address 0x200, 0x10000 or
    0x100000, depending on linux version. Modules however start some- where
    around 0x3ff xxxx xxxx.
    
    This is different than x86 and produces a large gap for which histogram
    allocation fails.
    
    Fix this by detecting the kernel's last symbol and do no adjustment for
    it. Introduce a weak function and handle s390 specifics.
    Reported-by: default avatarKlaus Theurich <klaus.theurich@de.ibm.com>
    Signed-off-by: default avatarThomas Richter <tmricht@linux.ibm.com>
    Acked-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
    Cc: Hendrik Brueckner <brueckner@linux.ibm.com>
    Cc: Vasily Gorbik <gor@linux.ibm.com>
    Cc: stable@vger.kernel.org
    Link: http://lkml.kernel.org/r/20190724122703.3996-2-tmricht@linux.ibm.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
    b9c0a649
machine.c 1.7 KB