delay.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Delay loops based on the OpenRISC implementation.
  4. *
  5. * Copyright (C) 2012 ARM Limited
  6. *
  7. * Author: Will Deacon <will.deacon@arm.com>
  8. */
  9. #include <linux/delay.h>
  10. #include <linux/init.h>
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <linux/timex.h>
  14. #include <clocksource/arm_arch_timer.h>
  15. #define USECS_TO_CYCLES(time_usecs) \
  16. xloops_to_cycles((time_usecs) * 0x10C7UL)
  17. static inline unsigned long xloops_to_cycles(unsigned long xloops)
  18. {
  19. return (xloops * loops_per_jiffy * HZ) >> 32;
  20. }
  21. /*
  22. * Force the use of CNTVCT_EL0 in order to have the same base as WFxT.
  23. * This avoids some annoying issues when CNTVOFF_EL2 is not reset 0 on a
  24. * KVM host running at EL1 until we do a vcpu_put() on the vcpu. When
  25. * running at EL2, the effective offset is always 0.
  26. *
  27. * Note that userspace cannot change the offset behind our back either,
  28. * as the vcpu mutex is held as long as KVM_RUN is in progress.
  29. */
  30. static cycles_t notrace __delay_cycles(void)
  31. {
  32. guard(preempt_notrace)();
  33. return __arch_counter_get_cntvct_stable();
  34. }
  35. void __delay(unsigned long cycles)
  36. {
  37. cycles_t start = __delay_cycles();
  38. if (alternative_has_cap_unlikely(ARM64_HAS_WFXT)) {
  39. u64 end = start + cycles;
  40. /*
  41. * Start with WFIT. If an interrupt makes us resume
  42. * early, use a WFET loop to complete the delay.
  43. */
  44. wfit(end);
  45. while ((__delay_cycles() - start) < cycles)
  46. wfet(end);
  47. } else if (arch_timer_evtstrm_available()) {
  48. const cycles_t timer_evt_period =
  49. USECS_TO_CYCLES(ARCH_TIMER_EVT_STREAM_PERIOD_US);
  50. while ((__delay_cycles() - start + timer_evt_period) < cycles)
  51. wfe();
  52. }
  53. while ((__delay_cycles() - start) < cycles)
  54. cpu_relax();
  55. }
  56. EXPORT_SYMBOL(__delay);
  57. inline void __const_udelay(unsigned long xloops)
  58. {
  59. __delay(xloops_to_cycles(xloops));
  60. }
  61. EXPORT_SYMBOL(__const_udelay);
  62. void __udelay(unsigned long usecs)
  63. {
  64. __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */
  65. }
  66. EXPORT_SYMBOL(__udelay);
  67. void __ndelay(unsigned long nsecs)
  68. {
  69. __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */
  70. }
  71. EXPORT_SYMBOL(__ndelay);