root/arch/s390/kernel/vdso64/clock_gettime.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 /*
   3  * Userland implementation of clock_gettime() for 64 bits processes in a
   4  * s390 kernel for use in the vDSO
   5  *
   6  *  Copyright IBM Corp. 2008
   7  *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
   8  */
   9 #include <asm/vdso.h>
  10 #include <asm/asm-offsets.h>
  11 #include <asm/unistd.h>
  12 #include <asm/dwarf.h>
  13 #include <asm/ptrace.h>
  14 
  15         .text
  16         .align 4
  17         .globl __kernel_clock_gettime
  18         .type  __kernel_clock_gettime,@function
  19 __kernel_clock_gettime:
  20         CFI_STARTPROC
  21         aghi    %r15,-16
  22         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
  23         CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
  24         larl    %r5,_vdso_data
  25         cghi    %r2,__CLOCK_REALTIME_COARSE
  26         je      4f
  27         cghi    %r2,__CLOCK_REALTIME
  28         je      5f
  29         cghi    %r2,-3          /* Per-thread CPUCLOCK with PID=0, VIRT=1 */
  30         je      9f
  31         cghi    %r2,__CLOCK_MONOTONIC_COARSE
  32         je      3f
  33         cghi    %r2,__CLOCK_MONOTONIC
  34         jne     12f
  35 
  36         /* CLOCK_MONOTONIC */
  37 0:      lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
  38         tmll    %r4,0x0001                      /* pending update ? loop */
  39         jnz     0b
  40         stcke   0(%r15)                         /* Store TOD clock */
  41         lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
  42         lg      %r0,__VDSO_WTOM_SEC(%r5)
  43         lg      %r1,1(%r15)
  44         sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
  45         msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
  46         alg     %r1,__VDSO_WTOM_NSEC(%r5)
  47         srlg    %r1,%r1,0(%r2)                  /*  >> tk->shift */
  48         clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
  49         jne     0b
  50         larl    %r5,13f
  51 1:      clg     %r1,0(%r5)
  52         jl      2f
  53         slg     %r1,0(%r5)
  54         aghi    %r0,1
  55         j       1b
  56 2:      stg     %r0,0(%r3)                      /* store tp->tv_sec */
  57         stg     %r1,8(%r3)                      /* store tp->tv_nsec */
  58         lghi    %r2,0
  59         aghi    %r15,16
  60         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
  61         CFI_RESTORE 15
  62         br      %r14
  63 
  64         /* CLOCK_MONOTONIC_COARSE */
  65         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
  66         CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
  67 3:      lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
  68         tmll    %r4,0x0001                      /* pending update ? loop */
  69         jnz     3b
  70         lg      %r0,__VDSO_WTOM_CRS_SEC(%r5)
  71         lg      %r1,__VDSO_WTOM_CRS_NSEC(%r5)
  72         clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
  73         jne     3b
  74         j       2b
  75 
  76         /* CLOCK_REALTIME_COARSE */
  77 4:      lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
  78         tmll    %r4,0x0001                      /* pending update ? loop */
  79         jnz     4b
  80         lg      %r0,__VDSO_XTIME_CRS_SEC(%r5)
  81         lg      %r1,__VDSO_XTIME_CRS_NSEC(%r5)
  82         clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
  83         jne     4b
  84         j       7f
  85 
  86         /* CLOCK_REALTIME */
  87 5:      lg      %r4,__VDSO_UPD_COUNT(%r5)       /* load update counter */
  88         tmll    %r4,0x0001                      /* pending update ? loop */
  89         jnz     5b
  90         stcke   0(%r15)                         /* Store TOD clock */
  91         lg      %r1,1(%r15)
  92         lg      %r0,__VDSO_TS_END(%r5)          /* TOD steering end time */
  93         slgr    %r0,%r1                         /* now - ts_steering_end */
  94         ltgr    %r0,%r0                         /* past end of steering ? */
  95         jm      17f
  96         srlg    %r0,%r0,15                      /* 1 per 2^16 */
  97         tm      __VDSO_TS_DIR+3(%r5),0x01       /* steering direction? */
  98         jz      18f
  99         lcgr    %r0,%r0                         /* negative TOD offset */
 100 18:     algr    %r1,%r0                         /* add steering offset */
 101 17:     lgf     %r2,__VDSO_TK_SHIFT(%r5)        /* Timekeeper shift */
 102         sg      %r1,__VDSO_XTIME_STAMP(%r5)     /* TOD - cycle_last */
 103         msgf    %r1,__VDSO_TK_MULT(%r5)         /*  * tk->mult */
 104         alg     %r1,__VDSO_XTIME_NSEC(%r5)      /*  + tk->xtime_nsec */
 105         srlg    %r1,%r1,0(%r2)                  /*  >> tk->shift */
 106         lg      %r0,__VDSO_XTIME_SEC(%r5)       /* tk->xtime_sec */
 107         clg     %r4,__VDSO_UPD_COUNT(%r5)       /* check update counter */
 108         jne     5b
 109         larl    %r5,13f
 110 6:      clg     %r1,0(%r5)
 111         jl      7f
 112         slg     %r1,0(%r5)
 113         aghi    %r0,1
 114         j       6b
 115 7:      stg     %r0,0(%r3)                      /* store tp->tv_sec */
 116         stg     %r1,8(%r3)                      /* store tp->tv_nsec */
 117         lghi    %r2,0
 118         aghi    %r15,16
 119         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
 120         CFI_RESTORE 15
 121         br      %r14
 122 
 123         /* CPUCLOCK_VIRT for this thread */
 124         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
 125         CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
 126 9:      lghi    %r4,0
 127         icm     %r0,15,__VDSO_ECTG_OK(%r5)
 128         jz      12f
 129         sacf    256                             /* Magic ectg instruction */
 130         .insn   ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4
 131         sacf    0
 132         algr    %r1,%r0                         /* r1 = cputime as TOD value */
 133         mghi    %r1,1000                        /* convert to nanoseconds */
 134         srlg    %r1,%r1,12                      /* r1 = cputime in nanosec */
 135         lgr     %r4,%r1
 136         larl    %r5,13f
 137         srlg    %r1,%r1,9                       /* divide by 1000000000 */
 138         mlg     %r0,8(%r5)
 139         srlg    %r0,%r0,11                      /* r0 = tv_sec */
 140         stg     %r0,0(%r3)
 141         msg     %r0,0(%r5)                      /* calculate tv_nsec */
 142         slgr    %r4,%r0                         /* r4 = tv_nsec */
 143         stg     %r4,8(%r3)
 144         lghi    %r2,0
 145         aghi    %r15,16
 146         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
 147         CFI_RESTORE 15
 148         br      %r14
 149 
 150         /* Fallback to system call */
 151         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD+16
 152         CFI_VAL_OFFSET 15, -STACK_FRAME_OVERHEAD
 153 12:     lghi    %r1,__NR_clock_gettime
 154         svc     0
 155         aghi    %r15,16
 156         CFI_DEF_CFA_OFFSET STACK_FRAME_OVERHEAD
 157         CFI_RESTORE 15
 158         br      %r14
 159         CFI_ENDPROC
 160 
 161 13:     .quad   1000000000
 162 14:     .quad   19342813113834067
 163         .size   __kernel_clock_gettime,.-__kernel_clock_gettime

/* [<][>][^][v][top][bottom][index][help] */