Here are some numbers:
read cr2 best: 11 av: 11.12
write cr2 cr2 best: 61 av: 64.42
read cr2 best: 11 av: 11.12
write cr2 cr2 best: 61 av: 65.01
read stk best: 10 av: 11.03
write cr2 stk best: 61 av: 64.95
read stk best: 10 av: 11.03
write cr2 stk best: 61 av: 65.23
Which come from insmod of the below two modules. I didn't test writing to
the stack register, but I expect it's similarly expensive as it affects the
call return stack and other behind the scenes dependancies. Suffice it to
say that reading %cr2 is essentially free on my box (athlon mp). Maybe
we should use it as a pointer into a per-cpu area to avoid writing it?
-ben
----teststk_k.c----
#define USE_STK 1
#include "testcr2_k.c"
----testcr2_k.c----
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/errno.h>
#include <linux/init.h>
static inline long long rdtsc(void)
{
unsigned int low,high;
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));
return low + (((long long)high)<<32);
}
long dummy;
long doit(void)
{
long long start, end;
long val;
start = rdtsc();
#ifdef USE_STK
#define WHICH "stk"
__asm__ __volatile__(
"movl $0x0003c000,%%eax \n" // 4 bits at bit 14
"movl $-16384,%%edx \n" // remove low 14 bits
"andl %%esp,%%eax \n"
"andl %%esp,%%edx \n"
"shrl $7,%%eax \n" // color it by 128 bytes
"addl %%edx,%%eax \n"
: "=a" (val) :: "edx");
#else
#define WHICH "cr2"
__asm__ __volatile__("movl %%cr2,%0" : "=r" (val));
#endif
val += 100;
dummy = val;
end = rdtsc();
return end - start;
}
long doit2(void)
{
long long start, end;
long val;
start = rdtsc();
val = dummy;
__asm__ __volatile__("movl %0,%%cr2" : "=r" (val));
end = rdtsc();
return end - start;
}
int test_init (void)
{
long min = 1000000000, av = 0;
int i;
for (i=0; i<100; i++) {
long dur = doit();
if (dur < min)
min = dur;
av += dur;
}
printk("read " WHICH " best: %ld av: %ld.%02ld\n", min, av / 100, av % 100);
min = 10000000;
av = 0;
for (i=0; i<100; i++) {
long dur = doit2();
if (dur < min)
min = dur;
av += dur;
}
printk("write cr2 " WHICH " best: %ld av: %ld.%02ld\n", min, av / 100, av % 100);
return -ENODEV;
}
void test_exit(void)
{
return;
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");
---snip---
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/