clock_gettime.S 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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,__CLOCK_THREAD_CPUTIME_ID
  28. je 9f
  29. cghi %r2,-2 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
  30. je 9f
  31. cghi %r2,__CLOCK_MONOTONIC_COARSE
  32. je 3f
  33. cghi %r2,__CLOCK_MONOTONIC
  34. jne 12f
  35. /* CLOCK_MONOTONIC */
  36. 0: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  37. tmll %r4,0x0001 /* pending update ? loop */
  38. jnz 0b
  39. stcke 0(%r15) /* Store TOD clock */
  40. lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
  41. lg %r0,__VDSO_WTOM_SEC(%r5)
  42. lg %r1,1(%r15)
  43. sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
  44. msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
  45. alg %r1,__VDSO_WTOM_NSEC(%r5)
  46. srlg %r1,%r1,0(%r2) /* >> tk->shift */
  47. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  48. jne 0b
  49. larl %r5,13f
  50. 1: clg %r1,0(%r5)
  51. jl 2f
  52. slg %r1,0(%r5)
  53. aghi %r0,1
  54. j 1b
  55. 2: stg %r0,0(%r3) /* store tp->tv_sec */
  56. stg %r1,8(%r3) /* store tp->tv_nsec */
  57. lghi %r2,0
  58. aghi %r15,16
  59. br %r14
  60. /* CLOCK_MONOTONIC_COARSE */
  61. 3: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  62. tmll %r4,0x0001 /* pending update ? loop */
  63. jnz 3b
  64. lg %r0,__VDSO_WTOM_CRS_SEC(%r5)
  65. lg %r1,__VDSO_WTOM_CRS_NSEC(%r5)
  66. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  67. jne 3b
  68. j 2b
  69. /* CLOCK_REALTIME_COARSE */
  70. 4: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  71. tmll %r4,0x0001 /* pending update ? loop */
  72. jnz 4b
  73. lg %r0,__VDSO_XTIME_CRS_SEC(%r5)
  74. lg %r1,__VDSO_XTIME_CRS_NSEC(%r5)
  75. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  76. jne 4b
  77. j 7f
  78. /* CLOCK_REALTIME */
  79. 5: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
  80. tmll %r4,0x0001 /* pending update ? loop */
  81. jnz 5b
  82. stcke 0(%r15) /* Store TOD clock */
  83. lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
  84. lg %r1,1(%r15)
  85. sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
  86. msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
  87. alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
  88. srlg %r1,%r1,0(%r2) /* >> tk->shift */
  89. lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
  90. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  91. jne 5b
  92. larl %r5,13f
  93. 6: clg %r1,0(%r5)
  94. jl 7f
  95. slg %r1,0(%r5)
  96. aghi %r0,1
  97. j 6b
  98. 7: stg %r0,0(%r3) /* store tp->tv_sec */
  99. stg %r1,8(%r3) /* store tp->tv_nsec */
  100. lghi %r2,0
  101. aghi %r15,16
  102. br %r14
  103. /* CLOCK_THREAD_CPUTIME_ID for this thread */
  104. 9: icm %r0,15,__VDSO_ECTG_OK(%r5)
  105. jz 12f
  106. ear %r2,%a4
  107. llilh %r4,0x0100
  108. sar %a4,%r4
  109. lghi %r4,0
  110. epsw %r5,0
  111. sacf 512 /* Magic ectg instruction */
  112. .insn ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
  113. tml %r5,0x4000
  114. jo 11f
  115. tml %r5,0x8000
  116. jno 10f
  117. sacf 256
  118. j 11f
  119. 10: sacf 0
  120. 11: sar %a4,%r2
  121. algr %r1,%r0 /* r1 = cputime as TOD value */
  122. mghi %r1,1000 /* convert to nanoseconds */
  123. srlg %r1,%r1,12 /* r1 = cputime in nanosec */
  124. lgr %r4,%r1
  125. larl %r5,13f
  126. srlg %r1,%r1,9 /* divide by 1000000000 */
  127. mlg %r0,8(%r5)
  128. srlg %r0,%r0,11 /* r0 = tv_sec */
  129. stg %r0,0(%r3)
  130. msg %r0,0(%r5) /* calculate tv_nsec */
  131. slgr %r4,%r0 /* r4 = tv_nsec */
  132. stg %r4,8(%r3)
  133. lghi %r2,0
  134. aghi %r15,16
  135. br %r14
  136. /* Fallback to system call */
  137. 12: lghi %r1,__NR_clock_gettime
  138. svc 0
  139. aghi %r15,16
  140. br %r14
  141. 13: .quad 1000000000
  142. 14: .quad 19342813113834067
  143. .cfi_endproc
  144. .size __kernel_clock_gettime,.-__kernel_clock_gettime