lkml.org 
[lkml]   [2010]   [Jul]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 02/21] mce: Add persistent events
    Date
    From: Borislav Petkov <borislav.petkov@amd.com>

    Add the required glue to enable the mce_record tracepoint on boot thus
    simulating a persistent event with allocated buffers. Userspace daemon
    will hook into it later when booting is done.

    Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
    ---
    arch/x86/kernel/cpu/mcheck/mce.c | 89 ++++++++++++++++++++++++++++++++++++++
    1 files changed, 89 insertions(+), 0 deletions(-)

    diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
    index 18cc425..42d2808 100644
    --- a/arch/x86/kernel/cpu/mcheck/mce.c
    +++ b/arch/x86/kernel/cpu/mcheck/mce.c
    @@ -95,6 +95,7 @@ static char *mce_helper_argv[2] = { mce_helper, NULL };

    static DECLARE_WAIT_QUEUE_HEAD(mce_wait);
    static DEFINE_PER_CPU(struct mce, mces_seen);
    +static DEFINE_PER_CPU(struct perf_event *, mce_event);
    static int cpu_missing;

    /*
    @@ -2063,6 +2064,91 @@ static void __cpuinit mce_reenable_cpu(void *h)
    }
    }

    +struct perf_event_attr pattr = {
    + .type = PERF_TYPE_TRACEPOINT,
    + .size = sizeof(pattr),
    + .sample_type = PERF_SAMPLE_RAW | PERF_SAMPLE_CPU | PERF_SAMPLE_TIME,
    +};
    +
    +static int mcheck_enable_perf_event_on_cpu(int cpu)
    +{
    + struct perf_event *event;
    + struct perf_buffer *buffer;
    +
    + if (!event_mce_record.event.type) {
    + printk(KERN_ERR "mce: Tracepoint not enumerated yet!\n");
    + return -EINVAL;
    + }
    + pattr.config = event_mce_record.event.type;
    + pattr.sample_period = ULLONG_MAX;
    +
    + event = perf_event_create_kernel_counter(&pattr, cpu, -1, NULL);
    + if (IS_ERR(event))
    + return -EINVAL;
    +
    + buffer = perf_buffer_alloc(128, 0, cpu, 0);
    + if (IS_ERR(buffer))
    + goto err;
    +
    + rcu_assign_pointer(event->buffer, buffer);
    + per_cpu(mce_event, cpu) = event;
    +
    + perf_event_enable(event);
    +
    + return 0;
    +
    +err:
    + perf_event_release_kernel(event);
    + return -EINVAL;
    +}
    +
    +static void mcheck_disable_perf_event_on_cpu(int cpu)
    +{
    + struct perf_event *event = per_cpu(mce_event, cpu);
    +
    + if (!event)
    + return;
    +
    + perf_event_disable(event);
    +
    + if (event->buffer) {
    + perf_buffer_put(event->buffer);
    + rcu_assign_pointer(event->buffer, NULL);
    + }
    +
    + per_cpu(mce_event, cpu) = NULL;
    +
    + perf_event_release_kernel(event);
    +}
    +
    +static int mcheck_init_perf_event(void)
    +{
    + int cpu, i, err = 0;
    +
    + get_online_cpus();
    +
    + for_each_online_cpu(cpu) {
    + err = mcheck_enable_perf_event_on_cpu(cpu);
    + if (err) {
    + printk(KERN_ERR "mce: error initializing mce tracepoint"
    + " on cpu %d\n", cpu);
    +
    + for (i = cpu - 1; i >= 0; i--)
    + mcheck_disable_perf_event_on_cpu(i);
    + }
    + }
    +
    + put_online_cpus();
    +
    + return err;
    +}
    +
    +/*
    + * This has to run after after event_trace_init() which is an fs_initcall()
    + * currently
    + */
    +device_initcall(mcheck_init_perf_event);
    +
    /* Get notified when a cpu comes on/off. Be hotplug friendly. */
    static int __cpuinit
    mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
    @@ -2076,6 +2162,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
    mce_create_device(cpu);
    if (threshold_cpu_callback)
    threshold_cpu_callback(action, cpu);
    + mcheck_enable_perf_event_on_cpu(cpu);
    break;
    case CPU_DEAD:
    case CPU_DEAD_FROZEN:
    @@ -2087,6 +2174,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
    case CPU_DOWN_PREPARE_FROZEN:
    del_timer_sync(t);
    smp_call_function_single(cpu, mce_disable_cpu, &action, 1);
    + mcheck_disable_perf_event_on_cpu(cpu);
    break;
    case CPU_DOWN_FAILED:
    case CPU_DOWN_FAILED_FROZEN:
    @@ -2096,6 +2184,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu)
    add_timer_on(t, cpu);
    }
    smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
    + mcheck_enable_perf_event_on_cpu(cpu);
    break;
    case CPU_POST_DEAD:
    /* intentionally ignoring frozen here */
    --
    1.7.1


    \
     
     \ /
      Last update: 2010-07-01 17:57    [W:0.031 / U:30.368 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site