summaryrefslogtreecommitdiff
path: root/arch/s390/kernel/vdso32/clock_gettime.S
blob: a9418bf975db5a32db1c88b07d59f71454ce550b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Userland implementation of clock_gettime() for 32 bits processes in a
 * s390 kernel for use in the vDSO
 *
 *  Copyright IBM Corp. 2008
 *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
 */
#include <asm/vdso.h>
#include <asm/asm-offsets.h>
#include <asm/unistd.h>
#include <asm/dwarf.h>

	.text
	.align 4
	.globl __kernel_clock_gettime
	.type  __kernel_clock_gettime,@function
__kernel_clock_gettime:
	CFI_STARTPROC
	ahi	%r15,-16
	CFI_DEF_CFA_OFFSET 176
	CFI_VAL_OFFSET 15, -160
	basr	%r5,0
0:	al	%r5,21f-0b(%r5)			/* get &_vdso_data */
	chi	%r2,__CLOCK_REALTIME_COARSE
	je	10f
	chi	%r2,__CLOCK_REALTIME
	je	11f
	chi	%r2,__CLOCK_MONOTONIC_COARSE
	je	9f
	chi	%r2,__CLOCK_MONOTONIC
	jne	19f

	/* CLOCK_MONOTONIC */
1:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
	tml	%r4,0x0001			/* pending update ? loop */
	jnz	1b
	stcke	0(%r15)				/* Store TOD clock */
	lm	%r0,%r1,1(%r15)
	s	%r0,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
	sl	%r1,__VDSO_XTIME_STAMP+4(%r5)
	brc	3,2f
	ahi	%r0,-1
2:	ms	%r0,__VDSO_TK_MULT(%r5)		/*  * tk->mult */
	lr	%r2,%r0
	l	%r0,__VDSO_TK_MULT(%r5)
	ltr	%r1,%r1
	mr	%r0,%r0
	jnm	3f
	a	%r0,__VDSO_TK_MULT(%r5)
3:	alr	%r0,%r2
	al	%r0,__VDSO_WTOM_NSEC(%r5)
	al	%r1,__VDSO_WTOM_NSEC+4(%r5)
	brc	12,5f
	ahi	%r0,1
5:	l	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */
	srdl	%r0,0(%r2)			/*  >> tk->shift */
	l	%r2,__VDSO_WTOM_SEC+4(%r5)
	cl	%r4,__VDSO_UPD_COUNT+4(%r5)	/* check update counter */
	jne	1b
	basr	%r5,0
6:	ltr	%r0,%r0
	jnz	7f
	cl	%r1,20f-6b(%r5)
	jl	8f
7:	ahi	%r2,1
	sl	%r1,20f-6b(%r5)
	brc	3,6b
	ahi	%r0,-1
	j	6b
8:	st	%r2,0(%r3)			/* store tp->tv_sec */
	st	%r1,4(%r3)			/* store tp->tv_nsec */
	lhi	%r2,0
	ahi	%r15,16
	CFI_DEF_CFA_OFFSET 160
	CFI_RESTORE 15
	br	%r14

	/* CLOCK_MONOTONIC_COARSE */
	CFI_DEF_CFA_OFFSET 176
	CFI_VAL_OFFSET 15, -160
9:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
	tml	%r4,0x0001			/* pending update ? loop */
	jnz	9b
	l	%r2,__VDSO_WTOM_CRS_SEC+4(%r5)
	l	%r1,__VDSO_WTOM_CRS_NSEC+4(%r5)
	cl	%r4,__VDSO_UPD_COUNT+4(%r5)	/* check update counter */
	jne	9b
	j	8b

	/* CLOCK_REALTIME_COARSE */
10:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
	tml	%r4,0x0001			/* pending update ? loop */
	jnz	10b
	l	%r2,__VDSO_XTIME_CRS_SEC+4(%r5)
	l	%r1,__VDSO_XTIME_CRS_NSEC+4(%r5)
	cl	%r4,__VDSO_UPD_COUNT+4(%r5)	/* check update counter */
	jne	10b
	j	17f

	/* CLOCK_REALTIME */
11:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
	tml	%r4,0x0001			/* pending update ? loop */
	jnz	11b
	stcke	0(%r15)				/* Store TOD clock */
	lm	%r0,%r1,__VDSO_TS_END(%r5)	/* TOD steering end time */
	s	%r0,1(%r15)			/* no - ts_steering_end */
	sl	%r1,5(%r15)
	brc	3,22f
	ahi	%r0,-1
22:	ltr	%r0,%r0				/* past end of steering? */
	jm	24f
	srdl	%r0,15				/* 1 per 2^16 */
	tm	__VDSO_TS_DIR+3(%r5),0x01	/* steering direction? */
	jz	23f
	lcr	%r0,%r0				/* negative TOD offset */
	lcr	%r1,%r1
	je	23f
	ahi	%r0,-1
23:	a	%r0,1(%r15)			/* add TOD timestamp */
	al	%r1,5(%r15)
	brc	12,25f
	ahi	%r0,1
	j	25f
24:	lm	%r0,%r1,1(%r15)			/* load TOD timestamp */
25:	s	%r0,__VDSO_XTIME_STAMP(%r5)	/* TOD - cycle_last */
	sl	%r1,__VDSO_XTIME_STAMP+4(%r5)
	brc	3,12f
	ahi	%r0,-1
12:	ms	%r0,__VDSO_TK_MULT(%r5)		/*  * tk->mult */
	lr	%r2,%r0
	l	%r0,__VDSO_TK_MULT(%r5)
	ltr	%r1,%r1
	mr	%r0,%r0
	jnm	13f
	a	%r0,__VDSO_TK_MULT(%r5)
13:	alr	%r0,%r2
	al	%r0,__VDSO_XTIME_NSEC(%r5)	/*  + tk->xtime_nsec */
	al	%r1,__VDSO_XTIME_NSEC+4(%r5)
	brc	12,14f
	ahi	%r0,1
14:	l	%r2,__VDSO_TK_SHIFT(%r5)	/* Timekeeper shift */
	srdl	%r0,0(%r2)			/*  >> tk->shift */
	l	%r2,__VDSO_XTIME_SEC+4(%r5)
	cl	%r4,__VDSO_UPD_COUNT+4(%r5)	/* check update counter */
	jne	11b
	basr	%r5,0
15:	ltr	%r0,%r0
	jnz	16f
	cl	%r1,20f-15b(%r5)
	jl	17f
16:	ahi	%r2,1
	sl	%r1,20f-15b(%r5)
	brc	3,15b
	ahi	%r0,-1
	j	15b
17:	st	%r2,0(%r3)			/* store tp->tv_sec */
	st	%r1,4(%r3)			/* store tp->tv_nsec */
	lhi	%r2,0
	ahi	%r15,16
	CFI_DEF_CFA_OFFSET 160
	CFI_RESTORE 15
	br	%r14

	/* Fallback to system call */
	CFI_DEF_CFA_OFFSET 176
	CFI_VAL_OFFSET 15, -160
19:	lhi	%r1,__NR_clock_gettime
	svc	0
	ahi	%r15,16
	CFI_DEF_CFA_OFFSET 160
	CFI_RESTORE 15
	br	%r14
	CFI_ENDPROC

20:	.long	1000000000
21:	.long	_vdso_data - 0b
	.size	__kernel_clock_gettime,.-__kernel_clock_gettime