s390/vdso: add vdso support for coarse clocks
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 29 Aug 2014 10:31:45 +0000 (12:31 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Sep 2014 06:53:27 +0000 (08:53 +0200)
Add CLOCK_REALTIME_COARSE and CLOCK_MONOTONIC_COARSE optimization to
the 64-bit and 31-bit vdso.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/vdso.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/time.c
arch/s390/kernel/vdso32/clock_getres.S
arch/s390/kernel/vdso32/clock_gettime.S
arch/s390/kernel/vdso64/clock_getres.S
arch/s390/kernel/vdso64/clock_gettime.S

index bc9746a7d47c53edf219c4b4b1f500bc0728a284..a62526d09201667f5d485192d9c6d081b7559060 100644 (file)
@@ -22,13 +22,17 @@ struct vdso_data {
        __u64 xtime_tod_stamp;          /* TOD clock for xtime          0x08 */
        __u64 xtime_clock_sec;          /* Kernel time                  0x10 */
        __u64 xtime_clock_nsec;         /*                              0x18 */
-       __u64 wtom_clock_sec;           /* Wall to monotonic clock      0x20 */
-       __u64 wtom_clock_nsec;          /*                              0x28 */
-       __u32 tz_minuteswest;           /* Minutes west of Greenwich    0x30 */
-       __u32 tz_dsttime;               /* Type of dst correction       0x34 */
-       __u32 ectg_available;           /* ECTG instruction present     0x38 */
-       __u32 tk_mult;                  /* Mult. used for xtime_nsec    0x3c */
-       __u32 tk_shift;                 /* Shift used for xtime_nsec    0x40 */
+       __u64 xtime_coarse_sec;         /* Coarse kernel time           0x20 */
+       __u64 xtime_coarse_nsec;        /*                              0x28 */
+       __u64 wtom_clock_sec;           /* Wall to monotonic clock      0x30 */
+       __u64 wtom_clock_nsec;          /*                              0x38 */
+       __u64 wtom_coarse_sec;          /* Coarse wall to monotonic     0x40 */
+       __u64 wtom_coarse_nsec;         /*                              0x48 */
+       __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 {
index afe1715a4eb765cb06d1ab3277bce0b4ce8fc3c2..3e9e479d9b49a939aabd2bb4961f354cffe81c36 100644 (file)
@@ -62,8 +62,12 @@ int main(void)
        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_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_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_ECTG_OK, offsetof(struct vdso_data, ectg_available));
        DEFINE(__VDSO_TK_MULT, offsetof(struct vdso_data, tk_mult));
@@ -73,8 +77,11 @@ int main(void)
        /* constants used by the vdso */
        DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
        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_REALTIME_RES, MONOTONIC_RES_NSEC);
+       DEFINE(__CLOCK_COARSE_RES, LOW_RES_NSEC);
        BLANK();
        /* idle data offsets */
        DEFINE(__CLOCK_IDLE_ENTER, offsetof(struct s390_idle_data, clock_idle_enter));
index 4cef607f371122fc2fcc7959bd6f12cff3d3d896..69e980de0f6282310e7978ee398a2a5a0d7184c6 100644 (file)
@@ -232,6 +232,19 @@ void update_vsyscall(struct timekeeper *tk)
                vdso_data->wtom_clock_nsec -= nsecps;
                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_shift = tk->tkr.shift;
        smp_wmb();
index 36aaa25d05daa4e1d785103d85a2bb5a078fc2cc..eca3f001f081309c88372de459a6dfcccd754e7d 100644 (file)
        .type  __kernel_clock_getres,@function
 __kernel_clock_getres:
        .cfi_startproc
+       basr    %r1,0
+       la      %r1,4f-.(%r1)
        chi     %r2,__CLOCK_REALTIME
        je      0f
        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
 0:     ltr     %r3,%r3
        jz      2f                              /* res == NULL */
-       basr    %r1,0
-1:     l       %r0,4f-1b(%r1)
+1:     l       %r0,0(%r1)
        xc      0(4,%r3),0(%r3)                 /* set tp->tv_sec to zero */
        st      %r0,4(%r3)                      /* store tp->tv_usec */
 2:     lhi     %r2,0
@@ -35,5 +41,6 @@ __kernel_clock_getres:
        svc     0
        br      %r14
 4:     .long   __CLOCK_REALTIME_RES
+5:     .long   __CLOCK_COARSE_RES
        .cfi_endproc
        .size   __kernel_clock_getres,.-__kernel_clock_getres
index 4e20a9365bb799144eb00cdd6cf3b19eb46e22f2..48c2206a39561ea9373bb3fb8ec48297b3509867 100644 (file)
@@ -21,8 +21,12 @@ __kernel_clock_gettime:
        .cfi_startproc
        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
 
@@ -68,6 +72,26 @@ __kernel_clock_gettime:
        lhi     %r2,0
        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 */
index 34deba7c7ed1d8b18036b0b07f9b7cd9d41e9259..c8513deb8c663f51fa4f4bc2b2299ea24f1aaefd 100644 (file)
        .type  __kernel_clock_getres,@function
 __kernel_clock_getres:
        .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
        je      0f
        cghi    %r2,__CLOCK_MONOTONIC
@@ -32,7 +38,6 @@ __kernel_clock_getres:
        jz      2f
 0:     ltgr    %r3,%r3
        jz      1f                              /* res == NULL */
-       larl    %r1,3f
        lg      %r0,0(%r1)
        xc      0(8,%r3),0(%r3)                 /* set tp->tv_sec to zero */
        stg     %r0,8(%r3)                      /* store tp->tv_usec */
@@ -42,5 +47,6 @@ __kernel_clock_getres:
        svc     0
        br      %r14
 3:     .quad   __CLOCK_REALTIME_RES
+4:     .quad   __CLOCK_COARSE_RES
        .cfi_endproc
        .size   __kernel_clock_getres,.-__kernel_clock_getres
index 4add40b78ed5571ca962f094947ed9e2d0e52c54..9d9761f8e11035761c3b1143c6486a9fc52193c6 100644 (file)
 __kernel_clock_gettime:
        .cfi_startproc
        larl    %r5,_vdso_data
+       cghi    %r2,__CLOCK_REALTIME_COARSE
+       je      4f
        cghi    %r2,__CLOCK_REALTIME
        je      5f
        cghi    %r2,__CLOCK_THREAD_CPUTIME_ID
        je      9f
        cghi    %r2,-2          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
        je      9f
+       cghi    %r2,__CLOCK_MONOTONIC_COARSE
+       je      3f
        cghi    %r2,__CLOCK_MONOTONIC
        jne     12f
 
@@ -54,6 +58,26 @@ __kernel_clock_gettime:
        lghi    %r2,0
        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 */
 5:     lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
        tmll    %r4,0x0001                      /* pending update ? loop */