lkml.org 
[lkml]   [2019]   [Nov]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 176/211] ARC: perf: Accommodate big-endian CPU
    Date
    From: Alexey Brodkin <Alexey.Brodkin@synopsys.com>

    commit 5effc09c4907901f0e71e68e5f2e14211d9a203f upstream.

    8-letter strings representing ARC perf events are stores in two
    32-bit registers as ASCII characters like that: "IJMP", "IALL", "IJMPTAK" etc.

    And the same order of bytes in the word is used regardless CPU endianness.

    Which means in case of big-endian CPU core we need to swap bytes to get
    the same order as if it was on little-endian CPU.

    Otherwise we're seeing the following error message on boot:
    ------------------------->8----------------------
    ARC perf : 8 counters (32 bits), 40 conditions, [overflow IRQ support]
    sysfs: cannot create duplicate filename '/devices/arc_pct/events/pmji'
    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.2.18 #3
    Stack Trace:
    arc_unwind_core+0xd4/0xfc
    dump_stack+0x64/0x80
    sysfs_warn_dup+0x46/0x58
    sysfs_add_file_mode_ns+0xb2/0x168
    create_files+0x70/0x2a0
    ------------[ cut here ]------------
    WARNING: CPU: 0 PID: 1 at kernel/events/core.c:12144 perf_event_sysfs_init+0x70/0xa0
    Failed to register pmu: arc_pct, reason -17
    Modules linked in:
    CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.2.18 #3
    Stack Trace:
    arc_unwind_core+0xd4/0xfc
    dump_stack+0x64/0x80
    __warn+0x9c/0xd4
    warn_slowpath_fmt+0x22/0x2c
    perf_event_sysfs_init+0x70/0xa0
    ---[ end trace a75fb9a9837bd1ec ]---
    ------------------------->8----------------------

    What happens here we're trying to register more than one raw perf event
    with the same name "PMJI". Why? Because ARC perf events are 4 to 8 letters
    and encoded into two 32-bit words. In this particular case we deal with 2
    events:
    * "IJMP____" which counts all jump & branch instructions
    * "IJMPC___" which counts only conditional jumps & branches

    Those strings are split in two 32-bit words this way "IJMP" + "____" &
    "IJMP" + "C___" correspondingly. Now if we read them swapped due to CPU core
    being big-endian then we read "PMJI" + "____" & "PMJI" + "___C".

    And since we interpret read array of ASCII letters as a null-terminated string
    on big-endian CPU we end up with 2 events of the same name "PMJI".

    Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>



    ---
    arch/arc/kernel/perf_event.c | 4 ++--
    1 file changed, 2 insertions(+), 2 deletions(-)

    --- a/arch/arc/kernel/perf_event.c
    +++ b/arch/arc/kernel/perf_event.c
    @@ -488,8 +488,8 @@ static int arc_pmu_device_probe(struct p
    /* loop thru all available h/w condition indexes */
    for (j = 0; j < cc_bcr.c; j++) {
    write_aux_reg(ARC_REG_CC_INDEX, j);
    - cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
    - cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
    + cc_name.indiv.word0 = le32_to_cpu(read_aux_reg(ARC_REG_CC_NAME0));
    + cc_name.indiv.word1 = le32_to_cpu(read_aux_reg(ARC_REG_CC_NAME1));

    /* See if it has been mapped to a perf event_id */
    for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {

    \
     
     \ /
      Last update: 2019-11-27 22:33    [W:2.758 / U:0.696 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site