Line data Source code
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 149 : static u64 jiffies_read(struct clocksource *cs) 17 : { 18 149 : 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 1 : static int __init init_jiffies_clocksource(void) 65 : { 66 1 : return __clocksource_register(&clocksource_jiffies); 67 : } 68 : 69 : core_initcall(init_jiffies_clocksource); 70 : 71 2 : struct clocksource * __init __weak clocksource_default_clock(void) 72 : { 73 2 : return &clocksource_jiffies; 74 : } 75 : 76 : static struct clocksource refined_jiffies; 77 : 78 0 : int register_refined_jiffies(long cycles_per_second) 79 : { 80 : u64 nsec_per_tick, shift_hz; 81 : long cycles_per_tick; 82 : 83 : 84 : 85 0 : refined_jiffies = clocksource_jiffies; 86 0 : refined_jiffies.name = "refined-jiffies"; 87 0 : refined_jiffies.rating++; 88 : 89 : /* Calc cycles per tick */ 90 0 : cycles_per_tick = (cycles_per_second + HZ/2)/HZ; 91 : /* shift_hz stores hz<<8 for extra accuracy */ 92 0 : shift_hz = (u64)cycles_per_second << 8; 93 0 : shift_hz += cycles_per_tick/2; 94 0 : do_div(shift_hz, cycles_per_tick); 95 : /* Calculate nsec_per_tick using shift_hz */ 96 0 : nsec_per_tick = (u64)NSEC_PER_SEC << 8; 97 0 : nsec_per_tick += (u32)shift_hz/2; 98 0 : do_div(nsec_per_tick, (u32)shift_hz); 99 : 100 0 : refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT; 101 : 102 0 : __clocksource_register(&refined_jiffies); 103 0 : return 0; 104 : }