| 1 | |
| 2 | |
| 3 | * Generic sched_clock() support, to extend low level hardware time
|
| 4 | * counters to full 64-bit ns values.
|
| 5 |
|
| 6 | #include <linux/clocksource.h>
|
| 7 | #include <linux/init.h>
|
| 8 | #include <linux/jiffies.h>
|
| 9 | #include <linux/ktime.h>
|
| 10 | #include <linux/kernel.h>
|
| 11 | #include <linux/math.h>
|
| 12 | #include <linux/moduleparam.h>
|
| 13 | #include <linux/sched.h>
|
| 14 | #include <linux/sched/clock.h>
|
| 15 | #include <linux/syscore_ops.h>
|
| 16 | #include <linux/hrtimer.h>
|
| 17 | #include <linux/sched_clock.h>
|
| 18 | #include <linux/seqlock.h>
|
| 19 | #include <linux/bitops.h>
|
| 20 |
|
| 21 | #include "timekeeping.h"
|
| 22 |
|
| 23 | |
| 24 | * struct clock_data - all data needed for sched_clock() (including
|
| 25 | * registration of a new clock source)
|
| 26 | *
|
| 27 | * @seq: Sequence counter for protecting updates. The lowest
|
| 28 | * bit is the index for @read_data.
|
| 29 | * @read_data: Data required to read from sched_clock.
|
| 30 | * @wrap_kt: Duration for which clock can run before wrapping.
|
| 31 | * @rate: Tick rate of the registered clock.
|
| 32 | * @actual_read_sched_clock: Registered hardware level clock read function.
|
| 33 | *
|
| 34 | * The ordering of this structure has been chosen to optimize cache
|
| 35 | * performance. In particular 'seq' and 'read_data[0]' (combined) should fit
|
| 36 | * into a single 64-byte cache line.
|
| 37 |
|
| 38 | struct clock_data {
|
| 39 | seqcount_latch_t seq;
|
| 40 | struct clock_read_data read_data[2];
|
| 41 | ktime_t wrap_kt;
|
| 42 | unsigned long rate;
|
| 43 |
|
| 44 | u64 (*actual_read_sched_clock)(void);
|
| 45 | };
|
| 46 |
|
| 47 | static struct hrtimer sched_clock_timer;
|
| 48 | static int irqtime = -1;
|
| 49 |
|
| 50 | core_param(irqtime, irqtime, int, 0400);
|
| 51 |
|
| 52 | static u64 notrace jiffy_sched_clock_read(void)
|
| 53 | {
|
| 54 | |
| 55 | * We don't need to use get_jiffies_64 on 32-bit arches here
|
| 56 | * because we register with BITS_PER_LONG
|
| 57 |
|
| 58 | return (u64)(jiffies - INITIAL_JIFFIES);
|
| 59 | }
|
| 60 |
|
| 61 | static struct clock_data cd ____cacheline_aligned = {
|
| 62 | .read_data[0] = { .mult = NSEC_PER_SEC / HZ,
|
| 63 | .read_sched_clock = jiffy_sched_clock_read, },
|
| 64 | .actual_read_sched_clock = jiffy_sched_clock_read,
|
| 65 | };
|
| 66 |
|
| 67 | static __always_inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
|
| 68 | {
|
| 69 | return (cyc * mult) >> shift;
|
| 70 | }
|
| 71 |
|
| 72 | notrace struct clock_read_data *sched_clock_read_begin(unsigned int *seq)
|
| 73 | {
|
| 74 | *seq = read_seqcount_latch(&cd.seq);
|
| 75 | return cd.read_data + (*seq & 1);
|
| 76 | }
|
| 77 |
|
| 78 | notrace int sched_clock_read_retry(unsigned int seq)
|
| 79 | {
|
| 80 | return read_seqcount_latch_retry(&cd.seq, seq);
|
| 81 | }
|
| 82 |
|
| 83 | static __always_inline unsigned long long __sched_clock(void)
|
| 84 | {
|
| 85 | struct clock_read_data *rd;
|
| 86 | unsigned int seq;
|
| 87 | u64 cyc, res;
|
| 88 |
|
| 89 | do {
|
| 90 | seq = raw_read_seqcount_latch(&cd.seq);
|
| 91 | rd = cd.read_data + (seq & 1);
|
| 92 |
|
| 93 | cyc = (rd->read_sched_clock() - rd->epoch_cyc) &
|
| 94 | rd->sched_clock_mask;
|
| 95 | res = rd->epoch_ns + cyc_to_ns(cyc, rd->mult, rd->shift);
|
| 96 | } while (raw_read_seqcount_latch_retry(&cd.seq, seq));
|
| 97 |
|
| 98 | return res;
|
| 99 | }
|
| 100 |
|
| 101 | unsigned long long noinstr sched_clock_noinstr(void)
|
| 102 | {
|
| 103 | return __sched_clock();
|
| 104 | }
|
| 105 |
|
| 106 | unsigned long long notrace sched_clock(void)
|
| 107 | {
|
| 108 | unsigned long long ns;
|
| 109 | preempt_disable_notrace();
|
| 110 | |
| 111 | * All of __sched_clock() is a seqcount_latch reader critical section,
|
| 112 | * but relies on the raw helpers which are uninstrumented. For KCSAN,
|
| 113 | * mark all accesses in __sched_clock() as atomic.
|
| 114 |
|
| 115 | kcsan_nestable_atomic_begin();
|
| 116 | ns = __sched_clock();
|
| 117 | kcsan_nestable_atomic_end();
|
| 118 | preempt_enable_notrace();
|
| 119 | return ns;
|
| 120 | }
|
| 121 |
|
| 122 | |
| 123 | * Updating the data required to read the clock.
|
| 124 | *
|
| 125 | * sched_clock() will never observe mis-matched data even if called from
|
| 126 | * an NMI. We do this by maintaining an odd/even copy of the data and
|
| 127 | * steering sched_clock() to one or the other using a sequence counter.
|
| 128 | * In order to preserve the data cache profile of sched_clock() as much
|
| 129 | * as possible the system reverts back to the even copy when the update
|
| 130 | * completes; the odd copy is used *only* during an update.
|
| 131 |
|
| 132 | static void update_clock_read_data(struct clock_read_data *rd)
|
| 133 | {
|
| 134 |
|
| 135 | write_seqcount_latch_begin(&cd.seq);
|
| 136 |
|
| 137 |
|
| 138 | cd.read_data[0] = *rd;
|
| 139 |
|
| 140 |
|
| 141 | write_seqcount_latch(&cd.seq);
|
| 142 |
|
| 143 |
|
| 144 | cd.read_data[1] = *rd;
|
| 145 |
|
| 146 | write_seqcount_latch_end(&cd.seq);
|
| 147 | }
|
| 148 |
|
| 149 | |
| 150 | * Atomically update the sched_clock() epoch.
|
| 151 |
|
| 152 | static void update_sched_clock(void)
|
| 153 | {
|
| 154 | u64 cyc;
|
| 155 | u64 ns;
|
| 156 | struct clock_read_data rd;
|
| 157 |
|
| 158 | rd = cd.read_data[0];
|
| 159 |
|
| 160 | cyc = cd.actual_read_sched_clock();
|
| 161 | ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift);
|
| 162 |
|
| 163 | rd.epoch_ns = ns;
|
| 164 | rd.epoch_cyc = cyc;
|
| 165 |
|
| 166 | update_clock_read_data(&rd);
|
| 167 | }
|
| 168 |
|
| 169 | static enum hrtimer_restart sched_clock_poll(struct hrtimer *hrt)
|
| 170 | {
|
| 171 | update_sched_clock();
|
| 172 | hrtimer_forward_now(hrt, cd.wrap_kt);
|
| 173 |
|
| 174 | return HRTIMER_RESTART;
|
| 175 | }
|
| 176 |
|
| 177 | void sched_clock_register(u64 (*read)(void), int bits, unsigned long rate)
|
| 178 | {
|
| 179 | u64 res, wrap, new_mask, new_epoch, cyc, ns;
|
| 180 | u32 new_mult, new_shift;
|
| 181 | unsigned long r, flags;
|
| 182 | char r_unit;
|
| 183 | struct clock_read_data rd;
|
| 184 |
|
| 185 | if (cd.rate > rate)
|
| 186 | return;
|
| 187 |
|
| 188 |
|
| 189 | local_irq_save(flags);
|
| 190 |
|
| 191 |
|
| 192 | clocks_calc_mult_shift(&new_mult, &new_shift, rate, NSEC_PER_SEC, 3600);
|
| 193 |
|
| 194 | new_mask = CLOCKSOURCE_MASK(bits);
|
| 195 | cd.rate = rate;
|
| 196 |
|
| 197 |
|
| 198 | wrap = clocks_calc_max_nsecs(new_mult, new_shift, 0, new_mask, NULL);
|
| 199 | cd.wrap_kt = ns_to_ktime(wrap);
|
| 200 |
|
| 201 | rd = cd.read_data[0];
|
| 202 |
|
| 203 |
|
| 204 | new_epoch = read();
|
| 205 | cyc = cd.actual_read_sched_clock();
|
| 206 | ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift);
|
| 207 | cd.actual_read_sched_clock = read;
|
| 208 |
|
| 209 | rd.read_sched_clock = read;
|
| 210 | rd.sched_clock_mask = new_mask;
|
| 211 | rd.mult = new_mult;
|
| 212 | rd.shift = new_shift;
|
| 213 | rd.epoch_cyc = new_epoch;
|
| 214 | rd.epoch_ns = ns;
|
| 215 |
|
| 216 | update_clock_read_data(&rd);
|
| 217 |
|
| 218 | if (ACCESS_PRIVATE(&sched_clock_timer, function) != NULL) {
|
| 219 |
|
| 220 | hrtimer_start(&sched_clock_timer, cd.wrap_kt,
|
| 221 | HRTIMER_MODE_REL_HARD);
|
| 222 | }
|
| 223 |
|
| 224 | r = rate;
|
| 225 | if (r >= 4000000) {
|
| 226 | r = DIV_ROUND_CLOSEST(r, 1000000);
|
| 227 | r_unit = 'M';
|
| 228 | } else if (r >= 4000) {
|
| 229 | r = DIV_ROUND_CLOSEST(r, 1000);
|
| 230 | r_unit = 'k';
|
| 231 | } else {
|
| 232 | r_unit = ' ';
|
| 233 | }
|
| 234 |
|
| 235 |
|
| 236 | res = cyc_to_ns(1ULL, new_mult, new_shift);
|
| 237 |
|
| 238 | pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lluns\n",
|
| 239 | bits, r, r_unit, res, wrap);
|
| 240 |
|
| 241 |
|
| 242 | if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
|
| 243 | enable_sched_clock_irqtime();
|
| 244 |
|
| 245 | local_irq_restore(flags);
|
| 246 |
|
| 247 | pr_debug("Registered %pS as sched_clock source\n", read);
|
| 248 | }
|
| 249 | EXPORT_SYMBOL_GPL(sched_clock_register);
|
| 250 |
|
| 251 | void __init generic_sched_clock_init(void)
|
| 252 | {
|
| 253 | |
| 254 | * If no sched_clock() function has been provided at that point,
|
| 255 | * make it the final one.
|
| 256 |
|
| 257 | if (cd.actual_read_sched_clock == jiffy_sched_clock_read)
|
| 258 | sched_clock_register(jiffy_sched_clock_read, BITS_PER_LONG, HZ);
|
| 259 |
|
| 260 | update_sched_clock();
|
| 261 |
|
| 262 | |
| 263 | * Start the timer to keep sched_clock() properly updated and
|
| 264 | * sets the initial epoch.
|
| 265 |
|
| 266 | hrtimer_setup(&sched_clock_timer, sched_clock_poll, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
|
| 267 | hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL_HARD);
|
| 268 | }
|
| 269 |
|
| 270 | |
| 271 | * Clock read function for use when the clock is suspended.
|
| 272 | *
|
| 273 | * This function makes it appear to sched_clock() as if the clock
|
| 274 | * stopped counting at its last update.
|
| 275 | *
|
| 276 | * This function must only be called from the critical
|
| 277 | * section in sched_clock(). It relies on the read_seqcount_retry()
|
| 278 | * at the end of the critical section to be sure we observe the
|
| 279 | * correct copy of 'epoch_cyc'.
|
| 280 |
|
| 281 | static u64 notrace suspended_sched_clock_read(void)
|
| 282 | {
|
| 283 | unsigned int seq = read_seqcount_latch(&cd.seq);
|
| 284 |
|
| 285 | return cd.read_data[seq & 1].epoch_cyc;
|
| 286 | }
|
| 287 |
|
| 288 | int sched_clock_suspend(void)
|
| 289 | {
|
| 290 | struct clock_read_data *rd = &cd.read_data[0];
|
| 291 |
|
| 292 | update_sched_clock();
|
| 293 | hrtimer_cancel(&sched_clock_timer);
|
| 294 | rd->read_sched_clock = suspended_sched_clock_read;
|
| 295 |
|
| 296 | return 0;
|
| 297 | }
|
| 298 |
|
| 299 | static int sched_clock_syscore_suspend(void *data)
|
| 300 | {
|
| 301 | return sched_clock_suspend();
|
| 302 | }
|
| 303 |
|
| 304 | void sched_clock_resume(void)
|
| 305 | {
|
| 306 | struct clock_read_data *rd = &cd.read_data[0];
|
| 307 |
|
| 308 | rd->epoch_cyc = cd.actual_read_sched_clock();
|
| 309 | hrtimer_start(&sched_clock_timer, cd.wrap_kt, HRTIMER_MODE_REL_HARD);
|
| 310 | rd->read_sched_clock = cd.actual_read_sched_clock;
|
| 311 | }
|
| 312 |
|
| 313 | static void sched_clock_syscore_resume(void *data)
|
| 314 | {
|
| 315 | sched_clock_resume();
|
| 316 | }
|
| 317 |
|
| 318 | static const struct syscore_ops sched_clock_syscore_ops = {
|
| 319 | .suspend = sched_clock_syscore_suspend,
|
| 320 | .resume = sched_clock_syscore_resume,
|
| 321 | };
|
| 322 |
|
| 323 | static struct syscore sched_clock_syscore = {
|
| 324 | .ops = &sched_clock_syscore_ops,
|
| 325 | };
|
| 326 |
|
| 327 | static int __init sched_clock_syscore_init(void)
|
| 328 | {
|
| 329 | register_syscore(&sched_clock_syscore);
|
| 330 |
|
| 331 | return 0;
|
| 332 | }
|
| 333 | device_initcall(sched_clock_syscore_init);
|