1
0

archtimr.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. archtimr.c
  5. Abstract:
  6. This module implements architecture-specific timer support for the hardware
  7. library.
  8. Author:
  9. Evan Green 31-Oct-2012
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/kernel.h>
  17. #include <minoca/kernel/arm.h>
  18. #include "../hlp.h"
  19. #include "../timer.h"
  20. #include "../clock.h"
  21. #include "../intrupt.h"
  22. #include "../profiler.h"
  23. //
  24. // ---------------------------------------------------------------- Definitions
  25. //
  26. //
  27. // ------------------------------------------------------ Data Type Definitions
  28. //
  29. //
  30. // ----------------------------------------------- Internal Function Prototypes
  31. //
  32. //
  33. // Builtin hardware module function prototypes.
  34. //
  35. VOID
  36. HlpArmCycleCounterModuleEntry (
  37. VOID
  38. );
  39. VOID
  40. HlpCpTimerModuleEntry (
  41. VOID
  42. );
  43. VOID
  44. HlpSp804TimerModuleEntry (
  45. VOID
  46. );
  47. VOID
  48. HlpOmap3TimerModuleEntry (
  49. VOID
  50. );
  51. VOID
  52. HlpOmap4TimerModuleEntry (
  53. VOID
  54. );
  55. VOID
  56. HlpAm335TimerModuleEntry (
  57. VOID
  58. );
  59. VOID
  60. HlpBcm2709TimerModuleEntry (
  61. VOID
  62. );
  63. VOID
  64. HlpRk32TimerModuleEntry (
  65. VOID
  66. );
  67. VOID
  68. HlpGtModuleEntry (
  69. VOID
  70. );
  71. //
  72. // -------------------------------------------------------------------- Globals
  73. //
  74. //
  75. // Timer modules that are initialized before the debugger.
  76. //
  77. PHARDWARE_MODULE_ENTRY HlPreDebuggerTimerModules[] = {
  78. HlpArmCycleCounterModuleEntry,
  79. };
  80. //
  81. // Built-in hardware modules.
  82. //
  83. PHARDWARE_MODULE_ENTRY HlBuiltinTimerModules[] = {
  84. HlpCpTimerModuleEntry,
  85. HlpSp804TimerModuleEntry,
  86. HlpOmap3TimerModuleEntry,
  87. HlpOmap4TimerModuleEntry,
  88. HlpAm335TimerModuleEntry,
  89. HlpBcm2709TimerModuleEntry,
  90. HlpRk32TimerModuleEntry,
  91. HlpGtModuleEntry
  92. };
  93. //
  94. // ------------------------------------------------------------------ Functions
  95. //
  96. KSTATUS
  97. HlGetProcessorCounterInformation (
  98. PHL_PROCESSOR_COUNTER_INFORMATION Information
  99. )
  100. /*++
  101. Routine Description:
  102. This routine returns information about the cycle counter built into the
  103. processor.
  104. Arguments:
  105. Information - Supplies a pointer where the processor counter information
  106. will be returned on success.
  107. Return Value:
  108. STATUS_SUCCESS on success.
  109. STATUS_NOT_SUPPORTED if the processor does not have a processor cycle
  110. counter.
  111. --*/
  112. {
  113. Information->Frequency = HlProcessorCounter->CounterFrequency;
  114. //
  115. // The ARM cycle counter is configured to divide actual cycles by 64, since
  116. // it's only a 32 bit value and can roll over quickly.
  117. //
  118. Information->Multiplier = 64;
  119. Information->Features = HlProcessorCounter->Features;
  120. return STATUS_SUCCESS;
  121. }
  122. VOID
  123. HlpArchInitializeTimersPreDebugger (
  124. VOID
  125. )
  126. /*++
  127. Routine Description:
  128. This routine implements early timer initialization for the hardware module
  129. API layer. This routine is *undebuggable*, as it is called before the
  130. debugger is brought online.
  131. Arguments:
  132. None.
  133. Return Value:
  134. None.
  135. --*/
  136. {
  137. PHARDWARE_MODULE_ENTRY ModuleEntry;
  138. UINTN TimerCount;
  139. UINTN TimerIndex;
  140. TimerCount = sizeof(HlPreDebuggerTimerModules) /
  141. sizeof(HlPreDebuggerTimerModules[0]);
  142. for (TimerIndex = 0; TimerIndex < TimerCount; TimerIndex += 1) {
  143. ModuleEntry = HlPreDebuggerTimerModules[TimerIndex];
  144. ModuleEntry();
  145. }
  146. return;
  147. }
  148. KSTATUS
  149. HlpArchInitializeTimers (
  150. VOID
  151. )
  152. /*++
  153. Routine Description:
  154. This routine performs architecture-specific initialization for the timer
  155. subsystem.
  156. Arguments:
  157. None.
  158. Return Value:
  159. Status code.
  160. --*/
  161. {
  162. UINTN ModuleCount;
  163. PHARDWARE_MODULE_ENTRY ModuleEntry;
  164. UINTN ModuleIndex;
  165. //
  166. // On the boot processor, perform one-time initialization.
  167. //
  168. if (KeGetCurrentProcessorNumber() == 0) {
  169. //
  170. // Loop through and initialize every built in hardware module.
  171. //
  172. ModuleCount = sizeof(HlBuiltinTimerModules) /
  173. sizeof(HlBuiltinTimerModules[0]);
  174. for (ModuleIndex = 0; ModuleIndex < ModuleCount; ModuleIndex += 1) {
  175. ModuleEntry = HlBuiltinTimerModules[ModuleIndex];
  176. ModuleEntry();
  177. }
  178. }
  179. return STATUS_SUCCESS;
  180. }
  181. KSTATUS
  182. HlpArchInitializeCalendarTimers (
  183. VOID
  184. )
  185. /*++
  186. Routine Description:
  187. This routine performs architecture-specific initialization for the
  188. calendar timer subsystem.
  189. Arguments:
  190. None.
  191. Return Value:
  192. Status code.
  193. --*/
  194. {
  195. return STATUS_SUCCESS;
  196. }
  197. KERNEL_API
  198. ULONGLONG
  199. HlQueryProcessorCounter (
  200. VOID
  201. )
  202. /*++
  203. Routine Description:
  204. This routine queries the processor counter hardware and returns a 64-bit
  205. monotonically non-decreasing value that correlates to "processor" time.
  206. This does not necessarily correspond to wall-clock time, as the frequency
  207. of this counter may vary over time. This counter may also vary across
  208. processors, so this routine must be called at dispatch level or higher.
  209. Failing to call this routine at or above dispatch level may cause the
  210. counter's internal accounting to malfunction.
  211. This routine is intended primarily for the scheduler to track processor
  212. cycles. Users looking to measure units of time should query the time
  213. counter.
  214. Arguments:
  215. None.
  216. Return Value:
  217. Returns a 64-bit non-decreasing value corresponding to "processor" time.
  218. --*/
  219. {
  220. //
  221. // Ideally there wouldn't be an assert in such a hot path, but it's very
  222. // important that this not be called below dispatch level, as doing so
  223. // would cause the "current count" software managed bits to get miscounted.
  224. //
  225. ASSERT((KeGetRunLevel() >= RunLevelDispatch) ||
  226. (ArAreInterruptsEnabled() == FALSE));
  227. return HlpTimerExtendedQuery(HlProcessorCounter);
  228. }
  229. //
  230. // --------------------------------------------------------- Internal Functions
  231. //