diff options
author | Huacai Chen <chenhuacai@loongson.cn> | 2022-08-06 15:19:33 +0800 |
---|---|---|
committer | Huacai Chen <chenhuacai@loongson.cn> | 2022-08-12 13:10:11 +0800 |
commit | dce6098b22d58e5b646b1c67174c53f5a6a05605 (patch) | |
tree | 0658f8ef3b5efcf58a386100c02b1930bbd9eea0 /arch/loongarch/vdso/vgetcpu.c | |
parent | 57fc7323a8e7c2e7c1d5795ab63cb3ffea3cfdfb (diff) |
LoongArch: Add vDSO syscall __vdso_getcpu()
We test 20 million times of getcpu(), the real syscall version take 25
seconds, while the vsyscall version take only 2.4 seconds.
Signed-off-by: Rui Wang <wangrui@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch/loongarch/vdso/vgetcpu.c')
-rw-r--r-- | arch/loongarch/vdso/vgetcpu.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/arch/loongarch/vdso/vgetcpu.c b/arch/loongarch/vdso/vgetcpu.c new file mode 100644 index 000000000000..43a0078e4418 --- /dev/null +++ b/arch/loongarch/vdso/vgetcpu.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Fast user context implementation of getcpu() + */ + +#include <asm/vdso.h> +#include <linux/getcpu.h> + +static __always_inline int read_cpu_id(void) +{ + int cpu_id; + + __asm__ __volatile__( + " rdtime.d $zero, %0\n" + : "=r" (cpu_id) + : + : "memory"); + + return cpu_id; +} + +static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void) +{ + return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE); +} + +int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused) +{ + int cpu_id; + const struct vdso_pcpu_data *data; + + cpu_id = read_cpu_id(); + + if (cpu) + *cpu = cpu_id; + + if (node) { + data = get_pcpu_data(); + *node = data[cpu_id].node; + } + + return 0; +} |