summaryrefslogtreecommitdiff
path: root/arch/s390/kernel/vdso32/clock_gettime.S
blob: b642c0382238a34ca59c26ec0ec52b7d665abe54 (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
/* 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)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License (version 2 only)
 * as published by the Free Software Foundation.
 */
#include <asm/vdso.h>
#include <asm/asm-offsets.h>
#include <asm/unistd.h>

	.text
	.align 4
	.globl __kernel_clock_gettime
	.type  __kernel_clock_gettime,@function
__kernel_clock_gettime:
	.cfi_startproc
	ahi	%r15,-16
	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
	br	%r14

	/* CLOCK_MONOTONIC_COARSE */
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
	br	%r14

	/* Fallback to system call */
19:	lhi	%r1,__NR_clock_gettime
	svc	0
	ahi	%r15,16
	br	%r14

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