lkml.org 
[lkml]   [2010]   [Apr]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 12/12] perf, x86: implement the ibs interrupt handler
    Date
    This patch implements code to handle ibs interrupts. If ibs data is
    available a raw perf_event data sample is created and sent back to the
    userland. Currently only the data is stored only in the raw data, but
    this could be extended in a later patch by generating generic event
    data such as the rip from the ibs sampling data.

    Signed-off-by: Robert Richter <robert.richter@amd.com>
    ---
    arch/x86/include/asm/msr-index.h | 3 ++
    arch/x86/kernel/cpu/perf_event_amd.c | 65 +++++++++++++++++++++++++++++++++-
    2 files changed, 67 insertions(+), 1 deletions(-)

    diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
    index bc473ac..a7e4aa5 100644
    --- a/arch/x86/include/asm/msr-index.h
    +++ b/arch/x86/include/asm/msr-index.h
    @@ -113,6 +113,7 @@
    #define MSR_AMD64_IBSFETCHCTL 0xc0011030
    #define MSR_AMD64_IBSFETCHLINAD 0xc0011031
    #define MSR_AMD64_IBSFETCHPHYSAD 0xc0011032
    +#define MSR_AMD64_IBSFETCH_SIZE 3
    #define MSR_AMD64_IBSOPCTL 0xc0011033
    #define MSR_AMD64_IBSOPRIP 0xc0011034
    #define MSR_AMD64_IBSOPDATA 0xc0011035
    @@ -120,7 +121,9 @@
    #define MSR_AMD64_IBSOPDATA3 0xc0011037
    #define MSR_AMD64_IBSDCLINAD 0xc0011038
    #define MSR_AMD64_IBSDCPHYSAD 0xc0011039
    +#define MSR_AMD64_IBSOP_SIZE 7
    #define MSR_AMD64_IBSCTL 0xc001103a
    +#define MSR_AMD64_IBS_SIZE_MAX MSR_AMD64_IBSOP_SIZE

    /* Fam 10h MSRs */
    #define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058
    diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c
    index 3dc327c..78b0b34 100644
    --- a/arch/x86/kernel/cpu/perf_event_amd.c
    +++ b/arch/x86/kernel/cpu/perf_event_amd.c
    @@ -283,6 +283,69 @@ static inline void __amd_pmu_enable_ibs_event(struct hw_perf_event *hwc)
    __x86_pmu_enable_event(hwc, IBS_OP_ENABLE);
    }

    +static int amd_pmu_check_ibs(int idx, unsigned int msr, u64 valid,
    + u64 reenable, int size, struct pt_regs *iregs)
    +{
    + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
    + struct perf_event *event = cpuc->events[idx];
    + struct perf_sample_data data;
    + struct perf_raw_record raw;
    + struct pt_regs regs;
    + u64 buffer[MSR_AMD64_IBS_SIZE_MAX];
    + u64 *buf = buffer;
    + int i;
    +
    + if (!test_bit(idx, cpuc->active_mask))
    + return 0;
    +
    + rdmsrl(msr++, *buf);
    + if (!(*buf++ & valid))
    + return 0;
    +
    + perf_sample_data_init(&data, 0);
    + if (event->attr.sample_type & PERF_SAMPLE_RAW) {
    + for (i = 1; i < size; i++)
    + rdmsrl(msr++, *buf++);
    + raw.size = sizeof(u64) * size;
    + raw.data = buffer;
    + data.raw = &raw;
    + }
    +
    + regs = *iregs; /* later: update ip from ibs sample */
    +
    + if (perf_event_overflow(event, 1, &data, &regs))
    + x86_pmu_stop(event);
    + else
    + __x86_pmu_enable_event(&event->hw, reenable);
    +
    + return 1;
    +}
    +
    +static int amd_pmu_handle_irq(struct pt_regs *regs)
    +{
    + int handled, handled2;
    +
    + handled = x86_pmu_handle_irq(regs);
    +
    + if (!x86_pmu.ibs)
    + return handled;
    +
    + handled2 = 0;
    + handled2 += amd_pmu_check_ibs(X86_PMC_IDX_SPECIAL_IBS_FETCH,
    + MSR_AMD64_IBSFETCHCTL, IBS_FETCH_VAL,
    + IBS_FETCH_ENABLE, MSR_AMD64_IBSFETCH_SIZE,
    + regs);
    + handled2 += amd_pmu_check_ibs(X86_PMC_IDX_SPECIAL_IBS_OP,
    + MSR_AMD64_IBSOPCTL, IBS_OP_VAL,
    + IBS_OP_ENABLE, MSR_AMD64_IBSOP_SIZE,
    + regs);
    +
    + if (handled2)
    + inc_irq_stat(apic_perf_irqs);
    +
    + return (handled || handled2);
    +}
    +
    static void amd_pmu_disable_all(void)
    {
    x86_pmu_disable_all();
    @@ -608,7 +671,7 @@ static void amd_pmu_cpu_dead(int cpu)

    static __initconst const struct x86_pmu amd_pmu = {
    .name = "AMD",
    - .handle_irq = x86_pmu_handle_irq,
    + .handle_irq = amd_pmu_handle_irq,
    .disable_all = amd_pmu_disable_all,
    .enable_all = amd_pmu_enable_all,
    .enable = amd_pmu_enable_event,
    --
    1.7.0.3



    \
     
     \ /
      Last update: 2010-04-13 22:29    [W:0.029 / U:60.488 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site