xref: /linux/arch/loongarch/vdso/vgetcpu.c (revision aa5e65dc0818bbf676bf06927368ec46867778fd)
1dce6098bSHuacai Chen // SPDX-License-Identifier: GPL-2.0-only
2dce6098bSHuacai Chen /*
3dce6098bSHuacai Chen  * Fast user context implementation of getcpu()
4dce6098bSHuacai Chen  */
5dce6098bSHuacai Chen 
6dce6098bSHuacai Chen #include <asm/vdso.h>
7dce6098bSHuacai Chen #include <linux/getcpu.h>
8dce6098bSHuacai Chen 
9dce6098bSHuacai Chen static __always_inline int read_cpu_id(void)
10dce6098bSHuacai Chen {
11dce6098bSHuacai Chen 	int cpu_id;
12dce6098bSHuacai Chen 
13dce6098bSHuacai Chen 	__asm__ __volatile__(
14dce6098bSHuacai Chen 	"	rdtime.d $zero, %0\n"
15dce6098bSHuacai Chen 	: "=r" (cpu_id)
16dce6098bSHuacai Chen 	:
17dce6098bSHuacai Chen 	: "memory");
18dce6098bSHuacai Chen 
19dce6098bSHuacai Chen 	return cpu_id;
20dce6098bSHuacai Chen }
21dce6098bSHuacai Chen 
22dce6098bSHuacai Chen static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
23dce6098bSHuacai Chen {
24*aa5e65dcSTiezhu Yang 	return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE);
25dce6098bSHuacai Chen }
26dce6098bSHuacai Chen 
2784e76206SHuacai Chen extern
2884e76206SHuacai Chen int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused);
29dce6098bSHuacai Chen int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused)
30dce6098bSHuacai Chen {
31dce6098bSHuacai Chen 	int cpu_id;
32dce6098bSHuacai Chen 	const struct vdso_pcpu_data *data;
33dce6098bSHuacai Chen 
34dce6098bSHuacai Chen 	cpu_id = read_cpu_id();
35dce6098bSHuacai Chen 
36dce6098bSHuacai Chen 	if (cpu)
37dce6098bSHuacai Chen 		*cpu = cpu_id;
38dce6098bSHuacai Chen 
39dce6098bSHuacai Chen 	if (node) {
40dce6098bSHuacai Chen 		data = get_pcpu_data();
41dce6098bSHuacai Chen 		*node = data[cpu_id].node;
42dce6098bSHuacai Chen 	}
43dce6098bSHuacai Chen 
44dce6098bSHuacai Chen 	return 0;
45dce6098bSHuacai Chen }
46