[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20161027093334.GK3102@twins.programming.kicks-ass.net>
Date: Thu, 27 Oct 2016 11:33:34 +0200
From: Peter Zijlstra <peterz@...radead.org>
To: Pavel Machek <pavel@....cz>
Cc: acme@...hat.com, kernel list <linux-kernel@...r.kernel.org>,
mingo@...hat.com, alexander.shishkin@...ux.intel.com
Subject: Re: Getting interrupt every million cache misses
On Thu, Oct 27, 2016 at 11:11:04AM +0200, Pavel Machek wrote:
> How to work around rowhammer, break my system _and_ make kernel perf
> maintainers scream at the same time: (:-) )
>
> I think I got the place now. Let me try...
Lol ;-)
>
> diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
> index d31735f..ce83f5e 100644
> --- a/arch/x86/events/core.c
> +++ b/arch/x86/events/core.c
> @@ -1495,6 +1495,11 @@ perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs)
>
> perf_sample_event_took(finish_clock - start_clock);
>
> + /* Here */
> + {
> + udelay(58000);
> + }
> +
> return ret;
> }
> NOKPROBE_SYMBOL(perf_event_nmi_handler);
Like you guess, not quite ;-)
I think you want to register a custom overflow handler with your event.
So you get something like:
struct perf_event_attr rh_attr = {
.type = PERF_TYPE_HARDWARE,
.config = PERF_COUNT_HW_CACHE_MISSES,
.size = sizeof(struct perf_event_attr),
.pinned = 1,
.sample_period = 1000000,
};
static DEFINE_PER_CPU(struct perf_event *, rh_event);
static DEFINE_PER_CPU(u64, rh_timestamp);
static void rh_overflow(struct perf_event *event, struct perf_sample_data *data, struct pt_regs *regs)
{
u64 *ts = this_cpu_ptr(&rh_timestamp); /* this is NMI context */
u64 now = ktime_get_mono_fast_ns();
s64 delta = now - *ts;
*ts = now;
if (delta > 64 * NSEC_PER_USEC)
udelay(58000);
}
__init int my_module_init()
{
int cpu;
/* XXX borken vs hotplug */
for_each_online_cpu(cpu) {
struct perf_event *event = per_cpu(event, cpu);
event = perf_event_create_kernel_counter(&rh_attr, cpu, NULL, rh_overflow, NULL);
if (!event)
/* meh */
;
}
}
__exit void my_module_exit()
{
int cpu;
for_each_online_cpu(cpu) {
struct perf_event *event = per_cpu(event, cpu);
if (event)
perf_event_release_kernel(event);
}
}
Powered by blists - more mailing lists