vdso.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. * Copyright (C) 2015 Imagination Technologies
  3. * Author: Alex Smith <alex.smith@imgtec.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. */
  10. #ifndef __ASM_VDSO_H
  11. #define __ASM_VDSO_H
  12. #include <linux/mm_types.h>
  13. #include <asm/barrier.h>
  14. /**
  15. * struct mips_vdso_image - Details of a VDSO image.
  16. * @data: Pointer to VDSO image data (page-aligned).
  17. * @size: Size of the VDSO image data (page-aligned).
  18. * @off_sigreturn: Offset of the sigreturn() trampoline.
  19. * @off_rt_sigreturn: Offset of the rt_sigreturn() trampoline.
  20. * @mapping: Special mapping structure.
  21. *
  22. * This structure contains details of a VDSO image, including the image data
  23. * and offsets of certain symbols required by the kernel. It is generated as
  24. * part of the VDSO build process, aside from the mapping page array, which is
  25. * populated at runtime.
  26. */
  27. struct mips_vdso_image {
  28. void *data;
  29. unsigned long size;
  30. unsigned long off_sigreturn;
  31. unsigned long off_rt_sigreturn;
  32. struct vm_special_mapping mapping;
  33. };
  34. /*
  35. * The following structures are auto-generated as part of the build for each
  36. * ABI by genvdso, see arch/mips/vdso/Makefile.
  37. */
  38. extern struct mips_vdso_image vdso_image;
  39. #ifdef CONFIG_MIPS32_O32
  40. extern struct mips_vdso_image vdso_image_o32;
  41. #endif
  42. #ifdef CONFIG_MIPS32_N32
  43. extern struct mips_vdso_image vdso_image_n32;
  44. #endif
  45. /**
  46. * union mips_vdso_data - Data provided by the kernel for the VDSO.
  47. * @xtime_sec: Current real time (seconds part).
  48. * @xtime_nsec: Current real time (nanoseconds part, shifted).
  49. * @wall_to_mono_sec: Wall-to-monotonic offset (seconds part).
  50. * @wall_to_mono_nsec: Wall-to-monotonic offset (nanoseconds part).
  51. * @seq_count: Counter to synchronise updates (odd = updating).
  52. * @cs_shift: Clocksource shift value.
  53. * @clock_mode: Clocksource to use for time functions.
  54. * @cs_mult: Clocksource multiplier value.
  55. * @cs_cycle_last: Clock cycle value at last update.
  56. * @cs_mask: Clocksource mask value.
  57. * @tz_minuteswest: Minutes west of Greenwich (from timezone).
  58. * @tz_dsttime: Type of DST correction (from timezone).
  59. *
  60. * This structure contains data needed by functions within the VDSO. It is
  61. * populated by the kernel and mapped read-only into user memory. The time
  62. * fields are mirrors of internal data from the timekeeping infrastructure.
  63. *
  64. * Note: Care should be taken when modifying as the layout must remain the same
  65. * for both 64- and 32-bit (for 32-bit userland on 64-bit kernel).
  66. */
  67. union mips_vdso_data {
  68. struct {
  69. u64 xtime_sec;
  70. u64 xtime_nsec;
  71. u32 wall_to_mono_sec;
  72. u32 wall_to_mono_nsec;
  73. u32 seq_count;
  74. u32 cs_shift;
  75. u8 clock_mode;
  76. u32 cs_mult;
  77. u64 cs_cycle_last;
  78. u64 cs_mask;
  79. s32 tz_minuteswest;
  80. s32 tz_dsttime;
  81. };
  82. u8 page[PAGE_SIZE];
  83. };
  84. static inline u32 vdso_data_read_begin(const union mips_vdso_data *data)
  85. {
  86. u32 seq;
  87. while (true) {
  88. seq = ACCESS_ONCE(data->seq_count);
  89. if (likely(!(seq & 1))) {
  90. /* Paired with smp_wmb() in vdso_data_write_*(). */
  91. smp_rmb();
  92. return seq;
  93. }
  94. cpu_relax();
  95. }
  96. }
  97. static inline bool vdso_data_read_retry(const union mips_vdso_data *data,
  98. u32 start_seq)
  99. {
  100. /* Paired with smp_wmb() in vdso_data_write_*(). */
  101. smp_rmb();
  102. return unlikely(data->seq_count != start_seq);
  103. }
  104. static inline void vdso_data_write_begin(union mips_vdso_data *data)
  105. {
  106. ++data->seq_count;
  107. /* Ensure sequence update is written before other data page values. */
  108. smp_wmb();
  109. }
  110. static inline void vdso_data_write_end(union mips_vdso_data *data)
  111. {
  112. /* Ensure data values are written before updating sequence again. */
  113. smp_wmb();
  114. ++data->seq_count;
  115. }
  116. #endif /* __ASM_VDSO_H */