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