18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef __VDSO_HELPERS_H
38c2ecf20Sopenharmony_ci#define __VDSO_HELPERS_H
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <vdso/datapage.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_cistatic __always_inline u32 vdso_read_begin(const struct vdso_data *vd)
108c2ecf20Sopenharmony_ci{
118c2ecf20Sopenharmony_ci	u32 seq;
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci	while (unlikely((seq = READ_ONCE(vd->seq)) & 1))
148c2ecf20Sopenharmony_ci		cpu_relax();
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	smp_rmb();
178c2ecf20Sopenharmony_ci	return seq;
188c2ecf20Sopenharmony_ci}
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic __always_inline u32 vdso_read_retry(const struct vdso_data *vd,
218c2ecf20Sopenharmony_ci					   u32 start)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	u32 seq;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	smp_rmb();
268c2ecf20Sopenharmony_ci	seq = READ_ONCE(vd->seq);
278c2ecf20Sopenharmony_ci	return seq != start;
288c2ecf20Sopenharmony_ci}
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_cistatic __always_inline void vdso_write_begin(struct vdso_data *vd)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	/*
338c2ecf20Sopenharmony_ci	 * WRITE_ONCE it is required otherwise the compiler can validly tear
348c2ecf20Sopenharmony_ci	 * updates to vd[x].seq and it is possible that the value seen by the
358c2ecf20Sopenharmony_ci	 * reader it is inconsistent.
368c2ecf20Sopenharmony_ci	 */
378c2ecf20Sopenharmony_ci	WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
388c2ecf20Sopenharmony_ci	WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
398c2ecf20Sopenharmony_ci	smp_wmb();
408c2ecf20Sopenharmony_ci}
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_cistatic __always_inline void vdso_write_end(struct vdso_data *vd)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	smp_wmb();
458c2ecf20Sopenharmony_ci	/*
468c2ecf20Sopenharmony_ci	 * WRITE_ONCE it is required otherwise the compiler can validly tear
478c2ecf20Sopenharmony_ci	 * updates to vd[x].seq and it is possible that the value seen by the
488c2ecf20Sopenharmony_ci	 * reader it is inconsistent.
498c2ecf20Sopenharmony_ci	 */
508c2ecf20Sopenharmony_ci	WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
518c2ecf20Sopenharmony_ci	WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#endif /* __VDSO_HELPERS_H */
57