Skip to content

Commit

Permalink
ARM: kprobes: Add some benchmarking to test module
Browse files Browse the repository at this point in the history
These benchmarks show the basic speed of kprobes and verify the success
of optimisations done to the emulation of typical function entry
instructions (i.e. push/stmdb).

Signed-off-by: Jon Medhurst <tixy@yxit.co.uk>
Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
  • Loading branch information
Jon Medhurst committed Sep 20, 2011
1 parent 963780d commit ce5af3b
Showing 1 changed file with 161 additions and 0 deletions.
161 changes: 161 additions & 0 deletions arch/arm/kernel/kprobes-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@
#include "kprobes-test.h"


#define BENCHMARKING 1


/*
* Test basic API
*/
Expand Down Expand Up @@ -443,6 +446,157 @@ static int run_api_tests(long (*func)(long, long))
}


/*
* Benchmarking
*/

#if BENCHMARKING

static void __naked benchmark_nop(void)
{
__asm__ __volatile__ (
"nop \n\t"
"bx lr"
);
}

#ifdef CONFIG_THUMB2_KERNEL
#define wide ".w"
#else
#define wide
#endif

static void __naked benchmark_pushpop1(void)
{
__asm__ __volatile__ (
"stmdb"wide" sp!, {r3-r11,lr} \n\t"
"ldmia"wide" sp!, {r3-r11,pc}"
);
}

static void __naked benchmark_pushpop2(void)
{
__asm__ __volatile__ (
"stmdb"wide" sp!, {r0-r8,lr} \n\t"
"ldmia"wide" sp!, {r0-r8,pc}"
);
}

static void __naked benchmark_pushpop3(void)
{
__asm__ __volatile__ (
"stmdb"wide" sp!, {r4,lr} \n\t"
"ldmia"wide" sp!, {r4,pc}"
);
}

static void __naked benchmark_pushpop4(void)
{
__asm__ __volatile__ (
"stmdb"wide" sp!, {r0,lr} \n\t"
"ldmia"wide" sp!, {r0,pc}"
);
}


#ifdef CONFIG_THUMB2_KERNEL

static void __naked benchmark_pushpop_thumb(void)
{
__asm__ __volatile__ (
"push.n {r0-r7,lr} \n\t"
"pop.n {r0-r7,pc}"
);
}

#endif

static int __kprobes
benchmark_pre_handler(struct kprobe *p, struct pt_regs *regs)
{
return 0;
}

static int benchmark(void(*fn)(void))
{
unsigned n, i, t, t0;

for (n = 1000; ; n *= 2) {
t0 = sched_clock();
for (i = n; i > 0; --i)
fn();
t = sched_clock() - t0;
if (t >= 250000000)
break; /* Stop once we took more than 0.25 seconds */
}
return t / n; /* Time for one iteration in nanoseconds */
};

static int kprobe_benchmark(void(*fn)(void), unsigned offset)
{
struct kprobe k = {
.addr = (kprobe_opcode_t *)((uintptr_t)fn + offset),
.pre_handler = benchmark_pre_handler,
};

int ret = register_kprobe(&k);
if (ret < 0) {
pr_err("FAIL: register_kprobe failed with %d\n", ret);
return ret;
}

ret = benchmark(fn);

unregister_kprobe(&k);
return ret;
};

struct benchmarks {
void (*fn)(void);
unsigned offset;
const char *title;
};

static int run_benchmarks(void)
{
int ret;
struct benchmarks list[] = {
{&benchmark_nop, 0, "nop"},
/*
* benchmark_pushpop{1,3} will have the optimised
* instruction emulation, whilst benchmark_pushpop{2,4} will
* be the equivalent unoptimised instructions.
*/
{&benchmark_pushpop1, 0, "stmdb sp!, {r3-r11,lr}"},
{&benchmark_pushpop1, 4, "ldmia sp!, {r3-r11,pc}"},
{&benchmark_pushpop2, 0, "stmdb sp!, {r0-r8,lr}"},
{&benchmark_pushpop2, 4, "ldmia sp!, {r0-r8,pc}"},
{&benchmark_pushpop3, 0, "stmdb sp!, {r4,lr}"},
{&benchmark_pushpop3, 4, "ldmia sp!, {r4,pc}"},
{&benchmark_pushpop4, 0, "stmdb sp!, {r0,lr}"},
{&benchmark_pushpop4, 4, "ldmia sp!, {r0,pc}"},
#ifdef CONFIG_THUMB2_KERNEL
{&benchmark_pushpop_thumb, 0, "push.n {r0-r7,lr}"},
{&benchmark_pushpop_thumb, 2, "pop.n {r0-r7,pc}"},
#endif
{0}
};

struct benchmarks *b;
for (b = list; b->fn; ++b) {
ret = kprobe_benchmark(b->fn, b->offset);
if (ret < 0)
return ret;
pr_info(" %dns for kprobe %s\n", ret, b->title);
}

pr_info("\n");
return 0;
}

#endif /* BENCHMARKING */


/*
* Decoding table self-consistency tests
*/
Expand Down Expand Up @@ -1526,6 +1680,13 @@ static int __init run_all_tests(void)
goto out;
}

#if BENCHMARKING
pr_info("Benchmarks\n");
ret = run_benchmarks();
if (ret)
goto out;
#endif

#if __LINUX_ARM_ARCH__ >= 7
/* We are able to run all test cases so coverage should be complete */
if (coverage_fail) {
Expand Down

0 comments on commit ce5af3b

Please sign in to comment.