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 #include <linux/sysctl.h> 12 13 #include "timekeeping.h" 14 #include "tick-internal.h" 15 16 17 static u64 jiffies_read(struct clocksource *cs) 18 { 19 return (u64) jiffies; 20 } 21 22 /* 23 * The Jiffies based clocksource is the lowest common 24 * denominator clock source which should function on 25 * all systems. It has the same coarse resolution as 26 * the timer interrupt frequency HZ and it suffers 27 * inaccuracies caused by missed or lost timer 28 * interrupts and the inability for the timer 29 * interrupt hardware to accurately tick at the 30 * requested HZ value. It is also not recommended 31 * for "tick-less" systems. 32 */ 33 static struct clocksource clocksource_jiffies = { 34 .name = "jiffies", 35 .rating = 1, /* lowest valid rating*/ 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 bool cs_jiffies_registered __initdata; 65 66 struct clocksource * __init __weak clocksource_default_clock(void) 67 { 68 if (!cs_jiffies_registered) { 69 __clocksource_register(&clocksource_jiffies); 70 cs_jiffies_registered = true; 71 } 72 return &clocksource_jiffies; 73 } 74 75 static struct clocksource refined_jiffies; 76 77 void __init register_refined_jiffies(long cycles_per_second) 78 { 79 u64 nsec_per_tick, shift_hz; 80 long cycles_per_tick; 81 82 refined_jiffies = clocksource_jiffies; 83 refined_jiffies.name = "refined-jiffies"; 84 refined_jiffies.rating++; 85 86 /* Calc cycles per tick */ 87 cycles_per_tick = (cycles_per_second + HZ/2)/HZ; 88 /* shift_hz stores hz<<8 for extra accuracy */ 89 shift_hz = (u64)cycles_per_second << 8; 90 shift_hz += cycles_per_tick/2; 91 do_div(shift_hz, cycles_per_tick); 92 /* Calculate nsec_per_tick using shift_hz */ 93 nsec_per_tick = (u64)NSEC_PER_SEC << 8; 94 nsec_per_tick += (u32)shift_hz/2; 95 do_div(nsec_per_tick, (u32)shift_hz); 96 97 refined_jiffies.mult = ((u32)nsec_per_tick) << JIFFIES_SHIFT; 98 99 __clocksource_register(&refined_jiffies); 100 } 101 102 #ifdef CONFIG_SYSCTL 103 static ulong mult_hz(const ulong val) 104 { 105 if (val >= ULONG_MAX / HZ) 106 return ULONG_MAX; 107 return val * HZ; 108 } 109 110 static ulong div_hz(const ulong val) 111 { 112 return val / HZ; 113 } 114 115 static int sysctl_u2k_int_conv_hz(const bool *negp, const ulong *u_ptr, int *k_ptr) 116 { 117 return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, mult_hz); 118 } 119 120 static int sysctl_k2u_int_conv_hz(bool *negp, ulong *u_ptr, const int *k_ptr) 121 { 122 return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, div_hz); 123 } 124 125 static int sysctl_u2k_int_conv_userhz(const bool *negp, const ulong *u_ptr, int *k_ptr) 126 { 127 return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, clock_t_to_jiffies); 128 } 129 130 static ulong sysctl_jiffies_to_clock_t(const ulong val) 131 { 132 return jiffies_to_clock_t(val); 133 } 134 135 static int sysctl_k2u_int_conv_userhz(bool *negp, ulong *u_ptr, const int *k_ptr) 136 { 137 return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, sysctl_jiffies_to_clock_t); 138 } 139 140 static ulong sysctl_msecs_to_jiffies(const ulong val) 141 { 142 if (val > jiffies_to_msecs(MAX_JIFFY_OFFSET)) 143 return MAX_JIFFY_OFFSET; 144 return msecs_to_jiffies(val); 145 } 146 147 static int sysctl_u2k_int_conv_ms(const bool *negp, const ulong *u_ptr, int *k_ptr) 148 { 149 return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, sysctl_msecs_to_jiffies); 150 } 151 152 static ulong sysctl_jiffies_to_msecs(const ulong val) 153 { 154 return jiffies_to_msecs(val); 155 } 156 157 static int sysctl_k2u_int_conv_ms(bool *negp, ulong *u_ptr, const int *k_ptr) 158 { 159 return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, sysctl_jiffies_to_msecs); 160 } 161 162 static int do_proc_int_conv_jiffies(bool *negp, ulong *u_ptr, int *k_ptr, 163 int dir, const struct ctl_table *tbl) 164 { 165 return proc_int_conv(negp, u_ptr, k_ptr, dir, tbl, false, 166 sysctl_u2k_int_conv_hz, sysctl_k2u_int_conv_hz); 167 } 168 169 static int do_proc_int_conv_userhz_jiffies(bool *negp, ulong *u_ptr, 170 int *k_ptr, int dir, 171 const struct ctl_table *tbl) 172 { 173 return proc_int_conv(negp, u_ptr, k_ptr, dir, tbl, false, 174 sysctl_u2k_int_conv_userhz, 175 sysctl_k2u_int_conv_userhz); 176 } 177 178 static int do_proc_int_conv_ms_jiffies(bool *negp, ulong *u_ptr, int *k_ptr, 179 int dir, const struct ctl_table *tbl) 180 { 181 return proc_int_conv(negp, u_ptr, k_ptr, dir, tbl, false, 182 sysctl_u2k_int_conv_ms, sysctl_k2u_int_conv_ms); 183 } 184 185 static int do_proc_int_conv_ms_jiffies_minmax(bool *negp, ulong *u_ptr, 186 int *k_ptr, int dir, 187 const struct ctl_table *tbl) 188 { 189 return proc_int_conv(negp, u_ptr, k_ptr, dir, tbl, true, 190 sysctl_u2k_int_conv_ms, sysctl_k2u_int_conv_ms); 191 } 192 193 static int sysctl_u2k_ulong_conv_ms(const ulong *u_ptr, ulong *k_ptr) 194 { 195 return proc_ulong_u2k_conv_uop(u_ptr, k_ptr, sysctl_msecs_to_jiffies); 196 } 197 198 static int sysctl_k2u_ulong_conv_ms(ulong *u_ptr, const ulong *k_ptr) 199 { 200 return proc_ulong_k2u_conv_kop(u_ptr, k_ptr, sysctl_jiffies_to_msecs); 201 } 202 203 static int do_proc_ulong_conv_ms_jiffies_minmax(bool *negp, ulong *u_ptr, ulong *k_ptr, 204 int dir, const struct ctl_table *tbl) 205 { 206 return proc_ulong_conv(u_ptr, k_ptr, dir, tbl, true, 207 sysctl_u2k_ulong_conv_ms, sysctl_k2u_ulong_conv_ms); 208 } 209 210 #else // CONFIG_SYSCTL 211 static int do_proc_int_conv_jiffies(bool *negp, ulong *u_ptr, int *k_ptr, 212 int dir, const struct ctl_table *tbl) 213 { 214 return -ENOSYS; 215 } 216 217 static int do_proc_int_conv_userhz_jiffies(bool *negp, ulong *u_ptr, 218 int *k_ptr, int dir, 219 const struct ctl_table *tbl) 220 { 221 return -ENOSYS; 222 } 223 224 static int do_proc_int_conv_ms_jiffies(bool *negp, ulong *u_ptr, int *k_ptr, 225 int dir, const struct ctl_table *tbl) 226 { 227 return -ENOSYS; 228 } 229 230 static int do_proc_int_conv_ms_jiffies_minmax(bool *negp, ulong *u_ptr, 231 int *k_ptr, int dir, 232 const struct ctl_table *tbl) 233 { 234 return -ENOSYS; 235 } 236 237 static int do_proc_ulong_conv_ms_jiffies_minmax(bool *negp, ulong *u_ptr, ulong *k_ptr, 238 int dir, const struct ctl_table *tbl) 239 { 240 return -ENOSYS; 241 } 242 #endif 243 244 /** 245 * proc_dointvec_jiffies - read a vector of integers as seconds 246 * @table: the sysctl table 247 * @dir: %TRUE if this is a write to the sysctl file 248 * @buffer: the user buffer 249 * @lenp: the size of the user buffer 250 * @ppos: file position 251 * 252 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer 253 * values from/to the user buffer, treated as an ASCII string. 254 * The values read are assumed to be in seconds, and are converted into 255 * jiffies. 256 * 257 * Returns 0 on success. 258 */ 259 int proc_dointvec_jiffies(const struct ctl_table *table, int dir, 260 void *buffer, size_t *lenp, loff_t *ppos) 261 { 262 return proc_dointvec_conv(table, dir, buffer, lenp, ppos, 263 do_proc_int_conv_jiffies); 264 } 265 EXPORT_SYMBOL(proc_dointvec_jiffies); 266 267 /** 268 * proc_dointvec_userhz_jiffies - read a vector of integers as 1/USER_HZ seconds 269 * @table: the sysctl table 270 * @dir: %TRUE if this is a write to the sysctl file 271 * @buffer: the user buffer 272 * @lenp: the size of the user buffer 273 * @ppos: pointer to the file position 274 * 275 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer 276 * values from/to the user buffer, treated as an ASCII string. 277 * The values read are assumed to be in 1/USER_HZ seconds, and 278 * are converted into jiffies. 279 * 280 * Returns 0 on success. 281 */ 282 int proc_dointvec_userhz_jiffies(const struct ctl_table *table, int dir, 283 void *buffer, size_t *lenp, loff_t *ppos) 284 { 285 return proc_dointvec_conv(table, dir, buffer, lenp, ppos, 286 do_proc_int_conv_userhz_jiffies); 287 } 288 EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); 289 290 /** 291 * proc_dointvec_ms_jiffies - read a vector of integers as 1 milliseconds 292 * @table: the sysctl table 293 * @dir: %TRUE if this is a write to the sysctl file 294 * @buffer: the user buffer 295 * @lenp: the size of the user buffer 296 * @ppos: the current position in the file 297 * 298 * Reads/writes up to table->maxlen/sizeof(unsigned int) integer 299 * values from/to the user buffer, treated as an ASCII string. 300 * The values read are assumed to be in 1/1000 seconds, and 301 * are converted into jiffies. 302 * 303 * Returns 0 on success. 304 */ 305 int proc_dointvec_ms_jiffies(const struct ctl_table *table, int dir, void *buffer, 306 size_t *lenp, loff_t *ppos) 307 { 308 return proc_dointvec_conv(table, dir, buffer, lenp, ppos, 309 do_proc_int_conv_ms_jiffies); 310 } 311 EXPORT_SYMBOL(proc_dointvec_ms_jiffies); 312 313 int proc_dointvec_ms_jiffies_minmax(const struct ctl_table *table, int dir, 314 void *buffer, size_t *lenp, loff_t *ppos) 315 { 316 return proc_dointvec_conv(table, dir, buffer, lenp, ppos, 317 do_proc_int_conv_ms_jiffies_minmax); 318 } 319 320 /** 321 * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values 322 * @table: the sysctl table 323 * @dir: %TRUE if this is a write to the sysctl file 324 * @buffer: the user buffer 325 * @lenp: the size of the user buffer 326 * @ppos: file position 327 * 328 * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long 329 * values from/to the user buffer, treated as an ASCII string. The values 330 * are treated as milliseconds, and converted to jiffies when they are stored. 331 * 332 * This routine will ensure the values are within the range specified by 333 * table->extra1 (min) and table->extra2 (max). 334 * 335 * Returns 0 on success. 336 */ 337 int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int dir, 338 void *buffer, size_t *lenp, loff_t *ppos) 339 { 340 return proc_doulongvec_conv(table, dir, buffer, lenp, ppos, 341 do_proc_ulong_conv_ms_jiffies_minmax); 342 } 343 EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax); 344 345