cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

delay.c (2840B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2012 Regents of the University of California
      4 */
      5
      6#include <linux/delay.h>
      7#include <linux/math.h>
      8#include <linux/param.h>
      9#include <linux/timex.h>
     10#include <linux/types.h>
     11#include <linux/export.h>
     12
     13#include <asm/processor.h>
     14
     15/*
     16 * This is copies from arch/arm/include/asm/delay.h
     17 *
     18 * Loop (or tick) based delay:
     19 *
     20 * loops = loops_per_jiffy * jiffies_per_sec * delay_us / us_per_sec
     21 *
     22 * where:
     23 *
     24 * jiffies_per_sec = HZ
     25 * us_per_sec = 1000000
     26 *
     27 * Therefore the constant part is HZ / 1000000 which is a small
     28 * fractional number. To make this usable with integer math, we
     29 * scale up this constant by 2^31, perform the actual multiplication,
     30 * and scale the result back down by 2^31 with a simple shift:
     31 *
     32 * loops = (loops_per_jiffy * delay_us * UDELAY_MULT) >> 31
     33 *
     34 * where:
     35 *
     36 * UDELAY_MULT = 2^31 * HZ / 1000000
     37 *             = (2^31 / 1000000) * HZ
     38 *             = 2147.483648 * HZ
     39 *             = 2147 * HZ + 483648 * HZ / 1000000
     40 *
     41 * 31 is the biggest scale shift value that won't overflow 32 bits for
     42 * delay_us * UDELAY_MULT assuming HZ <= 1000 and delay_us <= 2000.
     43 */
     44#define MAX_UDELAY_US	2000
     45#define MAX_UDELAY_HZ	1000
     46#define UDELAY_MULT	(2147UL * HZ + 483648UL * HZ / 1000000UL)
     47#define UDELAY_SHIFT	31
     48
     49#if HZ > MAX_UDELAY_HZ
     50#error "HZ > MAX_UDELAY_HZ"
     51#endif
     52
     53/*
     54 * RISC-V supports both UDELAY and NDELAY.  This is largely the same as above,
     55 * but with different constants.  I added 10 bits to the shift to get this, but
     56 * the result is that I need a 64-bit multiply, which is slow on 32-bit
     57 * platforms.
     58 *
     59 * NDELAY_MULT = 2^41 * HZ / 1000000000
     60 *             = (2^41 / 1000000000) * HZ
     61 *             = 2199.02325555 * HZ
     62 *             = 2199 * HZ + 23255550 * HZ / 1000000000
     63 *
     64 * The maximum here is to avoid 64-bit overflow, but it isn't checked as it
     65 * won't happen.
     66 */
     67#define MAX_NDELAY_NS   (1ULL << 42)
     68#define MAX_NDELAY_HZ	MAX_UDELAY_HZ
     69#define NDELAY_MULT	((unsigned long long)(2199ULL * HZ + 23255550ULL * HZ / 1000000000ULL))
     70#define NDELAY_SHIFT	41
     71
     72#if HZ > MAX_NDELAY_HZ
     73#error "HZ > MAX_NDELAY_HZ"
     74#endif
     75
     76void __delay(unsigned long cycles)
     77{
     78	u64 t0 = get_cycles();
     79
     80	while ((unsigned long)(get_cycles() - t0) < cycles)
     81		cpu_relax();
     82}
     83EXPORT_SYMBOL(__delay);
     84
     85void udelay(unsigned long usecs)
     86{
     87	u64 ucycles = (u64)usecs * lpj_fine * UDELAY_MULT;
     88	u64 n;
     89
     90	if (unlikely(usecs > MAX_UDELAY_US)) {
     91		n = (u64)usecs * riscv_timebase;
     92		do_div(n, 1000000);
     93
     94		__delay(n);
     95		return;
     96	}
     97
     98	__delay(ucycles >> UDELAY_SHIFT);
     99}
    100EXPORT_SYMBOL(udelay);
    101
    102void ndelay(unsigned long nsecs)
    103{
    104	/*
    105	 * This doesn't bother checking for overflow, as it won't happen (it's
    106	 * an hour) of delay.
    107	 */
    108	unsigned long long ncycles = nsecs * lpj_fine * NDELAY_MULT;
    109	__delay(ncycles >> NDELAY_SHIFT);
    110}
    111EXPORT_SYMBOL(ndelay);