135728b82SThomas Gleixner // SPDX-License-Identifier: GPL-2.0
238ff87f7SStephen Boyd /*
358c5fc2bSThomas Gleixner * Generic sched_clock() support, to extend low level hardware time
458c5fc2bSThomas Gleixner * counters to full 64-bit ns values.
538ff87f7SStephen Boyd */
638ff87f7SStephen Boyd #include <linux/clocksource.h>
738ff87f7SStephen Boyd #include <linux/init.h>
838ff87f7SStephen Boyd #include <linux/jiffies.h>
9a08ca5d1SStephen Boyd #include <linux/ktime.h>
1038ff87f7SStephen Boyd #include <linux/kernel.h>
1192067440SMaciej W. Rozycki #include <linux/math.h>
1238ff87f7SStephen Boyd #include <linux/moduleparam.h>
1338ff87f7SStephen Boyd #include <linux/sched.h>
14e6017571SIngo Molnar #include <linux/sched/clock.h>
1538ff87f7SStephen Boyd #include <linux/syscore_ops.h>
16a08ca5d1SStephen Boyd #include <linux/hrtimer.h>
1738ff87f7SStephen Boyd #include <linux/sched_clock.h>
1885c3d2ddSStephen Boyd #include <linux/seqlock.h>
19e7e3ff1bSStephen Boyd #include <linux/bitops.h>
2038ff87f7SStephen Boyd
21086ee46bSBen Dooks (Codethink) #include "timekeeping.h"
22086ee46bSBen Dooks (Codethink)
23cf7c9c17SDaniel Thompson /**
2432fea568SIngo Molnar * struct clock_data - all data needed for sched_clock() (including
25cf7c9c17SDaniel Thompson * registration of a new clock source)
26cf7c9c17SDaniel Thompson *
271809bfa4SDaniel Thompson * @seq: Sequence counter for protecting updates. The lowest
281809bfa4SDaniel Thompson * bit is the index for @read_data.
29cf7c9c17SDaniel Thompson * @read_data: Data required to read from sched_clock.
3032fea568SIngo Molnar * @wrap_kt: Duration for which clock can run before wrapping.
3132fea568SIngo Molnar * @rate: Tick rate of the registered clock.
3232fea568SIngo Molnar * @actual_read_sched_clock: Registered hardware level clock read function.
33cf7c9c17SDaniel Thompson *
34cf7c9c17SDaniel Thompson * The ordering of this structure has been chosen to optimize cache
3532fea568SIngo Molnar * performance. In particular 'seq' and 'read_data[0]' (combined) should fit
3632fea568SIngo Molnar * into a single 64-byte cache line.
37cf7c9c17SDaniel Thompson */
38cf7c9c17SDaniel Thompson struct clock_data {
39a690ed07SAhmed S. Darwish seqcount_latch_t seq;
401809bfa4SDaniel Thompson struct clock_read_data read_data[2];
41cf7c9c17SDaniel Thompson ktime_t wrap_kt;
42cf7c9c17SDaniel Thompson unsigned long rate;
4332fea568SIngo Molnar
4413dbeb38SDaniel Thompson u64 (*actual_read_sched_clock)(void);
45cf7c9c17SDaniel Thompson };
46cf7c9c17SDaniel Thompson
47a08ca5d1SStephen Boyd static struct hrtimer sched_clock_timer;
4838ff87f7SStephen Boyd static int irqtime = -1;
4938ff87f7SStephen Boyd
5038ff87f7SStephen Boyd core_param(irqtime, irqtime, int, 0400);
5138ff87f7SStephen Boyd
jiffy_sched_clock_read(void)52e7e3ff1bSStephen Boyd static u64 notrace jiffy_sched_clock_read(void)
5338ff87f7SStephen Boyd {
54e7e3ff1bSStephen Boyd /*
55e7e3ff1bSStephen Boyd * We don't need to use get_jiffies_64 on 32-bit arches here
56e7e3ff1bSStephen Boyd * because we register with BITS_PER_LONG
57e7e3ff1bSStephen Boyd */
58e7e3ff1bSStephen Boyd return (u64)(jiffies - INITIAL_JIFFIES);
5938ff87f7SStephen Boyd }
6038ff87f7SStephen Boyd
61cf7c9c17SDaniel Thompson static struct clock_data cd ____cacheline_aligned = {
621809bfa4SDaniel Thompson .read_data[0] = { .mult = NSEC_PER_SEC / HZ,
63cf7c9c17SDaniel Thompson .read_sched_clock = jiffy_sched_clock_read, },
6413dbeb38SDaniel Thompson .actual_read_sched_clock = jiffy_sched_clock_read,
65cf7c9c17SDaniel Thompson };
6638ff87f7SStephen Boyd
cyc_to_ns(u64 cyc,u32 mult,u32 shift)675949a68cSPeter Zijlstra static __always_inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
6838ff87f7SStephen Boyd {
6938ff87f7SStephen Boyd return (cyc * mult) >> shift;
7038ff87f7SStephen Boyd }
7138ff87f7SStephen Boyd
sched_clock_read_begin(unsigned int * seq)724cd2bb12SQuanyang Wang notrace struct clock_read_data *sched_clock_read_begin(unsigned int *seq)
731b86abc1SPeter Zijlstra {
7493190bc3SMarco Elver *seq = read_seqcount_latch(&cd.seq);
751b86abc1SPeter Zijlstra return cd.read_data + (*seq & 1);
761b86abc1SPeter Zijlstra }
771b86abc1SPeter Zijlstra
sched_clock_read_retry(unsigned int seq)784cd2bb12SQuanyang Wang notrace int sched_clock_read_retry(unsigned int seq)
791b86abc1SPeter Zijlstra {
8093190bc3SMarco Elver return read_seqcount_latch_retry(&cd.seq, seq);
811b86abc1SPeter Zijlstra }
821b86abc1SPeter Zijlstra
__sched_clock(void)838ab40fc2SMarco Elver static __always_inline unsigned long long __sched_clock(void)
8438ff87f7SStephen Boyd {
851809bfa4SDaniel Thompson struct clock_read_data *rd;
865949a68cSPeter Zijlstra unsigned int seq;
875949a68cSPeter Zijlstra u64 cyc, res;
88336ae118SStephen Boyd
8938ff87f7SStephen Boyd do {
905949a68cSPeter Zijlstra seq = raw_read_seqcount_latch(&cd.seq);
915949a68cSPeter Zijlstra rd = cd.read_data + (seq & 1);
928710e914SDaniel Thompson
9313dbeb38SDaniel Thompson cyc = (rd->read_sched_clock() - rd->epoch_cyc) &
9413dbeb38SDaniel Thompson rd->sched_clock_mask;
9513dbeb38SDaniel Thompson res = rd->epoch_ns + cyc_to_ns(cyc, rd->mult, rd->shift);
965949a68cSPeter Zijlstra } while (raw_read_seqcount_latch_retry(&cd.seq, seq));
9738ff87f7SStephen Boyd
988710e914SDaniel Thompson return res;
9938ff87f7SStephen Boyd }
10038ff87f7SStephen Boyd
sched_clock_noinstr(void)1018ab40fc2SMarco Elver unsigned long long noinstr sched_clock_noinstr(void)
1028ab40fc2SMarco Elver {
1038ab40fc2SMarco Elver return __sched_clock();
1048ab40fc2SMarco Elver }
1058ab40fc2SMarco Elver
sched_clock(void)1065949a68cSPeter Zijlstra unsigned long long notrace sched_clock(void)
1075949a68cSPeter Zijlstra {
1085949a68cSPeter Zijlstra unsigned long long ns;
1095949a68cSPeter Zijlstra preempt_disable_notrace();
1108ab40fc2SMarco Elver /*
1118ab40fc2SMarco Elver * All of __sched_clock() is a seqcount_latch reader critical section,
1128ab40fc2SMarco Elver * but relies on the raw helpers which are uninstrumented. For KCSAN,
1138ab40fc2SMarco Elver * mark all accesses in __sched_clock() as atomic.
1148ab40fc2SMarco Elver */
1158ab40fc2SMarco Elver kcsan_nestable_atomic_begin();
1168ab40fc2SMarco Elver ns = __sched_clock();
1178ab40fc2SMarco Elver kcsan_nestable_atomic_end();
1185949a68cSPeter Zijlstra preempt_enable_notrace();
1195949a68cSPeter Zijlstra return ns;
1205949a68cSPeter Zijlstra }
1215949a68cSPeter Zijlstra
12238ff87f7SStephen Boyd /*
1231809bfa4SDaniel Thompson * Updating the data required to read the clock.
1241809bfa4SDaniel Thompson *
12532fea568SIngo Molnar * sched_clock() will never observe mis-matched data even if called from
1261809bfa4SDaniel Thompson * an NMI. We do this by maintaining an odd/even copy of the data and
12732fea568SIngo Molnar * steering sched_clock() to one or the other using a sequence counter.
12832fea568SIngo Molnar * In order to preserve the data cache profile of sched_clock() as much
1291809bfa4SDaniel Thompson * as possible the system reverts back to the even copy when the update
1301809bfa4SDaniel Thompson * completes; the odd copy is used *only* during an update.
1311809bfa4SDaniel Thompson */
update_clock_read_data(struct clock_read_data * rd)1321809bfa4SDaniel Thompson static void update_clock_read_data(struct clock_read_data *rd)
1331809bfa4SDaniel Thompson {
1341809bfa4SDaniel Thompson /* steer readers towards the odd copy */
13593190bc3SMarco Elver write_seqcount_latch_begin(&cd.seq);
1361809bfa4SDaniel Thompson
1371809bfa4SDaniel Thompson /* now its safe for us to update the normal (even) copy */
1381809bfa4SDaniel Thompson cd.read_data[0] = *rd;
1391809bfa4SDaniel Thompson
1401809bfa4SDaniel Thompson /* switch readers back to the even copy */
14193190bc3SMarco Elver write_seqcount_latch(&cd.seq);
1421139c71dSMarco Elver
1431139c71dSMarco Elver /* update the backup (odd) copy with the new data */
1441139c71dSMarco Elver cd.read_data[1] = *rd;
14593190bc3SMarco Elver
14693190bc3SMarco Elver write_seqcount_latch_end(&cd.seq);
1471809bfa4SDaniel Thompson }
1481809bfa4SDaniel Thompson
1491809bfa4SDaniel Thompson /*
15032fea568SIngo Molnar * Atomically update the sched_clock() epoch.
15138ff87f7SStephen Boyd */
update_sched_clock(void)1529fee69a8SDaniel Thompson static void update_sched_clock(void)
15338ff87f7SStephen Boyd {
154e7e3ff1bSStephen Boyd u64 cyc;
15538ff87f7SStephen Boyd u64 ns;
1561809bfa4SDaniel Thompson struct clock_read_data rd;
1571809bfa4SDaniel Thompson
1581809bfa4SDaniel Thompson rd = cd.read_data[0];
15938ff87f7SStephen Boyd
16013dbeb38SDaniel Thompson cyc = cd.actual_read_sched_clock();
16132fea568SIngo Molnar ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift);
16285c3d2ddSStephen Boyd
1631809bfa4SDaniel Thompson rd.epoch_ns = ns;
1641809bfa4SDaniel Thompson rd.epoch_cyc = cyc;
1651809bfa4SDaniel Thompson
1661809bfa4SDaniel Thompson update_clock_read_data(&rd);
16738ff87f7SStephen Boyd }
16838ff87f7SStephen Boyd
sched_clock_poll(struct hrtimer * hrt)169a08ca5d1SStephen Boyd static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
17038ff87f7SStephen Boyd {
17138ff87f7SStephen Boyd update_sched_clock();
172a08ca5d1SStephen Boyd hrtimer_forward_now(hrt, cd.wrap_kt);
17332fea568SIngo Molnar
174a08ca5d1SStephen Boyd return HRTIMER_RESTART;
17538ff87f7SStephen Boyd }
17638ff87f7SStephen Boyd
17732fea568SIngo Molnar void __init
sched_clock_register(u64 (* read)(void),int bits,unsigned long rate)17832fea568SIngo Molnar sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
17938ff87f7SStephen Boyd {
1805ae8aabeSStephen Boyd u64 res, wrap, new_mask, new_epoch, cyc, ns;
1815ae8aabeSStephen Boyd u32 new_mult, new_shift;
18227077455SPaul Cercueil unsigned long r, flags;
18338ff87f7SStephen Boyd char r_unit;
1841809bfa4SDaniel Thompson struct clock_read_data rd;
18538ff87f7SStephen Boyd
18638ff87f7SStephen Boyd if (cd.rate > rate)
18738ff87f7SStephen Boyd return;
18838ff87f7SStephen Boyd
18927077455SPaul Cercueil /* Cannot register a sched_clock with interrupts on */
19027077455SPaul Cercueil local_irq_save(flags);
19138ff87f7SStephen Boyd
19232fea568SIngo Molnar /* Calculate the mult/shift to convert counter ticks to ns. */
1935ae8aabeSStephen Boyd clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
1945ae8aabeSStephen Boyd
1955ae8aabeSStephen Boyd new_mask = CLOCKSOURCE_MASK(bits);
1968710e914SDaniel Thompson cd.rate = rate;
1975ae8aabeSStephen Boyd
19832fea568SIngo Molnar /* Calculate how many nanosecs until we risk wrapping */
199fb82fe2fSJohn Stultz wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask, NULL);
2008710e914SDaniel Thompson cd.wrap_kt = ns_to_ktime(wrap);
2015ae8aabeSStephen Boyd
2021809bfa4SDaniel Thompson rd = cd.read_data[0];
2031809bfa4SDaniel Thompson
20432fea568SIngo Molnar /* Update epoch for new counter and update 'epoch_ns' from old counter*/
2055ae8aabeSStephen Boyd new_epoch = read();
20613dbeb38SDaniel Thompson cyc = cd.actual_read_sched_clock();
20732fea568SIngo Molnar ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift);
20813dbeb38SDaniel Thompson cd.actual_read_sched_clock = read;
2095ae8aabeSStephen Boyd
2101809bfa4SDaniel Thompson rd.read_sched_clock = read;
2111809bfa4SDaniel Thompson rd.sched_clock_mask = new_mask;
2121809bfa4SDaniel Thompson rd.mult = new_mult;
2131809bfa4SDaniel Thompson rd.shift = new_shift;
2141809bfa4SDaniel Thompson rd.epoch_cyc = new_epoch;
2151809bfa4SDaniel Thompson rd.epoch_ns = ns;
21632fea568SIngo Molnar
2171809bfa4SDaniel Thompson update_clock_read_data(&rd);
21838ff87f7SStephen Boyd
2191b8955bcSDavid Engraf if (sched_clock_timer.function != NULL) {
2201b8955bcSDavid Engraf /* update timeout for clock wrap */
2212c8bd588SAhmed S. Darwish hrtimer_start(&sched_clock_timer, cd.wrap_kt,
2222c8bd588SAhmed S. Darwish HRTIMER_MODE_REL_HARD);
2231b8955bcSDavid Engraf }
2241b8955bcSDavid Engraf
22538ff87f7SStephen Boyd r = rate;
22638ff87f7SStephen Boyd if (r >= 4000000) {
22792067440SMaciej W. Rozycki r = DIV_ROUND_CLOSEST(r, 1000000);
22838ff87f7SStephen Boyd r_unit = 'M';
229f4b62e1eSMaciej W. Rozycki } else if (r >= 4000) {
23092067440SMaciej W. Rozycki r = DIV_ROUND_CLOSEST(r, 1000);
23138ff87f7SStephen Boyd r_unit = 'k';
23232fea568SIngo Molnar } else {
23338ff87f7SStephen Boyd r_unit = ' ';
23432fea568SIngo Molnar }
23538ff87f7SStephen Boyd
23632fea568SIngo Molnar /* Calculate the ns resolution of this counter */
2375ae8aabeSStephen Boyd res = cyc_to_ns(1ULL, new_mult, new_shift);
2385ae8aabeSStephen Boyd
239a08ca5d1SStephen Boyd pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
240a08ca5d1SStephen Boyd bits, r, r_unit, res, wrap);
24138ff87f7SStephen Boyd
24232fea568SIngo Molnar /* Enable IRQ time accounting if we have a fast enough sched_clock() */
24338ff87f7SStephen Boyd if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
24438ff87f7SStephen Boyd enable_sched_clock_irqtime();
24538ff87f7SStephen Boyd
24627077455SPaul Cercueil local_irq_restore(flags);
24727077455SPaul Cercueil
248d75f773cSSakari Ailus pr_debug("Registered %pS as sched_clock source\n", read);
24938ff87f7SStephen Boyd }
25038ff87f7SStephen Boyd
generic_sched_clock_init(void)2515d2a4e91SPavel Tatashin void __init generic_sched_clock_init(void)
25238ff87f7SStephen Boyd {
25338ff87f7SStephen Boyd /*
25432fea568SIngo Molnar * If no sched_clock() function has been provided at that point,
255b0294f30SRandy Dunlap * make it the final one.
25638ff87f7SStephen Boyd */
25713dbeb38SDaniel Thompson if (cd.actual_read_sched_clock == jiffy_sched_clock_read)
258e7e3ff1bSStephen Boyd sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
25938ff87f7SStephen Boyd
260a08ca5d1SStephen Boyd update_sched_clock();
261a08ca5d1SStephen Boyd
262a08ca5d1SStephen Boyd /*
263a08ca5d1SStephen Boyd * Start the timer to keep sched_clock() properly updated and
264a08ca5d1SStephen Boyd * sets the initial epoch.
265a08ca5d1SStephen Boyd */
266*f66b0acfSNam Cao hrtimer_setup(&sched_clock_timer, sched_clock_poll, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
2672c8bd588SAhmed S. Darwish hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL_HARD);
26838ff87f7SStephen Boyd }
26938ff87f7SStephen Boyd
27013dbeb38SDaniel Thompson /*
27113dbeb38SDaniel Thompson * Clock read function for use when the clock is suspended.
27213dbeb38SDaniel Thompson *
27313dbeb38SDaniel Thompson * This function makes it appear to sched_clock() as if the clock
27413dbeb38SDaniel Thompson * stopped counting at its last update.
2751809bfa4SDaniel Thompson *
2761809bfa4SDaniel Thompson * This function must only be called from the critical
2771809bfa4SDaniel Thompson * section in sched_clock(). It relies on the read_seqcount_retry()
2781809bfa4SDaniel Thompson * at the end of the critical section to be sure we observe the
27932fea568SIngo Molnar * correct copy of 'epoch_cyc'.
28013dbeb38SDaniel Thompson */
suspended_sched_clock_read(void)28113dbeb38SDaniel Thompson static u64 notrace suspended_sched_clock_read(void)
28213dbeb38SDaniel Thompson {
28393190bc3SMarco Elver unsigned int seq = read_seqcount_latch(&cd.seq);
2841809bfa4SDaniel Thompson
2851809bfa4SDaniel Thompson return cd.read_data[seq & 1].epoch_cyc;
28613dbeb38SDaniel Thompson }
28713dbeb38SDaniel Thompson
sched_clock_suspend(void)2883f2552f7SChang-An Chen int sched_clock_suspend(void)
28938ff87f7SStephen Boyd {
2901809bfa4SDaniel Thompson struct clock_read_data *rd = &cd.read_data[0];
291cf7c9c17SDaniel Thompson
292f723aa18SStephen Boyd update_sched_clock();
293f723aa18SStephen Boyd hrtimer_cancel(&sched_clock_timer);
29413dbeb38SDaniel Thompson rd->read_sched_clock = suspended_sched_clock_read;
29532fea568SIngo Molnar
29638ff87f7SStephen Boyd return 0;
29738ff87f7SStephen Boyd }
29838ff87f7SStephen Boyd
sched_clock_resume(void)2993f2552f7SChang-An Chen void sched_clock_resume(void)
30038ff87f7SStephen Boyd {
3011809bfa4SDaniel Thompson struct clock_read_data *rd = &cd.read_data[0];
302cf7c9c17SDaniel Thompson
30313dbeb38SDaniel Thompson rd->epoch_cyc = cd.actual_read_sched_clock();
3042c8bd588SAhmed S. Darwish hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL_HARD);
30513dbeb38SDaniel Thompson rd->read_sched_clock = cd.actual_read_sched_clock;
30638ff87f7SStephen Boyd }
30738ff87f7SStephen Boyd
30838ff87f7SStephen Boyd static struct syscore_ops sched_clock_ops = {
30938ff87f7SStephen Boyd .suspend = sched_clock_suspend,
31038ff87f7SStephen Boyd .resume = sched_clock_resume,
31138ff87f7SStephen Boyd };
31238ff87f7SStephen Boyd
sched_clock_syscore_init(void)31338ff87f7SStephen Boyd static int __init sched_clock_syscore_init(void)
31438ff87f7SStephen Boyd {
31538ff87f7SStephen Boyd register_syscore_ops(&sched_clock_ops);
31632fea568SIngo Molnar
31738ff87f7SStephen Boyd return 0;
31838ff87f7SStephen Boyd }
31938ff87f7SStephen Boyd device_initcall(sched_clock_syscore_init);
320