162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __VDSO_HELPERS_H
362306a36Sopenharmony_ci#define __VDSO_HELPERS_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#ifndef __ASSEMBLY__
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <vdso/datapage.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistatic __always_inline u32 vdso_read_begin(const struct vdso_data *vd)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	u32 seq;
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci	while (unlikely((seq = READ_ONCE(vd->seq)) & 1))
1462306a36Sopenharmony_ci		cpu_relax();
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	smp_rmb();
1762306a36Sopenharmony_ci	return seq;
1862306a36Sopenharmony_ci}
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic __always_inline u32 vdso_read_retry(const struct vdso_data *vd,
2162306a36Sopenharmony_ci					   u32 start)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	u32 seq;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	smp_rmb();
2662306a36Sopenharmony_ci	seq = READ_ONCE(vd->seq);
2762306a36Sopenharmony_ci	return seq != start;
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic __always_inline void vdso_write_begin(struct vdso_data *vd)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	/*
3362306a36Sopenharmony_ci	 * WRITE_ONCE it is required otherwise the compiler can validly tear
3462306a36Sopenharmony_ci	 * updates to vd[x].seq and it is possible that the value seen by the
3562306a36Sopenharmony_ci	 * reader it is inconsistent.
3662306a36Sopenharmony_ci	 */
3762306a36Sopenharmony_ci	WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
3862306a36Sopenharmony_ci	WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
3962306a36Sopenharmony_ci	smp_wmb();
4062306a36Sopenharmony_ci}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_cistatic __always_inline void vdso_write_end(struct vdso_data *vd)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	smp_wmb();
4562306a36Sopenharmony_ci	/*
4662306a36Sopenharmony_ci	 * WRITE_ONCE it is required otherwise the compiler can validly tear
4762306a36Sopenharmony_ci	 * updates to vd[x].seq and it is possible that the value seen by the
4862306a36Sopenharmony_ci	 * reader it is inconsistent.
4962306a36Sopenharmony_ci	 */
5062306a36Sopenharmony_ci	WRITE_ONCE(vd[CS_HRES_COARSE].seq, vd[CS_HRES_COARSE].seq + 1);
5162306a36Sopenharmony_ci	WRITE_ONCE(vd[CS_RAW].seq, vd[CS_RAW].seq + 1);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#endif /* __VDSO_HELPERS_H */
57