clock_gettime.S 4.1 KB

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