| 1 | // SPDX-License-Identifier: GPL-2.0+ | 
|---|
| 2 | /* | 
|---|
| 3 | * This file contains the jiffies based clocksource. | 
|---|
| 4 | * | 
|---|
| 5 | * Copyright (C) 2004, 2005 IBM, John Stultz (johnstul@us.ibm.com) | 
|---|
| 6 | */ | 
|---|
| 7 | #include <linux/clocksource.h> | 
|---|
| 8 | #include <linux/jiffies.h> | 
|---|
| 9 | #include <linux/module.h> | 
|---|
| 10 | #include <linux/init.h> | 
|---|
| 11 |  | 
|---|
| 12 | #include "timekeeping.h" | 
|---|
| 13 | #include "tick-internal.h" | 
|---|
| 14 |  | 
|---|
| 15 |  | 
|---|
| 16 | static u64 jiffies_read(struct clocksource *cs) | 
|---|
| 17 | { | 
|---|
| 18 | return (u64) jiffies; | 
|---|
| 19 | } | 
|---|
| 20 |  | 
|---|
| 21 | /* | 
|---|
| 22 | * The Jiffies based clocksource is the lowest common | 
|---|
| 23 | * denominator clock source which should function on | 
|---|
| 24 | * all systems. It has the same coarse resolution as | 
|---|
| 25 | * the timer interrupt frequency HZ and it suffers | 
|---|
| 26 | * inaccuracies caused by missed or lost timer | 
|---|
| 27 | * interrupts and the inability for the timer | 
|---|
| 28 | * interrupt hardware to accurately tick at the | 
|---|
| 29 | * requested HZ value. It is also not recommended | 
|---|
| 30 | * for "tick-less" systems. | 
|---|
| 31 | */ | 
|---|
| 32 | static struct clocksource clocksource_jiffies = { | 
|---|
| 33 | .name			= "jiffies", | 
|---|
| 34 | .rating			= 1, /* lowest valid rating*/ | 
|---|
| 35 | .uncertainty_margin	= 32 * NSEC_PER_MSEC, | 
|---|
| 36 | .read			= jiffies_read, | 
|---|
| 37 | .mask			= CLOCKSOURCE_MASK(32), | 
|---|
| 38 | .mult			= TICK_NSEC << JIFFIES_SHIFT, /* details above */ | 
|---|
| 39 | .shift			= JIFFIES_SHIFT, | 
|---|
| 40 | .max_cycles		= 10, | 
|---|
| 41 | }; | 
|---|
| 42 |  | 
|---|
| 43 | __cacheline_aligned_in_smp DEFINE_RAW_SPINLOCK(jiffies_lock); | 
|---|
| 44 | __cacheline_aligned_in_smp seqcount_raw_spinlock_t jiffies_seq = | 
|---|
| 45 | SEQCNT_RAW_SPINLOCK_ZERO(jiffies_seq, &jiffies_lock); | 
|---|
| 46 |  | 
|---|
| 47 | #if (BITS_PER_LONG < 64) | 
|---|
| 48 | u64 get_jiffies_64(void) | 
|---|
| 49 | { | 
|---|
| 50 | unsigned int seq; | 
|---|
| 51 | u64 ret; | 
|---|
| 52 |  | 
|---|
| 53 | do { | 
|---|
| 54 | seq = read_seqcount_begin(&jiffies_seq); | 
|---|
| 55 | ret = jiffies_64; | 
|---|
| 56 | } while (read_seqcount_retry(&jiffies_seq, seq)); | 
|---|
| 57 | return ret; | 
|---|
| 58 | } | 
|---|
| 59 | EXPORT_SYMBOL(get_jiffies_64); | 
|---|
| 60 | #endif | 
|---|
| 61 |  | 
|---|
| 62 | EXPORT_SYMBOL(jiffies); | 
|---|
| 63 |  | 
|---|
| 64 | static int __init init_jiffies_clocksource(void) | 
|---|
| 65 | { | 
|---|
| 66 | return __clocksource_register(cs: &clocksource_jiffies); | 
|---|
| 67 | } | 
|---|
| 68 |  | 
|---|
| 69 | core_initcall(init_jiffies_clocksource); | 
|---|
| 70 |  | 
|---|
| 71 | struct clocksource * __init __weak clocksource_default_clock(void) | 
|---|
| 72 | { | 
|---|
| 73 | return &clocksource_jiffies; | 
|---|
| 74 | } | 
|---|
| 75 |  | 
|---|
| 76 | static struct clocksource refined_jiffies; | 
|---|
| 77 |  | 
|---|
| 78 | void __init register_refined_jiffies(long cycles_per_second) | 
|---|
| 79 | { | 
|---|
| 80 | u64 nsec_per_tick, shift_hz; | 
|---|
| 81 | long cycles_per_tick; | 
|---|
| 82 |  | 
|---|
| 83 | refined_jiffies = clocksource_jiffies; | 
|---|
| 84 | refined_jiffies.name = "refined-jiffies"; | 
|---|
| 85 | refined_jiffies.rating++; | 
|---|
| 86 |  | 
|---|
| 87 | /* Calc cycles per tick */ | 
|---|
| 88 | cycles_per_tick = (cycles_per_second + HZ/2)/HZ; | 
|---|
| 89 | /* shift_hz stores hz<<8 for extra accuracy */ | 
|---|
| 90 | shift_hz = (u64)cycles_per_second << 8; | 
|---|
| 91 | shift_hz += cycles_per_tick/2; | 
|---|
| 92 | do_div(shift_hz, cycles_per_tick); | 
|---|
| 93 | /* Calculate nsec_per_tick using shift_hz */ | 
|---|
| 94 | nsec_per_tick = (u64)NSEC_PER_SEC << 8; | 
|---|
| 95 | nsec_per_tick += (u32)shift_hz/2; | 
|---|
| 96 | do_div(nsec_per_tick, (u32)shift_hz); | 
|---|
| 97 |  | 
|---|
| 98 | refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT; | 
|---|
| 99 |  | 
|---|
| 100 | __clocksource_register(cs: &refined_jiffies); | 
|---|
| 101 | } | 
|---|
| 102 |  | 
|---|