Re: Getting interrupt every million cache misses

From: Peter Zijlstra
Date: Thu Oct 27 2016 - 10:37:40 EST


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);
}
}