summaryrefslogtreecommitdiff
path: root/arch/s390/kernel/vdso32/clock_gettime.S
blob: 5be8e472f57d1d0debe31c849b4177492380d957 (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
/*
 * 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
	basr	%r5,0
0:	al	%r5,21f-0b(%r5)			/* get &_vdso_data */
	chi	%r2,__CLOCK_REALTIME
	je	10f
	chi	%r2,__CLOCK_MONOTONIC
	jne	19f

	/* CLOCK_MONOTONIC */
	ltr	%r3,%r3
	jz	9f				/* tp == NULL */
1:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
	tml	%r4,0x0001			/* pending update ? loop */
	jnz	1b
	stck	24(%r15)			/* Store TOD clock */
	lm	%r0,%r1,24(%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_XTIME_NSEC(%r5)	/*  + tk->xtime_nsec */
	al	%r1,__VDSO_XTIME_NSEC+4(%r5)
	brc	12,4f
	ahi	%r0,1
4:	al	%r0,__VDSO_WTOM_NSEC(%r5)	/*  + wall_to_monotonic.nsec */
	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_XTIME_SEC+4(%r5)
	al	%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 */
9:	lhi	%r2,0
	br	%r14

	/* CLOCK_REALTIME */
10:	ltr	%r3,%r3				/* tp == NULL */
	jz	18f
11:	l	%r4,__VDSO_UPD_COUNT+4(%r5)	/* load update counter */
	tml	%r4,0x0001			/* pending update ? loop */
	jnz	11b
	stck	24(%r15)			/* Store TOD clock */
	lm	%r0,%r1,24(%r15)
	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 */
18:	lhi	%r2,0
	br	%r14

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

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