Commit b7eacb59 authored by Martin Schwidefsky's avatar Martin Schwidefsky

s390/vdso: add vdso support for coarse clocks

Add CLOCK_REALTIME_COARSE and CLOCK_MONOTONIC_COARSE optimization to
the 64-bit and 31-bit vdso.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 070b7be6
...@@ -22,13 +22,17 @@ struct vdso_data { ...@@ -22,13 +22,17 @@ struct vdso_data {
__u64 xtime_tod_stamp; /* TOD clock for xtime 0x08 */ __u64 xtime_tod_stamp; /* TOD clock for xtime 0x08 */
__u64 xtime_clock_sec; /* Kernel time 0x10 */ __u64 xtime_clock_sec; /* Kernel time 0x10 */
__u64 xtime_clock_nsec; /* 0x18 */ __u64 xtime_clock_nsec; /* 0x18 */
__u64 wtom_clock_sec; /* Wall to monotonic clock 0x20 */ __u64 xtime_coarse_sec; /* Coarse kernel time 0x20 */
__u64 wtom_clock_nsec; /* 0x28 */ __u64 xtime_coarse_nsec; /* 0x28 */
__u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */ __u64 wtom_clock_sec; /* Wall to monotonic clock 0x30 */
__u32 tz_dsttime; /* Type of dst correction 0x34 */ __u64 wtom_clock_nsec; /* 0x38 */
__u32 ectg_available; /* ECTG instruction present 0x38 */ __u64 wtom_coarse_sec; /* Coarse wall to monotonic 0x40 */
__u32 tk_mult; /* Mult. used for xtime_nsec 0x3c */ __u64 wtom_coarse_nsec; /* 0x48 */
__u32 tk_shift; /* Shift used for xtime_nsec 0x40 */ __u32 tz_minuteswest; /* Minutes west of Greenwich 0x50 */
__u32 tz_dsttime; /* Type of dst correction 0x54 */
__u32 ectg_available; /* ECTG instruction present 0x58 */
__u32 tk_mult; /* Mult. used for xtime_nsec 0x5c */
__u32 tk_shift; /* Shift used for xtime_nsec 0x60 */
}; };
struct vdso_per_cpu_data { struct vdso_per_cpu_data {
......
...@@ -62,8 +62,12 @@ int main(void) ...@@ -62,8 +62,12 @@ int main(void)
DEFINE(__VDSO_XTIME_STAMP, offsetof(struct vdso_data, xtime_tod_stamp)); DEFINE(__VDSO_XTIME_STAMP, offsetof(struct vdso_data, xtime_tod_stamp));
DEFINE(__VDSO_XTIME_SEC, offsetof(struct vdso_data, xtime_clock_sec)); DEFINE(__VDSO_XTIME_SEC, offsetof(struct vdso_data, xtime_clock_sec));
DEFINE(__VDSO_XTIME_NSEC, offsetof(struct vdso_data, xtime_clock_nsec)); DEFINE(__VDSO_XTIME_NSEC, offsetof(struct vdso_data, xtime_clock_nsec));
DEFINE(__VDSO_XTIME_CRS_SEC, offsetof(struct vdso_data, xtime_coarse_sec));
DEFINE(__VDSO_XTIME_CRS_NSEC, offsetof(struct vdso_data, xtime_coarse_nsec));
DEFINE(__VDSO_WTOM_SEC, offsetof(struct vdso_data, wtom_clock_sec)); DEFINE(__VDSO_WTOM_SEC, offsetof(struct vdso_data, wtom_clock_sec));
DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec));
DEFINE(__VDSO_WTOM_CRS_SEC, offsetof(struct vdso_data, wtom_coarse_sec));
DEFINE(__VDSO_WTOM_CRS_NSEC, offsetof(struct vdso_data, wtom_coarse_nsec));
DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest)); DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest));
DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available)); DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available));
DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult)); DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult));
...@@ -73,8 +77,11 @@ int main(void) ...@@ -73,8 +77,11 @@ int main(void)
/* constants used by the vdso */ /* constants used by the vdso */
DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME); DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC); DEFINE(__CLOCK_MONOTONIC, CLOCK_MONOTONIC);
DEFINE(__CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE);
DEFINE(__CLOCK_MONOTONIC_COARSE, CLOCK_MONOTONIC_COARSE);
DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID); DEFINE(__CLOCK_THREAD_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID);
DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
BLANK(); BLANK();
/* idle data offsets */ /* idle data offsets */
DEFINE(__CLOCK_IDLE_ENTER, offsetof(struct s390_idle_data, clock_idle_enter)); DEFINE(__CLOCK_IDLE_ENTER, offsetof(struct s390_idle_data, clock_idle_enter));
......
...@@ -232,6 +232,19 @@ void update_vsyscall(struct timekeeper *tk) ...@@ -232,6 +232,19 @@ void update_vsyscall(struct timekeeper *tk)
vdso_data->wtom_clock_nsec -= nsecps; vdso_data->wtom_clock_nsec -= nsecps;
vdso_data->wtom_clock_sec++; vdso_data->wtom_clock_sec++;
} }
vdso_data->xtime_coarse_sec = tk->xtime_sec;
vdso_data->xtime_coarse_nsec =
(long)(tk->tkr.xtime_nsec >> tk->tkr.shift);
vdso_data->wtom_coarse_sec =
vdso_data->xtime_coarse_sec + tk->wall_to_monotonic.tv_sec;
vdso_data->wtom_coarse_nsec =
vdso_data->xtime_coarse_nsec + tk->wall_to_monotonic.tv_nsec;
while (vdso_data->wtom_coarse_nsec >= NSEC_PER_SEC) {
vdso_data->wtom_coarse_nsec -= NSEC_PER_SEC;
vdso_data->wtom_coarse_sec++;
}
vdso_data->tk_mult = tk->tkr.mult; vdso_data->tk_mult = tk->tkr.mult;
vdso_data->tk_shift = tk->tkr.shift; vdso_data->tk_shift = tk->tkr.shift;
smp_wmb(); smp_wmb();
......
...@@ -19,14 +19,20 @@ ...@@ -19,14 +19,20 @@
.type __kernel_clock_getres,@function .type __kernel_clock_getres,@function
__kernel_clock_getres: __kernel_clock_getres:
.cfi_startproc .cfi_startproc
basr %r1,0
la %r1,4f-.(%r1)
chi %r2,__CLOCK_REALTIME chi %r2,__CLOCK_REALTIME
je 0f je 0f
chi %r2,__CLOCK_MONOTONIC chi %r2,__CLOCK_MONOTONIC
je 0f
la %r1,5f-4f(%r1)
chi %r2,__CLOCK_REALTIME_COARSE
je 0f
chi %r2,__CLOCK_MONOTONIC_COARSE
jne 3f jne 3f
0: ltr %r3,%r3 0: ltr %r3,%r3
jz 2f /* res == NULL */ jz 2f /* res == NULL */
basr %r1,0 1: l %r0,0(%r1)
1: l %r0,4f-1b(%r1)
xc 0(4,%r3),0(%r3) /* set tp->tv_sec to zero */ xc 0(4,%r3),0(%r3) /* set tp->tv_sec to zero */
st %r0,4(%r3) /* store tp->tv_usec */ st %r0,4(%r3) /* store tp->tv_usec */
2: lhi %r2,0 2: lhi %r2,0
...@@ -35,5 +41,6 @@ __kernel_clock_getres: ...@@ -35,5 +41,6 @@ __kernel_clock_getres:
svc 0 svc 0
br %r14 br %r14
4: .long __CLOCK_REALTIME_RES 4: .long __CLOCK_REALTIME_RES
5: .long __CLOCK_COARSE_RES
.cfi_endproc .cfi_endproc
.size __kernel_clock_getres,.-__kernel_clock_getres .size __kernel_clock_getres,.-__kernel_clock_getres
...@@ -21,8 +21,12 @@ __kernel_clock_gettime: ...@@ -21,8 +21,12 @@ __kernel_clock_gettime:
.cfi_startproc .cfi_startproc
basr %r5,0 basr %r5,0
0: al %r5,21f-0b(%r5) /* get &_vdso_data */ 0: al %r5,21f-0b(%r5) /* get &_vdso_data */
chi %r2,__CLOCK_REALTIME_COARSE
je 10f
chi %r2,__CLOCK_REALTIME chi %r2,__CLOCK_REALTIME
je 11f je 11f
chi %r2,__CLOCK_MONOTONIC_COARSE
je 9f
chi %r2,__CLOCK_MONOTONIC chi %r2,__CLOCK_MONOTONIC
jne 19f jne 19f
...@@ -68,6 +72,26 @@ __kernel_clock_gettime: ...@@ -68,6 +72,26 @@ __kernel_clock_gettime:
lhi %r2,0 lhi %r2,0
br %r14 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 */ /* CLOCK_REALTIME */
11: l %r4,__VDSO_UPD_COUNT+4(%r5) /* load update counter */ 11: l %r4,__VDSO_UPD_COUNT+4(%r5) /* load update counter */
tml %r4,0x0001 /* pending update ? loop */ tml %r4,0x0001 /* pending update ? loop */
......
...@@ -19,6 +19,12 @@ ...@@ -19,6 +19,12 @@
.type __kernel_clock_getres,@function .type __kernel_clock_getres,@function
__kernel_clock_getres: __kernel_clock_getres:
.cfi_startproc .cfi_startproc
larl %r1,4f
cghi %r2,__CLOCK_REALTIME_COARSE
je 0f
cghi %r2,__CLOCK_MONOTONIC_COARSE
je 0f
larl %r1,3f
cghi %r2,__CLOCK_REALTIME cghi %r2,__CLOCK_REALTIME
je 0f je 0f
cghi %r2,__CLOCK_MONOTONIC cghi %r2,__CLOCK_MONOTONIC
...@@ -32,7 +38,6 @@ __kernel_clock_getres: ...@@ -32,7 +38,6 @@ __kernel_clock_getres:
jz 2f jz 2f
0: ltgr %r3,%r3 0: ltgr %r3,%r3
jz 1f /* res == NULL */ jz 1f /* res == NULL */
larl %r1,3f
lg %r0,0(%r1) lg %r0,0(%r1)
xc 0(8,%r3),0(%r3) /* set tp->tv_sec to zero */ xc 0(8,%r3),0(%r3) /* set tp->tv_sec to zero */
stg %r0,8(%r3) /* store tp->tv_usec */ stg %r0,8(%r3) /* store tp->tv_usec */
...@@ -42,5 +47,6 @@ __kernel_clock_getres: ...@@ -42,5 +47,6 @@ __kernel_clock_getres:
svc 0 svc 0
br %r14 br %r14
3: .quad __CLOCK_REALTIME_RES 3: .quad __CLOCK_REALTIME_RES
4: .quad __CLOCK_COARSE_RES
.cfi_endproc .cfi_endproc
.size __kernel_clock_getres,.-__kernel_clock_getres .size __kernel_clock_getres,.-__kernel_clock_getres
...@@ -20,12 +20,16 @@ ...@@ -20,12 +20,16 @@
__kernel_clock_gettime: __kernel_clock_gettime:
.cfi_startproc .cfi_startproc
larl %r5,_vdso_data larl %r5,_vdso_data
cghi %r2,__CLOCK_REALTIME_COARSE
je 4f
cghi %r2,__CLOCK_REALTIME cghi %r2,__CLOCK_REALTIME
je 5f je 5f
cghi %r2,__CLOCK_THREAD_CPUTIME_ID cghi %r2,__CLOCK_THREAD_CPUTIME_ID
je 9f je 9f
cghi %r2,-2 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */ cghi %r2,-2 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
je 9f je 9f
cghi %r2,__CLOCK_MONOTONIC_COARSE
je 3f
cghi %r2,__CLOCK_MONOTONIC cghi %r2,__CLOCK_MONOTONIC
jne 12f jne 12f
...@@ -54,6 +58,26 @@ __kernel_clock_gettime: ...@@ -54,6 +58,26 @@ __kernel_clock_gettime:
lghi %r2,0 lghi %r2,0
br %r14 br %r14
/* CLOCK_MONOTONIC_COARSE */
3: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
tmll %r4,0x0001 /* pending update ? loop */
jnz 3b
lg %r0,__VDSO_WTOM_CRS_SEC(%r5)
lg %r1,__VDSO_WTOM_CRS_NSEC(%r5)
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
jne 3b
j 2b
/* CLOCK_REALTIME_COARSE */
4: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
tmll %r4,0x0001 /* pending update ? loop */
jnz 4b
lg %r0,__VDSO_XTIME_CRS_SEC(%r5)
lg %r1,__VDSO_XTIME_CRS_NSEC(%r5)
clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */
jne 4b
j 7f
/* CLOCK_REALTIME */ /* CLOCK_REALTIME */
5: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */ 5: lg %r4,__VDSO_UPD_COUNT(%r5) /* load update counter */
tmll %r4,0x0001 /* pending update ? loop */ tmll %r4,0x0001 /* pending update ? loop */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment