cache.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. /*++
  2. Copyright (c) 2013 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. cache.c
  5. Abstract:
  6. This module implements cache support for the hardware library.
  7. Author:
  8. Chris Stevens 13-Jan-2014
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel/kernel.h>
  16. #include <minoca/kernel/bootload.h>
  17. #include "hlp.h"
  18. #include "cache.h"
  19. //
  20. // ---------------------------------------------------------------- Definitions
  21. //
  22. //
  23. // ------------------------------------------------------ Data Type Definitions
  24. //
  25. /*++
  26. Structure Description:
  27. This structure defines a cache controller that has been registered with the
  28. system.
  29. Members:
  30. ListEntry - Stores pointers to the next and previous cache controllers in
  31. the system.
  32. FunctionTable - Stores pointers to functions implemented by the hardware
  33. module abstracting this cache controller.
  34. PrivateContext - Stores a pointer to the hardware module's private context.
  35. Identifier - Stores the unique hardware identifier of the cache controller.
  36. Flags - Stores a bitmaks of cache controller flags.
  37. See CACHE_CONTROLLER_FLAG_* for definitions.
  38. --*/
  39. typedef struct _CACHE_CONTROLLER {
  40. LIST_ENTRY ListEntry;
  41. CACHE_CONTROLLER_FUNCTION_TABLE FunctionTable;
  42. PVOID PrivateContext;
  43. ULONG Identifier;
  44. ULONG Flags;
  45. } CACHE_CONTROLLER, *PCACHE_CONTROLLER;
  46. //
  47. // ----------------------------------------------- Internal Function Prototypes
  48. //
  49. //
  50. // -------------------------------------------------------------------- Globals
  51. //
  52. //
  53. // Store the list of registered cache controllers.
  54. //
  55. LIST_ENTRY HlCacheControllers;
  56. //
  57. // ------------------------------------------------------------------ Functions
  58. //
  59. VOID
  60. HlFlushCache (
  61. ULONG Flags
  62. )
  63. /*++
  64. Routine Description:
  65. This routine flushes the cache for every registered cache controller.
  66. Arguments:
  67. Flags - Supplies a bitmask of cache flush flags. See HL_CACHE_FLAG_* for
  68. definitions.
  69. Return Value:
  70. None.
  71. --*/
  72. {
  73. PCACHE_CONTROLLER CurrentCache;
  74. PLIST_ENTRY CurrentEntry;
  75. PCACHE_CONTROLLER_FLUSH Flush;
  76. //
  77. // Iterate over each cache and flush it.
  78. //
  79. CurrentEntry = HlCacheControllers.Next;
  80. while (CurrentEntry != &HlCacheControllers) {
  81. CurrentCache = LIST_VALUE(CurrentEntry, CACHE_CONTROLLER, ListEntry);
  82. Flush = CurrentCache->FunctionTable.Flush;
  83. Flush(CurrentCache->PrivateContext, Flags);
  84. CurrentEntry = CurrentEntry->Next;
  85. }
  86. return;
  87. }
  88. VOID
  89. HlFlushCacheRegion (
  90. PHYSICAL_ADDRESS Address,
  91. UINTN SizeInBytes,
  92. ULONG Flags
  93. )
  94. /*++
  95. Routine Description:
  96. This routine flushes the given cache region for every registered cache
  97. controller.
  98. Arguments:
  99. Address - Supplies the starting physical address of the region to flush. It
  100. must be aligned to the cache line size.
  101. SizeInBytes - Supplies the number of bytes to flush.
  102. Flags - Supplies a bitmask of cache flush flags. See HL_CACHE_FLAG_* for
  103. definitions.
  104. Return Value:
  105. None.
  106. --*/
  107. {
  108. PCACHE_CONTROLLER CurrentCache;
  109. PLIST_ENTRY CurrentEntry;
  110. PCACHE_CONTROLLER_FLUSH_REGION FlushRegion;
  111. //
  112. // Iterate over each cache and flush the region.
  113. //
  114. CurrentEntry = HlCacheControllers.Next;
  115. while (CurrentEntry != &HlCacheControllers) {
  116. CurrentCache = LIST_VALUE(CurrentEntry, CACHE_CONTROLLER, ListEntry);
  117. FlushRegion = CurrentCache->FunctionTable.FlushRegion;
  118. FlushRegion(CurrentCache->PrivateContext, Address, SizeInBytes, Flags);
  119. CurrentEntry = CurrentEntry->Next;
  120. }
  121. return;
  122. }
  123. ULONG
  124. HlGetDataCacheLineSize (
  125. VOID
  126. )
  127. /*++
  128. Routine Description:
  129. This routine returns the maximum data cache line size out of all registered
  130. cache controllers.
  131. Arguments:
  132. None.
  133. Return Value:
  134. Returns the maximum data cache line size out of all registered cache
  135. controllers in bytes.
  136. --*/
  137. {
  138. PCACHE_CONTROLLER CurrentCache;
  139. PLIST_ENTRY CurrentEntry;
  140. PCACHE_CONTROLLER_GET_PROPERTIES GetProperties;
  141. ULONG MaxDataCacheLineSize;
  142. CACHE_CONTROLLER_PROPERTIES Properties;
  143. KSTATUS Status;
  144. MaxDataCacheLineSize = 0;
  145. Properties.Version = CACHE_CONTROLLER_PROPERTIES_VERSION;
  146. //
  147. // Iterate over each cache and find the biggest data cache line size.
  148. //
  149. CurrentEntry = HlCacheControllers.Next;
  150. while (CurrentEntry != &HlCacheControllers) {
  151. CurrentCache = LIST_VALUE(CurrentEntry, CACHE_CONTROLLER, ListEntry);
  152. GetProperties = CurrentCache->FunctionTable.GetProperties;
  153. Status = GetProperties(CurrentCache->PrivateContext, &Properties);
  154. if (KSUCCESS(Status)) {
  155. ASSERT(POWER_OF_2(Properties.DataCacheLineSize) != FALSE);
  156. ASSERT(Properties.Version == CACHE_CONTROLLER_PROPERTIES_VERSION);
  157. if (Properties.DataCacheLineSize > MaxDataCacheLineSize) {
  158. MaxDataCacheLineSize = Properties.DataCacheLineSize;
  159. }
  160. }
  161. CurrentEntry = CurrentEntry->Next;
  162. }
  163. return MaxDataCacheLineSize;
  164. }
  165. KSTATUS
  166. HlpInitializeCacheControllers (
  167. PKERNEL_INITIALIZATION_BLOCK Parameters
  168. )
  169. /*++
  170. Routine Description:
  171. This routine initializes the cache subsystem.
  172. Arguments:
  173. Parameters - Supplies a pointer to the kernel's initialization information.
  174. Return Value:
  175. Status code.
  176. --*/
  177. {
  178. KSTATUS Status;
  179. Status = STATUS_SUCCESS;
  180. if (KeGetCurrentProcessorNumber() == 0) {
  181. INITIALIZE_LIST_HEAD(&HlCacheControllers);
  182. //
  183. // Perform architecture-specific initialization.
  184. //
  185. Status = HlpArchInitializeCacheControllers();
  186. if (!KSUCCESS(Status)) {
  187. goto InitializeCachesEnd;
  188. }
  189. }
  190. InitializeCachesEnd:
  191. return Status;
  192. }
  193. KSTATUS
  194. HlpCacheControllerRegisterHardware (
  195. PCACHE_CONTROLLER_DESCRIPTION CacheDescription
  196. )
  197. /*++
  198. Routine Description:
  199. This routine is called to register a new cache controller with the system.
  200. Arguments:
  201. CacheDescription - Supplies a pointer to a structure describing the new
  202. cache controller.
  203. Return Value:
  204. Status code.
  205. --*/
  206. {
  207. ULONG AllocationSize;
  208. PCACHE_CONTROLLER CacheController;
  209. PCACHE_CONTROLLER_INITIALIZE Initialize;
  210. KSTATUS Status;
  211. CacheController = NULL;
  212. //
  213. // Check the table version.
  214. //
  215. if (CacheDescription->TableVersion < CACHE_CONTROLLER_DESCRIPTION_VERSION) {
  216. Status = STATUS_VERSION_MISMATCH;
  217. goto CacheControllerRegisterHardwareEnd;
  218. }
  219. //
  220. // Check the properties version.
  221. //
  222. if (CacheDescription->PropertiesVersion <
  223. CACHE_CONTROLLER_PROPERTIES_VERSION) {
  224. Status = STATUS_VERSION_MISMATCH;
  225. goto CacheControllerRegisterHardwareEnd;
  226. }
  227. //
  228. // Check required function pointers.
  229. //
  230. if ((CacheDescription->FunctionTable.Flush == NULL) ||
  231. (CacheDescription->FunctionTable.FlushRegion == NULL) ||
  232. (CacheDescription->FunctionTable.GetProperties == NULL)) {
  233. Status = STATUS_INVALID_PARAMETER;
  234. goto CacheControllerRegisterHardwareEnd;
  235. }
  236. //
  237. // Allocate the new controller object.
  238. //
  239. AllocationSize = sizeof(CACHE_CONTROLLER);
  240. CacheController = MmAllocateNonPagedPool(AllocationSize, HL_POOL_TAG);
  241. if (CacheController == NULL) {
  242. Status = STATUS_INSUFFICIENT_RESOURCES;
  243. goto CacheControllerRegisterHardwareEnd;
  244. }
  245. RtlZeroMemory(CacheController, AllocationSize);
  246. //
  247. // Initialize the new cache controller based on the description.
  248. //
  249. RtlCopyMemory(&(CacheController->FunctionTable),
  250. &(CacheDescription->FunctionTable),
  251. sizeof(CACHE_CONTROLLER_FUNCTION_TABLE));
  252. CacheController->Identifier = CacheDescription->Identifier;
  253. CacheController->PrivateContext = CacheDescription->Context;
  254. //
  255. // Insert the cache controller into the list.
  256. //
  257. INSERT_BEFORE(&(CacheController->ListEntry), &HlCacheControllers);
  258. //
  259. // Initialize the new cache controller immediately.
  260. //
  261. Status = STATUS_SUCCESS;
  262. Initialize = CacheController->FunctionTable.Initialize;
  263. if (Initialize != NULL) {
  264. Status = Initialize(CacheController->PrivateContext);
  265. }
  266. if (!KSUCCESS(Status)) {
  267. CacheController->Flags |= CACHE_CONTROLLER_FLAG_FAILED;
  268. } else {
  269. CacheController->Flags |= CACHE_CONTROLLER_FLAG_INITIALIZED;
  270. }
  271. Status = STATUS_SUCCESS;
  272. CacheControllerRegisterHardwareEnd:
  273. return Status;
  274. }
  275. //
  276. // --------------------------------------------------------- Internal Functions
  277. //