diff options
Diffstat (limited to 'arch/x86_64/vdso/vgetcpu.c')
-rw-r--r-- | arch/x86_64/vdso/vgetcpu.c | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/arch/x86_64/vdso/vgetcpu.c b/arch/x86_64/vdso/vgetcpu.c new file mode 100644 index 000000000000..91f6e85d0fc2 --- /dev/null +++ b/arch/x86_64/vdso/vgetcpu.c | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Copyright 2006 Andi Kleen, SUSE Labs. | ||
3 | * Subject to the GNU Public License, v.2 | ||
4 | * | ||
5 | * Fast user context implementation of getcpu() | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/getcpu.h> | ||
10 | #include <linux/jiffies.h> | ||
11 | #include <linux/time.h> | ||
12 | #include <asm/vsyscall.h> | ||
13 | #include <asm/vgtod.h> | ||
14 | #include "vextern.h" | ||
15 | |||
16 | long __vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) | ||
17 | { | ||
18 | unsigned int dummy, p; | ||
19 | unsigned long j = 0; | ||
20 | |||
21 | /* Fast cache - only recompute value once per jiffies and avoid | ||
22 | relatively costly rdtscp/cpuid otherwise. | ||
23 | This works because the scheduler usually keeps the process | ||
24 | on the same CPU and this syscall doesn't guarantee its | ||
25 | results anyways. | ||
26 | We do this here because otherwise user space would do it on | ||
27 | its own in a likely inferior way (no access to jiffies). | ||
28 | If you don't like it pass NULL. */ | ||
29 | if (tcache && tcache->blob[0] == (j = *vdso_jiffies)) { | ||
30 | p = tcache->blob[1]; | ||
31 | } else if (*vdso_vgetcpu_mode == VGETCPU_RDTSCP) { | ||
32 | /* Load per CPU data from RDTSCP */ | ||
33 | rdtscp(dummy, dummy, p); | ||
34 | } else { | ||
35 | /* Load per CPU data from GDT */ | ||
36 | asm("lsl %1,%0" : "=r" (p) : "r" (__PER_CPU_SEG)); | ||
37 | } | ||
38 | if (tcache) { | ||
39 | tcache->blob[0] = j; | ||
40 | tcache->blob[1] = p; | ||
41 | } | ||
42 | if (cpu) | ||
43 | *cpu = p & 0xfff; | ||
44 | if (node) | ||
45 | *node = p >> 12; | ||
46 | return 0; | ||
47 | } | ||
48 | |||
49 | long getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *tcache) | ||
50 | __attribute__((weak, alias("__vdso_getcpu"))); | ||