18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Fast user context implementation of getcpu()
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <asm/vdso.h>
78c2ecf20Sopenharmony_ci#include <linux/getcpu.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistatic __always_inline int read_cpu_id(void)
108c2ecf20Sopenharmony_ci{
118c2ecf20Sopenharmony_ci	int cpu_id;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	__asm__ __volatile__(
148c2ecf20Sopenharmony_ci	"	rdtime.d $zero, %0\n"
158c2ecf20Sopenharmony_ci	: "=r" (cpu_id)
168c2ecf20Sopenharmony_ci	:
178c2ecf20Sopenharmony_ci	: "memory");
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci	return cpu_id;
208c2ecf20Sopenharmony_ci}
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_cistatic __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
238c2ecf20Sopenharmony_ci{
248c2ecf20Sopenharmony_ci	return (struct vdso_pcpu_data *)(get_vdso_data() + VVAR_LOONGARCH_PAGES_START * PAGE_SIZE);
258c2ecf20Sopenharmony_ci}
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciint __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	int cpu_id;
308c2ecf20Sopenharmony_ci	const struct vdso_pcpu_data *data;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	cpu_id = read_cpu_id();
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	if (cpu)
358c2ecf20Sopenharmony_ci		*cpu = cpu_id;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	if (node) {
388c2ecf20Sopenharmony_ci		data = get_pcpu_data();
398c2ecf20Sopenharmony_ci		*node = data[cpu_id].node;
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	return 0;
438c2ecf20Sopenharmony_ci}
44