^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) // Copyright (C) 2005-2017 Andes Technology Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/compiler.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/hrtimer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <asm/barrier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/vdso_datapage.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/vdso_timer_info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/asm-offsets.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define X(x) #x
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define Y(x) X(x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) extern struct vdso_data *__get_datapage(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) extern struct vdso_data *__get_timerpage(void);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static notrace unsigned int __vdso_read_begin(const struct vdso_data *vdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) u32 seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) repeat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) seq = READ_ONCE(vdata->seq_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (seq & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) goto repeat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static notrace unsigned int vdso_read_begin(const struct vdso_data *vdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned int seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) seq = __vdso_read_begin(vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) smp_rmb(); /* Pairs with smp_wmb in vdso_write_end */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static notrace int vdso_read_retry(const struct vdso_data *vdata, u32 start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) smp_rmb(); /* Pairs with smp_wmb in vdso_write_begin */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return vdata->seq_count != start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static notrace long clock_gettime_fallback(clockid_t _clkid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) struct __kernel_old_timespec *_ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) register struct __kernel_old_timespec *ts asm("$r1") = _ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) register clockid_t clkid asm("$r0") = _clkid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) register long ret asm("$r0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) asm volatile ("movi $r15, %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) "syscall 0x0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) :"=r" (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) :"r"(clkid), "r"(ts), "i"(__NR_clock_gettime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) :"$r15", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static notrace int do_realtime_coarse(struct __kernel_old_timespec *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct vdso_data *vdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u32 seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) seq = vdso_read_begin(vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) ts->tv_sec = vdata->xtime_coarse_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) ts->tv_nsec = vdata->xtime_coarse_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) } while (vdso_read_retry(vdata, seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static notrace int do_monotonic_coarse(struct __kernel_old_timespec *ts,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct vdso_data *vdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u32 seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) u64 ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) seq = vdso_read_begin(vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ts->tv_sec = vdata->xtime_coarse_sec + vdata->wtm_clock_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ns = vdata->xtime_coarse_nsec + vdata->wtm_clock_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) } while (vdso_read_retry(vdata, seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) ts->tv_nsec = ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static notrace inline u64 vgetsns(struct vdso_data *vdso)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u32 cycle_now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u32 cycle_delta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) u32 *timer_cycle_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) timer_cycle_base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) (u32 *) ((char *)__get_timerpage() + vdso->cycle_count_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) cycle_now = readl_relaxed(timer_cycle_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) if (true == vdso->cycle_count_down)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) cycle_now = ~(*timer_cycle_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) cycle_delta = cycle_now - (u32) vdso->cs_cycle_last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return ((u64) cycle_delta & vdso->cs_mask) * vdso->cs_mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static notrace int do_realtime(struct __kernel_old_timespec *ts, struct vdso_data *vdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u64 ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) count = vdso_read_begin(vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ts->tv_sec = vdata->xtime_clock_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ns = vdata->xtime_clock_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) ns += vgetsns(vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ns >>= vdata->cs_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } while (vdso_read_retry(vdata, count));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ts->tv_nsec = ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static notrace int do_monotonic(struct __kernel_old_timespec *ts, struct vdso_data *vdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) u64 ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) u32 seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) seq = vdso_read_begin(vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ts->tv_sec = vdata->xtime_clock_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ns = vdata->xtime_clock_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) ns += vgetsns(vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ns >>= vdata->cs_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ts->tv_sec += vdata->wtm_clock_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ns += vdata->wtm_clock_nsec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) } while (vdso_read_retry(vdata, seq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) ts->tv_nsec = ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) notrace int __vdso_clock_gettime(clockid_t clkid, struct __kernel_old_timespec *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct vdso_data *vdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) int ret = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) vdata = __get_datapage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (vdata->cycle_count_offset == EMPTY_REG_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return clock_gettime_fallback(clkid, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) switch (clkid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) case CLOCK_REALTIME_COARSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ret = do_realtime_coarse(ts, vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) case CLOCK_MONOTONIC_COARSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) ret = do_monotonic_coarse(ts, vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case CLOCK_REALTIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) ret = do_realtime(ts, vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) case CLOCK_MONOTONIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = do_monotonic(ts, vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) ret = clock_gettime_fallback(clkid, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static notrace int clock_getres_fallback(clockid_t _clk_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct __kernel_old_timespec *_res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) register clockid_t clk_id asm("$r0") = _clk_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) register struct __kernel_old_timespec *res asm("$r1") = _res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) register int ret asm("$r0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) asm volatile ("movi $r15, %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) "syscall 0x0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) :"=r" (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) :"r"(clk_id), "r"(res), "i"(__NR_clock_getres)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) :"$r15", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) notrace int __vdso_clock_getres(clockid_t clk_id, struct __kernel_old_timespec *res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) struct vdso_data *vdata = __get_datapage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (res == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) switch (clk_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) case CLOCK_REALTIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) case CLOCK_MONOTONIC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case CLOCK_MONOTONIC_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) res->tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) res->tv_nsec = vdata->hrtimer_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) case CLOCK_REALTIME_COARSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) case CLOCK_MONOTONIC_COARSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) res->tv_sec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) res->tv_nsec = CLOCK_COARSE_RES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return clock_getres_fallback(clk_id, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) static notrace inline int gettimeofday_fallback(struct __kernel_old_timeval *_tv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) struct timezone *_tz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) register struct __kernel_old_timeval *tv asm("$r0") = _tv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) register struct timezone *tz asm("$r1") = _tz;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) register int ret asm("$r0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) asm volatile ("movi $r15, %3\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) "syscall 0x0\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) :"=r" (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) :"r"(tv), "r"(tz), "i"(__NR_gettimeofday)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) :"$r15", "memory");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) notrace int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct __kernel_old_timespec ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct vdso_data *vdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) vdata = __get_datapage();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (vdata->cycle_count_offset == EMPTY_REG_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return gettimeofday_fallback(tv, tz);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) ret = do_realtime(&ts, vdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) if (tv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) tv->tv_sec = ts.tv_sec;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) tv->tv_usec = ts.tv_nsec / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (tz) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) tz->tz_minuteswest = vdata->tz_minuteswest;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) tz->tz_dsttime = vdata->tz_dsttime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }