LCOV - code coverage report
Current view: top level - kernel/time - vsyscall.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 64 66 97.0 %
Date: 2022-03-28 13:20:08 Functions: 3 3 100.0 %
Branches: 3 4 75.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Copyright 2019 ARM Ltd.
       4                 :            :  *
       5                 :            :  * Generic implementation of update_vsyscall and update_vsyscall_tz.
       6                 :            :  *
       7                 :            :  * Based on the x86 specific implementation.
       8                 :            :  */
       9                 :            : 
      10                 :            : #include <linux/hrtimer.h>
      11                 :            : #include <linux/timekeeper_internal.h>
      12                 :            : #include <vdso/datapage.h>
      13                 :            : #include <vdso/helpers.h>
      14                 :            : #include <vdso/vsyscall.h>
      15                 :            : 
      16                 :      98549 : static inline void update_vdso_data(struct vdso_data *vdata,
      17                 :            :                                     struct timekeeper *tk)
      18                 :            : {
      19                 :      98549 :         struct vdso_timestamp *vdso_ts;
      20                 :      98549 :         u64 nsec, sec;
      21                 :            : 
      22                 :      98549 :         vdata[CS_HRES_COARSE].cycle_last        = tk->tkr_mono.cycle_last;
      23                 :      98549 :         vdata[CS_HRES_COARSE].mask              = tk->tkr_mono.mask;
      24                 :      98549 :         vdata[CS_HRES_COARSE].mult              = tk->tkr_mono.mult;
      25                 :      98549 :         vdata[CS_HRES_COARSE].shift             = tk->tkr_mono.shift;
      26                 :      98549 :         vdata[CS_RAW].cycle_last                = tk->tkr_raw.cycle_last;
      27                 :      98549 :         vdata[CS_RAW].mask                      = tk->tkr_raw.mask;
      28                 :      98549 :         vdata[CS_RAW].mult                      = tk->tkr_raw.mult;
      29                 :      98549 :         vdata[CS_RAW].shift                     = tk->tkr_raw.shift;
      30                 :            : 
      31                 :            :         /* CLOCK_MONOTONIC */
      32                 :      98549 :         vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC];
      33                 :      98549 :         vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
      34                 :            : 
      35                 :      98549 :         nsec = tk->tkr_mono.xtime_nsec;
      36                 :      98549 :         nsec += ((u64)tk->wall_to_monotonic.tv_nsec << tk->tkr_mono.shift);
      37         [ +  + ]:     141610 :         while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
      38                 :      43061 :                 nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
      39                 :      43061 :                 vdso_ts->sec++;
      40                 :            :         }
      41                 :      98549 :         vdso_ts->nsec        = nsec;
      42                 :            : 
      43                 :            :         /* Copy MONOTONIC time for BOOTTIME */
      44                 :      98549 :         sec     = vdso_ts->sec;
      45                 :            :         /* Add the boot offset */
      46                 :      98549 :         sec     += tk->monotonic_to_boot.tv_sec;
      47                 :      98549 :         nsec    += (u64)tk->monotonic_to_boot.tv_nsec << tk->tkr_mono.shift;
      48                 :            : 
      49                 :            :         /* CLOCK_BOOTTIME */
      50                 :      98549 :         vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_BOOTTIME];
      51                 :      98549 :         vdso_ts->sec = sec;
      52                 :            : 
      53         [ -  + ]:      98549 :         while (nsec >= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift)) {
      54                 :          0 :                 nsec -= (((u64)NSEC_PER_SEC) << tk->tkr_mono.shift);
      55                 :          0 :                 vdso_ts->sec++;
      56                 :            :         }
      57                 :      98549 :         vdso_ts->nsec        = nsec;
      58                 :            : 
      59                 :            :         /* CLOCK_MONOTONIC_RAW */
      60                 :      98549 :         vdso_ts         = &vdata[CS_RAW].basetime[CLOCK_MONOTONIC_RAW];
      61                 :      98549 :         vdso_ts->sec = tk->raw_sec;
      62                 :      98549 :         vdso_ts->nsec        = tk->tkr_raw.xtime_nsec;
      63                 :            : 
      64                 :            :         /* CLOCK_TAI */
      65                 :      98549 :         vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI];
      66                 :      98549 :         vdso_ts->sec = tk->xtime_sec + (s64)tk->tai_offset;
      67                 :      98549 :         vdso_ts->nsec        = tk->tkr_mono.xtime_nsec;
      68                 :      98549 : }
      69                 :            : 
      70                 :      98549 : void update_vsyscall(struct timekeeper *tk)
      71                 :            : {
      72                 :      98549 :         struct vdso_data *vdata = __arch_get_k_vdso_data();
      73                 :      98549 :         struct vdso_timestamp *vdso_ts;
      74                 :      98549 :         u64 nsec;
      75                 :            : 
      76                 :            :         /* copy vsyscall data */
      77                 :      98549 :         vdso_write_begin(vdata);
      78                 :            : 
      79                 :      98549 :         vdata[CS_HRES_COARSE].clock_mode        = __arch_get_clock_mode(tk);
      80                 :      98549 :         vdata[CS_RAW].clock_mode                = __arch_get_clock_mode(tk);
      81                 :            : 
      82                 :            :         /* CLOCK_REALTIME also required for time() */
      83                 :      98549 :         vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME];
      84                 :      98549 :         vdso_ts->sec = tk->xtime_sec;
      85                 :      98549 :         vdso_ts->nsec        = tk->tkr_mono.xtime_nsec;
      86                 :            : 
      87                 :            :         /* CLOCK_REALTIME_COARSE */
      88                 :      98549 :         vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME_COARSE];
      89                 :      98549 :         vdso_ts->sec = tk->xtime_sec;
      90                 :      98549 :         vdso_ts->nsec        = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
      91                 :            : 
      92                 :            :         /* CLOCK_MONOTONIC_COARSE */
      93                 :      98549 :         vdso_ts         = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC_COARSE];
      94                 :      98549 :         vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec;
      95                 :      98549 :         nsec            = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
      96                 :      98549 :         nsec            = nsec + tk->wall_to_monotonic.tv_nsec;
      97                 :      98549 :         vdso_ts->sec += __iter_div_u64_rem(nsec, NSEC_PER_SEC, &vdso_ts->nsec);
      98                 :            : 
      99                 :            :         /*
     100                 :            :          * Read without the seqlock held by clock_getres().
     101                 :            :          * Note: No need to have a second copy.
     102                 :            :          */
     103                 :      98549 :         WRITE_ONCE(vdata[CS_HRES_COARSE].hrtimer_res, hrtimer_resolution);
     104                 :            : 
     105                 :            :         /*
     106                 :            :          * Architectures can opt out of updating the high resolution part
     107                 :            :          * of the VDSO.
     108                 :            :          */
     109                 :      98549 :         if (__arch_update_vdso_data())
     110                 :      98549 :                 update_vdso_data(vdata, tk);
     111                 :            : 
     112                 :      98549 :         __arch_update_vsyscall(vdata, tk);
     113                 :            : 
     114                 :      98549 :         vdso_write_end(vdata);
     115                 :            : 
     116                 :      98549 :         __arch_sync_vdso_data(vdata);
     117                 :      98549 : }
     118                 :            : 
     119                 :         30 : void update_vsyscall_tz(void)
     120                 :            : {
     121                 :         30 :         struct vdso_data *vdata = __arch_get_k_vdso_data();
     122                 :            : 
     123                 :         30 :         vdata[CS_HRES_COARSE].tz_minuteswest = sys_tz.tz_minuteswest;
     124                 :         30 :         vdata[CS_HRES_COARSE].tz_dsttime = sys_tz.tz_dsttime;
     125                 :            : 
     126                 :         30 :         __arch_sync_vdso_data(vdata);
     127                 :         30 : }

Generated by: LCOV version 1.14