clock_gettime.S 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. lgf %r2,__VDSO_TK_SHIFT(%r5) /* Timekeeper shift */
  82. lg %r1,1(%r15)
  83. sg %r1,__VDSO_XTIME_STAMP(%r5) /* TOD - cycle_last */
  84. msgf %r1,__VDSO_TK_MULT(%r5) /* * tk->mult */
  85. alg %r1,__VDSO_XTIME_NSEC(%r5) /* + tk->xtime_nsec */
  86. srlg %r1,%r1,0(%r2) /* >> tk->shift */
  87. lg %r0,__VDSO_XTIME_SEC(%r5) /* tk->xtime_sec */
  88. clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
  89. jne 5b
  90. larl %r5,13f
  91. 6: clg %r1,0(%r5)
  92. jl 7f
  93. slg %r1,0(%r5)
  94. aghi %r0,1
  95. j 6b
  96. 7: stg %r0,0(%r3) /* store tp->tv_sec */
  97. stg %r1,8(%r3) /* store tp->tv_nsec */
  98. lghi %r2,0
  99. aghi %r15,16
  100. br %r14
  101. /* CPUCLOCK_VIRT for this thread */
  102. 9: icm %r0,15,__VDSO_ECTG_OK(%r5)
  103. jz 12f
  104. ear %r2,%a4
  105. llilh %r4,0x0100
  106. sar %a4,%r4
  107. lghi %r4,0
  108. epsw %r5,0
  109. sacf 512 /* Magic ectg instruction */
  110. .insn ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
  111. tml %r5,0x4000
  112. jo 11f
  113. tml %r5,0x8000
  114. jno 10f
  115. sacf 256
  116. j 11f
  117. 10: sacf 0
  118. 11: sar %a4,%r2
  119. algr %r1,%r0 /* r1 = cputime as TOD value */
  120. mghi %r1,1000 /* convert to nanoseconds */
  121. srlg %r1,%r1,12 /* r1 = cputime in nanosec */
  122. lgr %r4,%r1
  123. larl %r5,13f
  124. srlg %r1,%r1,9 /* divide by 1000000000 */
  125. mlg %r0,8(%r5)
  126. srlg %r0,%r0,11 /* r0 = tv_sec */
  127. stg %r0,0(%r3)
  128. msg %r0,0(%r5) /* calculate tv_nsec */
  129. slgr %r4,%r0 /* r4 = tv_nsec */
  130. stg %r4,8(%r3)
  131. lghi %r2,0
  132. aghi %r15,16
  133. br %r14
  134. /* Fallback to system call */
  135. 12: lghi %r1,__NR_clock_gettime
  136. svc 0
  137. aghi %r15,16
  138. br %r14
  139. 13: .quad 1000000000
  140. 14: .quad 19342813113834067
  141. .cfi_endproc
  142. .size __kernel_clock_gettime,.-__kernel_clock_gettime