clock_gettime.S 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Userland implementation of clock_gettime() for 64 bits processes in a
  4. * s390 kernel for use in the vDSO
  5. *
  6. * Copyright IBM Corp. 2008
  7. * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  8. */
  9. #include <asm/vdso.h>
  10. #include <asm/asm-offsets.h>
  11. #include <asm/unistd.h>
  12. #include <asm/dwarf.h>
  13. #include <asm/ptrace.h>
  14. .text
  15. .align 4
  16. .globl __kernel_clock_gettime
  17. .type __kernel_clock_gettime,@function
  18. __kernel_clock_gettime:
  19. CFI_STARTPROC
  20. aghi %r15,-16
  21. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
  22. CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
  23. larl %r5,_vdso_data
  24. cghi %r2,__CLOCK_REALTIME_COARSE
  25. je 4f
  26. cghi %r2,__CLOCK_REALTIME
  27. je 5f
  28. cghi %r2,-3 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
  29. je 9f
  30. cghi %r2,__CLOCK_MONOTONIC_COARSE
  31. je 3f
  32. cghi %r2,__CLOCK_MONOTONIC
  33. jne 12f
  34. /* CLOCK_MONOTONIC */
  35. 0: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  36. tmll %r4,0x0001 /* pending update ? loop */
  37. jnz 0b
  38. stcke 0(%r15) /* Store TOD clock */
  39. lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
  40. lg %r0,__VDSO_WTOM_SEC(%r5)
  41. lg %r1,1(%r15)
  42. sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
  43. msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
  44. alg %r1,__VDSO_WTOM_NSEC(%r5)
  45. srlg %r1,%r1,0(%r2) /* >> tk->shift */
  46. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  47. jne 0b
  48. larl %r5,13f
  49. 1: clg %r1,0(%r5)
  50. jl 2f
  51. slg %r1,0(%r5)
  52. aghi %r0,1
  53. j 1b
  54. 2: stg %r0,0(%r3) /* store tp->tv_sec */
  55. stg %r1,8(%r3) /* store tp->tv_nsec */
  56. lghi %r2,0
  57. aghi %r15,16
  58. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
  59. CFI_RESTORE 15
  60. br %r14
  61. /* CLOCK_MONOTONIC_COARSE */
  62. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
  63. CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
  64. 3: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  65. tmll %r4,0x0001 /* pending update ? loop */
  66. jnz 3b
  67. lg %r0,__VDSO_WTOM_CRS_SEC(%r5)
  68. lg %r1,__VDSO_WTOM_CRS_NSEC(%r5)
  69. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  70. jne 3b
  71. j 2b
  72. /* CLOCK_REALTIME_COARSE */
  73. 4: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  74. tmll %r4,0x0001 /* pending update ? loop */
  75. jnz 4b
  76. lg %r0,__VDSO_XTIME_CRS_SEC(%r5)
  77. lg %r1,__VDSO_XTIME_CRS_NSEC(%r5)
  78. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  79. jne 4b
  80. j 7f
  81. /* CLOCK_REALTIME */
  82. 5: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  83. tmll %r4,0x0001 /* pending update ? loop */
  84. jnz 5b
  85. stcke 0(%r15) /* Store TOD clock */
  86. lg %r1,1(%r15)
  87. lg %r0,__VDSO_TS_END(%r5) /* TOD steering end time */
  88. slgr %r0,%r1 /* now - ts_steering_end */
  89. ltgr %r0,%r0 /* past end of steering ? */
  90. jm 17f
  91. srlg %r0,%r0,15 /* 1 per 2^16 */
  92. tm __VDSO_TS_DIR+3(%r5),0x01 /* steering direction? */
  93. jz 18f
  94. lcgr %r0,%r0 /* negative TOD offset */
  95. 18: algr %r1,%r0 /* add steering offset */
  96. 17: lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
  97. sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
  98. msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
  99. alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
  100. srlg %r1,%r1,0(%r2) /* >> tk->shift */
  101. lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
  102. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  103. jne 5b
  104. larl %r5,13f
  105. 6: clg %r1,0(%r5)
  106. jl 7f
  107. slg %r1,0(%r5)
  108. aghi %r0,1
  109. j 6b
  110. 7: stg %r0,0(%r3) /* store tp->tv_sec */
  111. stg %r1,8(%r3) /* store tp->tv_nsec */
  112. lghi %r2,0
  113. aghi %r15,16
  114. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
  115. CFI_RESTORE 15
  116. br %r14
  117. /* CPUCLOCK_VIRT for this thread */
  118. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
  119. CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
  120. 9: lghi %r4,0
  121. icm %r0,15,__VDSO_ECTG_OK(%r5)
  122. jz 12f
  123. sacf 256 /* Magic ectg instruction */
  124. .insn ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
  125. sacf 0
  126. algr %r1,%r0 /* r1 = cputime as TOD value */
  127. mghi %r1,1000 /* convert to nanoseconds */
  128. srlg %r1,%r1,12 /* r1 = cputime in nanosec */
  129. lgr %r4,%r1
  130. larl %r5,13f
  131. srlg %r1,%r1,9 /* divide by 1000000000 */
  132. mlg %r0,8(%r5)
  133. srlg %r0,%r0,11 /* r0 = tv_sec */
  134. stg %r0,0(%r3)
  135. msg %r0,0(%r5) /* calculate tv_nsec */
  136. slgr %r4,%r0 /* r4 = tv_nsec */
  137. stg %r4,8(%r3)
  138. lghi %r2,0
  139. aghi %r15,16
  140. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
  141. CFI_RESTORE 15
  142. br %r14
  143. /* Fallback to system call */
  144. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
  145. CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
  146. 12: lghi %r1,__NR_clock_gettime
  147. svc 0
  148. aghi %r15,16
  149. CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
  150. CFI_RESTORE 15
  151. br %r14
  152. CFI_ENDPROC
  153. 13: .quad 1000000000
  154. 14: .quad 19342813113834067
  155. .size __kernel_clock_gettime,.-__kernel_clock_gettime