clock_gettime.S 3.2 KB

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