cacheLib.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:39k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* cacheLib.c - cache management library */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01s,22aug01,dgp  correct drvExample1( ) per SPR 66362
  8. 01r,26jun96,dbt  added test (address == NONE) in cacheTextUpdate (SPR #4262).
  9.  Update copyright.
  10. 01q,02aug95,tpr  added MC68060 CPU test in cacheFuncsSet().
  11. 01p,27oct94,hdn  added support for I80X86 for external write-back cache.
  12. 01o,22sep94,rhp  doc: fix typo in CACHE_LIB structure description (spr#2491).
  13. 01n,06jan93,jdi  documentation cleanup.
  14. 01m,19oct92,jcf  retained 5.0 cache defines and reworked xxxInit param ordering.
  15. 01l,29sep92,jwt  merged cacheLibInit(), cacheReset(), and cacheModeSet().
  16. 01k,17sep92,jdi  documentation cleanup, and ansification.
  17. 01j,16sep92,jwt  documentation cleanup for DNW changes in version 01g.
  18. 01i,23aug92,jcf  moved cache* function pointer structs to funcBind.c.
  19. 01h,04aug92,ajm  passed correct parameters in cacheTextUpdate
  20. 01g,31jul92,jwt  put function pointers back in "data" section.
  21.     30jul92,dnw  added cacheLib functions and CACHE_FUNCS structures.
  22. 01f,24jul92,jwt  added more comprehensive write buffer description.
  23. 01e,09jul92,jwt  added description for virtual<->physical, no code mods.
  24. 01d,07jul92,ajm  forward declared sysCacheLibInit for mips compiler
  25. 01c,07jul92,jwt  more clean up of descriptions and binding to BSP.
  26. 01b,06jul92,jwt  cleaned up descriptions and binding to BSP.
  27. 01a,03jul92,jwt  created - top-level cache library for VxWorks 5.1 release.
  28. */
  29. /*
  30. DESCRIPTION
  31. This library provides architecture-independent routines for managing
  32. the instruction and data caches.  Architecture-dependent routines are
  33. documented in the architecture-specific libraries.  
  34. The cache library is initialized by cacheLibInit() in usrInit().  The
  35. cacheLibInit() routine typically calls an architecture-specific
  36. initialization routine in one of the architecture-specific libraries.  The
  37. initialization routine places the cache in a known and quiescent state,
  38. ready for use, but not yet enabled.  Cache devices are enabled and disabled
  39. by calls to cacheEnable() and cacheDisable(), respectively.  
  40. The structure CACHE_LIB in cacheLib.h provides a function pointer that
  41. allows for the installation of different cache implementations in an
  42. architecture-independent manner.  If the processor family allows more than
  43. one cache implementation, the board support package (BSP) must select the
  44. appropriate cache library using the function pointer `sysCacheLibInit'.
  45. The cacheLibInit() routine calls the initialization function attached to
  46. `sysCacheLibInit' to perform the actual CACHE_LIB function pointer
  47. initialization (see cacheLib.h).  Note that `sysCacheLibInit' must be
  48. initialized when declared; it need not exist for architectures with a
  49. single cache design.  Systems without caches have all NULL pointers in the
  50. CACHE_LIB structure.  For systems with bus snooping, NULLifying the flush
  51. and invalidate function pointers in sysHwInit() improves overall system
  52. and driver performance.
  53. Function pointers also provide a way to supplement the cache library or
  54. attach user-defined cache functions for managing secondary cache systems.
  55. Parameters specified by cacheLibInit() are used to select the cache mode,
  56. either write-through (CACHE_WRITETHROUGH) or copyback (CACHE_COPYBACK), as
  57. well as to implement all other cache configuration features via software
  58. bit-flags.  Note that combinations, such as setting copyback and
  59. write-through at the same time, do not make sense.
  60. Typically, the first argument passed to cache routines after initialization 
  61. is the CACHE_TYPE, which selects the data cache (DATA_CACHE) or the 
  62. instruction cache (INSTRUCTION_CACHE).  
  63. Several routines accept two additional arguments: an address and
  64. the number of bytes.  Some cache operations can be applied to the
  65. entire cache (bytes = ENTIRE_CACHE) or to a portion of the cache.  This
  66. range specification allows the cache to be selectively locked, unlocked,
  67. flushed, invalidated, and cleared.  The two complementary routines,
  68. cacheDmaMalloc() and cacheDmaFree(), are tailored for efficient driver writing.
  69. The cacheDmaMalloc() routine attempts to return a "cache-safe" buffer,
  70. which is created by the MMU and a set of flush and invalidate function
  71. pointers.  Examples are provided below in the section "Using the Cache
  72. Library."
  73. Most routines in this library return a STATUS value of OK, or 
  74. ERROR if the cache selection is invalid or the cache operation fails.  
  75. BACKGROUND
  76. The emergence of RISC processors and effective CISC caches has made cache
  77. and MMU support a key enhancement to VxWorks.  (For more information about MMU
  78. support, see the manual entry for vmLib.)  The VxWorks cache strategy
  79. is to maintain coherency between the data cache and RAM and between the
  80. instruction and data caches.  VxWorks also preserves overall system
  81. performance.  The product is designed to support several architectures and
  82. board designs, to have a high-performance implementation for drivers, and
  83. to make routines functional for users, as well as within the entire
  84. operating system.  The lack of a consistent cache design, even within
  85. architectures, has required designing for the case with the greatest number of
  86. coherency issues (Harvard architecture, copyback mode, DMA devices,
  87. multiple bus masters, and no hardware coherency support).
  88. Caches run in two basic modes, write-through and copyback.  The
  89. write-through mode forces all writes to the cache and to RAM, providing
  90. partial coherency.  Writing to RAM every time, however, slows down the
  91. processor and uses bus bandwidth.  The copyback mode conserves processor
  92. performance time and bus bandwidth by writing only to the cache, not RAM.
  93. Copyback cache entries are only written to memory on demand.  A Least
  94. Recently Used (LRU) algorithm is typically used to determine which cache
  95. line to displace and flush.  Copyback provides higher system performance,
  96. but requires more coherency support.  Below is a logical diagram of a
  97. cached system to aid in the visualization of the coherency issues.
  98. .CS
  99. .vs -4
  100. .ne 20
  101.    +---------------+     +-----------------+     +--------------+
  102.    |               |     |                 |     |              |
  103.    |  INSTRUCTION  |---->|    PROCESSOR    |<--->|  DATA CACHE  | (3)
  104.    |     CACHE     |     |                 |     |  (copyback)  |
  105.    |               |     |                 |     |              |
  106.    +---------------+     +-----------------+     +--------------+
  107.            ^                     (2)                     ^
  108.            |                                             |
  109.            |             +-----------------+             |
  110.            |             |                 |         (1) |
  111.            +-------------|       RAM       |<------------+
  112.                          |                 |
  113.                          +-----------------+
  114.                              ^         ^
  115.                              |         |
  116.            +-------------+   |         |   +-------------+
  117.            |             |   |         |   |             |
  118.            | DMA Devices |<--+         +-->| VMEbus, etc.|
  119.            |             |                 |             |
  120.            +-------------+                 +-------------+
  121. .vs
  122. .CE
  123. The loss of cache coherency for a VxWorks system occurs in three places:
  124.     (1) data cache / RAM
  125.     (2) instruction cache / data cache
  126.     (3) shared cache lines
  127. A problem between the data cache and RAM (1) results from asynchronous
  128. accesses (reads and writes) to the RAM by the processor and other
  129. masters.  Accesses by DMA devices and alternate bus masters (shared
  130. memory) are the primary causes of incoherency, which can be remedied with
  131. minor code additions to the drivers.  
  132. The instruction cache and data cache (2) can get out of sync when the
  133. loader, the debugger, and the interrupt connection routines are being
  134. used.  The instructions resulting from these operations are loaded into
  135. the data cache, but not necessarily the instruction cache, in which case
  136. there is a coherency problem.  This can be fixed by "flushing" the data
  137. cache entries to RAM, then "invalidating" the instruction cache entries.
  138. The invalid instruction cache tags will force the retrieval of the new
  139. instructions that the data cache has just flushed to RAM.
  140. Cache lines that are shared (3) by more than one task create coherency
  141. problems.  These are manifest when one thread of execution invalidates a
  142. cache line in which entries may belong to another thread.  This can be
  143. avoided by allocating memory on a cache line boundary, then rounding up to
  144. a multiple of the cache line size.
  145. The best way to preserve cache coherency with optimal performance
  146. (Harvard architecture, copyback mode, no software intervention) is
  147. to use hardware with bus snooping capabilities.  The caches, the RAM, the
  148. DMA devices, and all other bus masters are tied to a physical bus
  149. where the caches can "snoop" or watch the bus transactions.  The
  150. address cycle and control (read/write) bits are broadcast on the bus
  151. to allow snooping.  Data transfer cycles are deferred until absolutely
  152. necessary.  When one of the entries on the physical side of the cache
  153. is modified by an asynchronous action, the cache(s) marks its
  154. entry(s) as invalid.  If an access is made by the processor (logical
  155. side) to the now invalid cached entry, it is forced to retrieve the
  156. valid entry from RAM.  If while in copyback mode the processor writes
  157. to a cached entry, the RAM version becomes stale.  If another master
  158. attempts to access that stale entry in RAM, the cache with the valid
  159. version pre-empts the access and writes the valid data to RAM.  The
  160. interrupted access then restarts and retrieves the now-valid data in
  161. RAM.  Note that this configuration allows only one valid entry at any
  162. time.  At this time, only a few boards provide the snooping capability; 
  163. therefore, cache support software must be designed to handle
  164. incoherency hazards without degrading performance.
  165. The determinism, interrupt latency, and benchmarks for a cached system are
  166. exceedingly difficult to specify (best case, worst case, average case) due
  167. to cache hits and misses, line flushes and fills, atomic burst cycles,
  168. global and local instruction and data cache locking, copyback versus
  169. write-through modes, hardware coherency support (or lack of), and MMU
  170. operations (table walks, TLB locking).
  171. USING THE CACHE LIBRARY
  172. The coherency problems described above can be overcome by adding cache
  173. support to existing software.  For code segments that are not
  174. time-critical (loader, debugger, interrupt connection), the following
  175. sequence should be used first to flush the data cache entries and then 
  176. to invalidate the corresponding instruction cache entries.
  177. .CS
  178.     cacheFlush (DATA_CACHE, address, bytes);
  179.     cacheInvalidate (INSTRUCTION_CACHE, address, bytes);
  180. .CE
  181. For time-critical code, implementation is up to the driver writer.
  182. The following are tips for using the VxWorks cache library effectively.  
  183. Incorporate cache calls in the driver program to maintain overall system
  184. performance.  The cache may be disabled to facilitate driver development;
  185. however, high-performance production systems should operate with the cache
  186. enabled.  A disabled cache will dramatically reduce system performance for
  187. a completed application.
  188. Buffers can be static or dynamic.  Mark buffers "non-cacheable" to avoid
  189. cache coherency problems.  This usually requires MMU support.  Dynamic
  190. buffers are typically smaller than their static counterparts, and they are
  191. allocated and freed often.  When allocating either type of buffer, it
  192. should be designated non-cacheable; however, dynamic buffers should be
  193. marked "cacheable" before being freed.  Otherwise, memory becomes
  194. fragmented with numerous non-cacheable dynamic buffers.
  195. Alternatively, use the following flush/invalidate scheme to maintain 
  196. cache coherency.
  197. .CS
  198.     cacheInvalidate (DATA_CACHE, address, bytes);   /@ input buffer  @/
  199.     cacheFlush (DATA_CACHE, address, bytes);        /@ output buffer @/
  200. .CE
  201. The principle is to flush output buffers before each use and invalidate
  202. input buffers before each use.  Flushing only writes modified entries back
  203. to RAM, and instruction cache entries never get modified.
  204. Several flush and invalidate macros are defined in cacheLib.h.  Since
  205. optimized code uses these macros, they provide a mechanism to avoid
  206. unnecessary cache calls and accomplish the necessary work (return OK).
  207. Needless work includes flushing a write-through cache, flushing or
  208. invalidating cache entries in a system with bus snooping, and flushing
  209. or invalidating cache entries in a system without caches.  The macros
  210. are set to reflect the state of the cache system hardware and software.
  211. .SH "Example 1"
  212. The following example is of a simple driver that uses cacheFlush()
  213. and cacheInvalidate() from the cache library to maintain coherency and
  214. performance.  There are two buffers (lines 3 and 4), one for input and
  215. one for output.  The output buffer is obtained by the call to
  216. memalign(), a special version of the well-known malloc() routine (line
  217. 6).  It returns a pointer that is rounded down and up to the alignment
  218. parameter's specification.  Note that cache lines should not be shared,
  219. therefore _CACHE_ALIGN_SIZE is used to force alignment.  If the memory
  220. allocator fails (line 8), the driver will typically return ERROR (line
  221. 9) and quit.
  222. The driver fills the output buffer with initialization information,
  223. device commands, and data (line 11), and is prepared to pass the
  224. buffer to the device.  Before doing so the driver must flush the data
  225. cache (line 13) to ensure that the buffer is in memory, not hidden in
  226. the cache.  The drvWrite() routine lets the device know that the data
  227. is ready and where in memory it is located (line 14).
  228. More driver code is executed (line 16), then the driver is ready to
  229. receive data that the device has placed in an input buffer in memory
  230. (line 18).  Before the driver can work with the incoming data, it must
  231. invalidate the data cache entries (line 19) that correspond to the input
  232. buffer's data in order to eliminate stale entries.  That done, it is safe for
  233. the driver to retrieve the input data from memory (line 21).  Remember
  234. to free (line 23) the buffer acquired from the memory allocator.  The
  235. driver will return OK (line 24) to distinguish a successful from an
  236. unsuccessful operation.
  237. .CS
  238. STATUS drvExample1 () /@ simple driver - good performance @/
  239.     {
  240. 3:  void * pInBuf; /@ input buffer @/
  241. 4:  void * pOutBuf; /@ output buffer @/
  242.     
  243. 6:  pOutBuf = memalign (_CACHE_ALIGN_SIZE, BUF_SIZE);
  244. 8:  if (pOutBuf == NULL)
  245. 9:      return (ERROR); /@ memory allocator failed @/
  246. 11: /@ other driver initialization and buffer filling @/
  247. 13: cacheFlush (DATA_CACHE, pOutBuf, BUF_SIZE);
  248. 14: drvWrite (pOutBuf); /@ output data to device @/
  249. 16: /@ more driver code @/
  250. 18: cacheClear (DATA_CACHE, pInBuf, BUF_SIZE);
  251. 19: pInBuf = drvRead (); /@ wait for device data @/
  252. 21: /@ handle input data from device @/
  253. 23: free (pOutBuf); /@ return buffer to memory pool @/
  254. 24: return (OK);
  255.     }
  256. .CE
  257. Extending this flush/invalidate concept further, individual
  258. buffers can be treated this way, not just the entire cache system.  The 
  259. idea is to avoid
  260. unnecessary flush and/or invalidate operations on a per-buffer basis by
  261. allocating cache-safe buffers.  Calls to cacheDmaMalloc() optimize the
  262. flush and invalidate function pointers to NULL, if possible, while
  263. maintaining data integrity.
  264. .SH "Example 2"
  265. The following example is of a high-performance driver that takes advantage
  266. of the cache library to maintain coherency.  It uses cacheDmaMalloc() and
  267. the macros CACHE_DMA_FLUSH and CACHE_DMA_INVALIDATE.  A buffer pointer
  268. is passed as a parameter (line 2).  If the pointer is not NULL (line 7),
  269. it is assumed that the buffer will not experience any cache coherency
  270. problems.  If the driver was not provided with a cache-safe buffer, it
  271. will get one (line 11) from cacheDmaMalloc().  A CACHE_FUNCS structure
  272. (see cacheLib.h) is used to create a buffer that will not suffer from cache
  273. coherency problems.  If the memory allocator fails (line 13), the driver
  274. will typically return ERROR (line 14) and quit.
  275. The driver fills the output buffer with initialization information,
  276. device commands, and data (line 17), and is prepared to pass the
  277. buffer to the device.  Before doing so, the driver must flush the data
  278. cache (line 19) to ensure that the buffer is in memory, not hidden in
  279. the cache.  The routine drvWrite() lets the device know that the data
  280. is ready and where in memory it is located (line 20).
  281. More driver code is executed (line 22), and the driver is then ready to
  282. receive data that the device has placed in the buffer in memory (line
  283. 24).  Before the driver cache can work with the incoming data, it must
  284. invalidate the data cache entries (line 25) that correspond to the input
  285. buffer`s data in order to eliminate stale entries.  That done, it is safe 
  286. for the driver to handle the input data (line 27), which the driver 
  287. retrieves from memory.  Remember to free the buffer (line 29) acquired 
  288. from the memory allocator.  The driver will return OK (line 30) to 
  289. distinguish a successful from an unsuccessful operation.
  290. .CS
  291. STATUS drvExample2 (pBuf) /@ simple driver - great performance @/
  292. 2:  void * pBuf; /@ buffer pointer parameter @/
  293.     {
  294. 5:  if (pBuf != NULL)
  295. {
  296. 7: /@ no cache coherency problems with buffer passed to driver @/
  297. }
  298.     else
  299.         {
  300. 11:     pBuf = cacheDmaMalloc (BUF_SIZE);
  301. 13:     if (pBuf == NULL)
  302. 14:         return (ERROR); /@ memory allocator failed @/
  303.         }
  304. 17: /@ other driver initialization and buffer filling @/
  305. 19: CACHE_DMA_FLUSH (pBuf, BUF_SIZE);
  306. 20: drvWrite (pBuf); /@ output data to device @/
  307. 22: /@ more driver code @/
  308. 24: drvWait (); /@ wait for device data @/
  309. 25: CACHE_DMA_INVALIDATE (pBuf, BUF_SIZE);
  310. 27: /@ handle input data from device @/
  311. 29: cacheDmaFree (pBuf); /@ return buffer to memory pool @/
  312. 30: return (OK);
  313.     }
  314. .CE
  315. Do not use CACHE_DMA_FLUSH or CACHE_DMA_INVALIDATE without first calling
  316. cacheDmaMalloc(), otherwise the function pointers may not be
  317. initialized correctly.  Note that this driver scheme assumes all cache
  318. coherency modes have been set before driver initialization, and that
  319. the modes do not change after driver initialization.  The cacheFlush() and
  320. cacheInvalidate() functions can be used at any time throughout the system
  321. since they are affiliated with the hardware, not the malloc/free buffer.
  322. A call to cacheLibInit() in write-through mode makes the flush function
  323. pointers NULL.  Setting the caches in copyback mode (if supported) should
  324. set the pointer to and call an architecture-specific flush routine.  The
  325. invalidate and flush macros may be NULLified if the hardware provides bus
  326. snooping and there are no cache coherency problems.
  327. .SH "Example 3"
  328. The next example shows a more complex driver that requires address
  329. translations to assist in the cache coherency scheme.  The previous
  330. example had `a priori' knowledge of the system memory map and/or the device
  331. interaction with the memory system.  This next driver demonstrates a case 
  332. in which the virtual address returned by cacheDmaMalloc() might differ from 
  333. the physical address seen by the device.  It uses the CACHE_DMA_VIRT_TO_PHYS 
  334. and CACHE_DMA_PHYS_TO_VIRT macros in addition to the CACHE_DMA_FLUSH and
  335. CACHE_DMA_INVALIDATE macros.
  336. The cacheDmaMalloc() routine initializes the buffer pointer (line 3).  If
  337. the memory allocator fails (line 5), the driver will typically return
  338. ERROR (line 6) and quit.  The driver fills the output buffer with
  339. initialization information, device commands, and data (line 8), and is
  340. prepared to pass the buffer to the device.  Before doing so, the driver
  341. must flush the data cache (line 10) to ensure that the buffer is in
  342. memory, not hidden in the cache.  The flush is based on the virtual
  343. address since the processor filled in the buffer.  The drvWrite() routine
  344. lets the device know that the data is ready and where in memory it is
  345. located (line 11).  Note that the CACHE_DMA_VIRT_TO_PHYS macro converts
  346. the buffer's virtual address to the corresponding physical address for the
  347. device.
  348. More driver code is executed (line 13), and the driver is then ready to
  349. receive data that the device has placed in the buffer in memory (line
  350. 15).  Note the use of the CACHE_DMA_PHYS_TO_VIRT macro on the buffer
  351. pointer received from the device.  Before the driver cache can work
  352. with the incoming data, it must invalidate the data cache entries (line
  353. 16) that correspond to the input buffer's data in order to eliminate 
  354. stale entries.  That done, it is safe for the driver to handle the input 
  355. data (line 17), which it retrieves from memory.  Remember to free (line
  356. 19) the buffer acquired from the memory allocator.  The driver will return
  357. OK (line 20) to distinguish a successful from an unsuccessful operation.
  358. .CS
  359. STATUS drvExample3 ()           /@ complex driver - great performance @/ {
  360. 3:  void * pBuf = cacheDmaMalloc (BUF_SIZE);
  361. 5:  if (pBuf == NULL)
  362. 6:      return (ERROR); /@ memory allocator failed @/
  363. 8: /@ other driver initialization and buffer filling @/
  364. 10: CACHE_DMA_FLUSH (pBuf, BUF_SIZE);
  365. 11: drvWrite (CACHE_DMA_VIRT_TO_PHYS (pBuf));
  366. 13: /@ more driver code @/
  367. 15: pBuf = CACHE_DMA_PHYS_TO_VIRT (drvRead ());
  368. 16: CACHE_DMA_INVALIDATE (pBuf, BUF_SIZE);
  369. 17: /@ handle input data from device @/
  370. 19: cacheDmaFree (pBuf); /@ return buffer to memory pool @/
  371. 20: return (OK);
  372.     }
  373. .CE
  374. .SH "Driver Summary"
  375. The virtual-to-physical and physical-to-virtual function pointers
  376. associated with cacheDmaMalloc() are supplements to a cache-safe buffer.
  377. Since the processor operates on virtual addresses and the devices access
  378. physical addresses, discrepant addresses can occur and might prevent
  379. DMA-type devices from being able to access the allocated buffer.
  380. Typically, the MMU is used to return a buffer that has pages marked as 
  381. non-cacheable.  An MMU is used to translate virtual addresses into physical
  382. addresses, but it is not guaranteed that this will be a "transparent"
  383. translation.
  384. When cacheDmaMalloc() does something that makes the virtual address
  385. different from the physical address needed by the device, it provides the
  386. translation procedures.  This is often the case when using translation
  387. lookaside buffers (TLB) or a segmented address space to inhibit caching
  388. (e.g., by creating a different virtual address for the same physical
  389. space.)  If the virtual address returned by cacheDmaMalloc() is the same
  390. as the physical address, the function pointers are made NULL so that no calls
  391. are made when the macros are expanded.
  392. .SH "Board Support Packages"
  393. Each board for an architecture with more than one cache implementation has
  394. the potential for a different cache system.  Hence the BSP for selecting
  395. the appropriate cache library.  The function pointer `sysCacheLibInit' is
  396. set to cacheXxxLibInit() ("Xxx" refers to the chip-specific name of a
  397. library or function) so that the function pointers for that cache system
  398. will be initialized and the linker will pull in only the desired cache
  399. library.  Below is an example of cacheXxxLib being linked in by sysLib.c.
  400. For systems without caches and for those architectures with only one cache
  401. design, there is no need for the `sysCacheLibInit' variable.
  402. .CS
  403.      FUNCPTR sysCacheLibInit = (FUNCPTR) cacheXxxLibInit;
  404. .CE
  405. For cache systems with bus snooping, the flush and invalidate macros
  406. should be NULLified to enhance system and driver performance in sysHwInit().
  407. .CS
  408.      void sysHwInit ()
  409.         {
  410.         ...
  411. cacheLib.flushRtn = NULL; /@ no flush necessary @/
  412. cacheLib.invalidateRtn = NULL; /@ no invalidate necessary @/
  413.         ...
  414.         }
  415. .CE
  416. There may be some drivers that require numerous cache calls, so many 
  417. that they interfere with the code clarity.  Additional checking can be
  418. done at the initialization stage to determine if cacheDmaMalloc() returned
  419. a buffer in non-cacheable space.  Remember that it will return a
  420. cache-safe buffer by virtue of the function pointers.  Ideally, these are
  421. NULL, since the MMU was used to mark the pages as non-cacheable.  The
  422. macros CACHE_Xxx_IS_WRITE_COHERENT and CACHE_Xxx_IS_READ_COHERENT
  423. can be used to check the flush and invalidate function pointers,
  424. respectively.
  425. Write buffers are used to allow the processor to continue execution while
  426. the bus interface unit moves the data to the external device.  In theory,
  427. the write buffer should be smart enough to flush itself when there is a
  428. write to non-cacheable space or a read of an item that is in the buffer.
  429. In those cases where the hardware does not support this, the software must
  430. flush the buffer manually.  This often is accomplished by a read to
  431. non-cacheable space or a NOP instruction that serializes the chip's
  432. pipelines and buffers.  This is not really a caching issue; however, the
  433. cache library provides a CACHE_PIPE_FLUSH macro.  External write buffers
  434. may still need to be handled in a board-specific manner.
  435. INTERNAL 
  436. The manipulation of the cache and/or cache registers should be done in
  437. the most efficient way possible to maintain driver performance.  Some
  438. of the code may have to be written in assembly language depending on
  439. the cache design.  Allowing different granularities for the cache
  440. operations helps reduce the overhead associated with the cache
  441. coherency software.  This may be applicable to all the cache calls,
  442. and will vary with each architecture.  Examples are entry, line, set,
  443. page, segment, region, context.  MMU support is needed to selectively
  444. enable and disable parts of the address space, and is typically done
  445. on a "page" basis.  Board-specific and some secondary cache operations
  446. should be part of the BSP.  The inclusion of routines that assist in
  447. debugging (cache tag dumps) is desirable.
  448. The memory allocator must round addresses down to a cache line
  449. boundary, and return a number of bytes that is a multiple of the cache
  450. line size to prevent shared cache lines.  Cache operations on address
  451. ranges must be rounded down and up to the appropriate boundaries
  452. (line, page, etc.).  _CACHE_ALIGN_SIZE may be used to force alignment
  453. when using memalign().
  454. The atomicity of the cache operations is preserved by locking
  455. interrupts and disabling caching.  Interrupts should be locked out
  456. while the cache is disabled since interrupt handling and other tasks
  457. would be run with caching disabled until the preempted task is
  458. switched back in, if it is ever switched back in.  The cache must be
  459. disabled while performing most of these operations.  For example, the
  460. cache should not be loading new entries during an invalidate operation
  461. and lose critical data such as stack entries.
  462. cacheDmaMalloc() returns the memalign() return value, or NULL if there
  463. is some procedure-specific error in cache<Xxx>DmaMalloc().  The flush
  464. and invalidate function pointers should be set as follows:
  465.     NO DATA CACHE cacheDrv.flushRtn = NULL
  466.                                 cacheDrv.invalidateRtn = NULL
  467.     DATA CACHE DISABLED cacheDrv.flushRtn = NULL
  468.                                 cacheDrv.invalidateRtn = NULL
  469.     DATA CACHING INHIBITED cacheDrv.flushRtn = NULL
  470.                                 cacheDrv.invalidateRtn = NULL
  471.     BUS SNOOPING HARDWARE cacheDrv.flushRtn = NULL
  472.                                 cacheDrv.invalidateRtn = NULL
  473.     WRITE-THROUGH DATA CACHE cacheDrv.flushRtn = NULL
  474.                                 cacheDrv.invalidate = cache<Xxx>Invalidate()
  475.     COPYBACK DATA CACHE cacheDrv.flushRtn = cache<Xxx>Flush()
  476.                                 cacheDrv.invalidate = cache<Xxx>Invalidate()
  477.     RETURN NULL BUFFER POINTER cacheDrv.flushRtn = cache<Xxx>Flush()
  478.                                 cacheDrv.invalidate = cache<Xxx>Invalidate()
  479. The setting of the flush function pointer may not be NULL if the system has 
  480. write buffers that need to be flushed.
  481. INCLUDE FILES: cacheLib.h
  482. SEE ALSO: Architecture-specific cache-management libraries (cacheXxxLib), vmLib,
  483. .pG "I/O System"
  484. */
  485. #include "cacheLib.h"
  486. #include "stdlib.h"
  487. #include "private/vmLibP.h"
  488. /* globals */
  489. FUNCPTR cacheDmaMallocRtn = NULL; /* malloc dma memory if MMU */
  490. FUNCPTR cacheDmaFreeRtn = NULL; /* free dma memory if MMU */
  491. CACHE_MODE cacheDataMode = CACHE_DISABLED; /* data cache mode */
  492. BOOL cacheDataEnabled = FALSE; /* data cache disabled */
  493. BOOL cacheMmuAvailable = FALSE; /* MMU support available */
  494. /* externals */
  495. IMPORT FUNCPTR sysCacheLibInit; /* Board-specific cache library */
  496. /**************************************************************************
  497. *
  498. * cacheLibInit - initialize the cache library for a processor architecture
  499. *
  500. * This routine initializes the function pointers for the appropriate cache 
  501. * library.  For architectures with more than one cache implementation, the
  502. * board support package must select the appropriate cache library with 
  503. * `sysCacheLibInit'.  Systems without cache coherency problems (i.e., bus 
  504. * snooping) should NULLify the flush and invalidate function pointers in 
  505. * the cacheLib structure to enhance driver and overall system performance.
  506. * This can be done in sysHwInit().
  507. * RETURNS: OK, or ERROR if there is no cache library installed.
  508. */
  509. STATUS cacheLibInit
  510.     (
  511.     CACHE_MODE instMode, /* inst cache mode */
  512.     CACHE_MODE dataMode /* data cache mode */
  513.     )
  514.     {
  515. #if _ARCH_MULTIPLE_CACHELIB
  516.     /* BSP selection of cache library */
  517.     return ((STATUS) (sysCacheLibInit == NULL) ? ERROR :
  518.     (*sysCacheLibInit) (instMode, dataMode));
  519. #else
  520.     /* Single cache library for arch */
  521.     return (cacheArchLibInit (instMode, dataMode));
  522. #endif /* _ARCH_MULTIPLE_CACHELIB */
  523.     }
  524. /**************************************************************************
  525. *
  526. * cacheEnable - enable the specified cache
  527. *
  528. * This routine invalidates the cache tags and enables the instruction or 
  529. * data cache.
  530. *
  531. * RETURNS: OK, or ERROR if the cache type is invalid or the cache control
  532. * is not supported.
  533. */
  534. STATUS cacheEnable
  535.     (
  536.     CACHE_TYPE cache /* cache to enable */
  537.     )
  538.     {
  539.     return ((cacheLib.enableRtn == NULL) ? ERROR : 
  540.             (cacheLib.enableRtn) (cache));
  541.     }
  542. /**************************************************************************
  543. *
  544. * cacheDisable - disable the specified cache
  545. *
  546. * This routine flushes the cache and disables the instruction or data cache.
  547. *
  548. * RETURNS: OK, or ERROR if the cache type is invalid or the cache control
  549. * is not supported.
  550. */
  551. STATUS cacheDisable
  552.     (
  553.     CACHE_TYPE cache /* cache to disable */
  554.     )
  555.     {
  556.     return ((cacheLib.disableRtn == NULL) ? ERROR : 
  557.             (cacheLib.disableRtn) (cache));
  558.     }
  559. /**************************************************************************
  560. *
  561. * cacheLock - lock all or part of a specified cache
  562. *
  563. * This routine locks all (global) or some (local) entries in the specified 
  564. * cache.  Cache locking is useful in real-time systems.  Not all caches can 
  565. * perform locking.
  566. *
  567. * RETURNS: OK, or ERROR if the cache type is invalid or the cache control
  568. * is not supported.
  569. */
  570. STATUS cacheLock
  571.     (
  572.     CACHE_TYPE cache, /* cache to lock */
  573.     void * address, /* virtual address */
  574.     size_t bytes /* number of bytes to lock */
  575.     )
  576.     {
  577.     return ((cacheLib.lockRtn == NULL) ? ERROR : 
  578.             (cacheLib.lockRtn) (cache, address, bytes));
  579.     }
  580. /**************************************************************************
  581. *
  582. * cacheUnlock - unlock all or part of a specified cache
  583. *
  584. * This routine unlocks all (global) or some (local) entries in the 
  585. * specified cache.  Not all caches can perform unlocking.
  586. *
  587. * RETURNS: OK, or ERROR if the cache type is invalid or the cache control
  588. * is not supported.
  589. */
  590. STATUS cacheUnlock
  591.     (
  592.     CACHE_TYPE cache, /* cache to unlock */
  593.     void * address, /* virtual address */
  594.     size_t bytes /* number of bytes to unlock */
  595.     )
  596.     {
  597.     return ((cacheLib.unlockRtn == NULL) ? ERROR : 
  598.             (cacheLib.unlockRtn) (cache, address, bytes));
  599.     }
  600. /**************************************************************************
  601. *
  602. * cacheFlush - flush all or some of a specified cache
  603. *
  604. * This routine flushes (writes to memory) all or some of the entries in
  605. * the specified cache.  Depending on the cache design, this operation may
  606. * also invalidate the cache tags.  For write-through caches, no work needs
  607. * to be done since RAM already matches the cached entries.  Note that
  608. * write buffers on the chip may need to be flushed to complete the flush.
  609. *
  610. * RETURNS: OK, or ERROR if the cache type is invalid or the cache control
  611. * is not supported.
  612. */
  613. STATUS cacheFlush
  614.     (
  615.     CACHE_TYPE cache, /* cache to flush */
  616.     void * address, /* virtual address */
  617.     size_t bytes /* number of bytes to flush */
  618.     )
  619.     {
  620.     return ((cacheLib.flushRtn == NULL) ? OK : 
  621.             (cacheLib.flushRtn) (cache, address, bytes));
  622.     }
  623. /**************************************************************************
  624. *
  625. * cacheInvalidate - invalidate all or some of a specified cache
  626. *
  627. * This routine invalidates all or some of the entries in the
  628. * specified cache.  Depending on the cache design, the invalidation
  629. * may be similar to the flush, or one may invalidate the tags directly.
  630. *
  631. * RETURNS: OK, or ERROR if the cache type is invalid or the cache control
  632. * is not supported.
  633. */
  634. STATUS cacheInvalidate
  635.     (
  636.     CACHE_TYPE cache, /* cache to invalidate */
  637.     void * address, /* virtual address */
  638.     size_t bytes /* number of bytes to invalidate */
  639.     )
  640.     {
  641.     return ((cacheLib.invalidateRtn == NULL) ? OK : 
  642.             (cacheLib.invalidateRtn) (cache, address, bytes));
  643.     }
  644. /**************************************************************************
  645. *
  646. * cacheClear - clear all or some entries from a cache
  647. *
  648. * This routine flushes and invalidates all or some entries in the
  649. * specified cache.
  650. *
  651. * RETURNS: OK, or ERROR if the cache type is invalid or the cache control
  652. * is not supported.
  653. */
  654. STATUS cacheClear
  655.     (
  656.     CACHE_TYPE cache, /* cache to clear */
  657.     void * address, /* virtual address */
  658.     size_t bytes /* number of bytes to clear */
  659.     )
  660.     {
  661.     return ((cacheLib.clearRtn == NULL) ? ERROR : 
  662.             (cacheLib.clearRtn) (cache, address, bytes));
  663.     }
  664. /**************************************************************************
  665. *
  666. * cachePipeFlush - flush processor write buffers to memory
  667. *
  668. * This routine forces the processor output buffers to write their contents 
  669. * to RAM.  A cache flush may have forced its data into the write buffers, 
  670. * then the buffers need to be flushed to RAM to maintain coherency.
  671. *
  672. * RETURNS: OK, or ERROR if the cache control is not supported.
  673. */
  674. STATUS cachePipeFlush (void)
  675.     {
  676.     return ((cacheLib.pipeFlushRtn == NULL) ? OK :
  677.             (cacheLib.pipeFlushRtn) ());
  678.     }
  679. /**************************************************************************
  680. *
  681. * cacheTextUpdate - synchronize the instruction and data caches
  682. *
  683. * This routine flushes the data cache, then invalidates the instruction 
  684. * cache.  This operation forces the instruction cache to fetch code that 
  685. * may have been created via the data path.
  686. *
  687. * RETURNS: OK, or ERROR if the cache control is not supported.
  688. */
  689. STATUS cacheTextUpdate 
  690.     (
  691.     void * address, /* virtual address */
  692.     size_t bytes /* number of bytes to sync */
  693.     )
  694.     {
  695.     /* if address not valid, return */
  696.     if ((UINT32) address == NONE)
  697. return ERROR;
  698.     return ((cacheLib.textUpdateRtn == NULL) ? OK :
  699.             (cacheLib.textUpdateRtn) (address, bytes));
  700.     }
  701. /**************************************************************************
  702. *
  703. * cacheDmaMalloc - allocate a cache-safe buffer for DMA devices and drivers
  704. *
  705. * This routine returns a pointer to a section of memory that will not 
  706. * experience any cache coherency problems.  Function pointers in the 
  707. * CACHE_FUNCS structure provide access to DMA support routines.
  708. *
  709. * RETURNS: A pointer to the cache-safe buffer, or NULL.
  710. */
  711. void * cacheDmaMalloc 
  712.     (
  713.     size_t bytes /* number of bytes to allocate */
  714.     )
  715.     {
  716.     return ((cacheDmaMallocRtn == NULL) ?
  717.     malloc (bytes) : ((void *) (cacheDmaMallocRtn) (bytes)));
  718.     }
  719. /**************************************************************************
  720. *
  721. * cacheDmaFree - free the buffer acquired with cacheDmaMalloc()
  722. *
  723. * This routine frees the buffer returned by cacheDmaMalloc().
  724. *
  725. * RETURNS: OK, or ERROR if the cache control is not supported.
  726. */
  727. STATUS cacheDmaFree 
  728.     (
  729.     void * pBuf /* pointer to malloc/free buffer */
  730.     )
  731.     {
  732.     return ((cacheDmaFreeRtn == NULL) ?
  733.     free (pBuf), OK : (cacheDmaFreeRtn) (pBuf));
  734.     }
  735. /**************************************************************************
  736. *
  737. * cacheFuncsSet - set cache functions according to configuration
  738. *
  739. * This routine initializes the various CACHE_FUNCS structures.
  740. *
  741. * NOMANUAL
  742. */
  743. void cacheFuncsSet (void)
  744.     {
  745.     if ((cacheDataEnabled == FALSE) || 
  746. (cacheDataMode & CACHE_SNOOP_ENABLE))
  747. {
  748. /* no cache or fully coherent cache */
  749. cacheUserFuncs = cacheNullFuncs;
  750. cacheDmaFuncs  = cacheNullFuncs;
  751. #if (CPU == MC68060)
  752. cacheDmaMallocRtn = cacheLib.dmaMallocRtn;
  753. cacheDmaFreeRtn   = cacheLib.dmaFreeRtn;;
  754. #else
  755. cacheDmaMallocRtn = NULL;
  756. cacheDmaFreeRtn   = NULL;
  757. #endif /* (CPU == MC68060) */
  758. }
  759.     else
  760. {
  761. /* cache is not fully coherent */
  762. cacheUserFuncs.invalidateRtn = cacheLib.invalidateRtn;
  763. if (cacheDataMode & CACHE_WRITETHROUGH)
  764.     cacheUserFuncs.flushRtn = NULL;
  765. else
  766.     cacheUserFuncs.flushRtn = cacheLib.flushRtn;
  767. #if (CPU_FAMILY==I80X86) /* for write-back external cache */
  768. cacheUserFuncs.flushRtn = cacheLib.flushRtn;
  769. #endif
  770. if (cacheMmuAvailable)
  771.     {
  772.     /* MMU available - dma buffers will be made non-cacheable */
  773.     cacheDmaFuncs.flushRtn = NULL;
  774.     cacheDmaFuncs.invalidateRtn = NULL;
  775.     cacheDmaFuncs.virtToPhysRtn = cacheLib.dmaVirtToPhysRtn;
  776.     cacheDmaFuncs.physToVirtRtn = cacheLib.dmaPhysToVirtRtn;
  777.     cacheDmaMallocRtn = cacheLib.dmaMallocRtn;
  778.     cacheDmaFreeRtn = cacheLib.dmaFreeRtn;
  779.     }
  780. else
  781.     {
  782.     /* no MMU - dma buffers are same as regular buffers */
  783.     cacheDmaFuncs = cacheUserFuncs;
  784.     cacheDmaMallocRtn = NULL;
  785.     cacheDmaFreeRtn   = NULL;
  786.     }
  787. }
  788.     }
  789. /**************************************************************************
  790. * cacheDrvFlush - flush the data cache for drivers
  791. *
  792. * This routine flushes the data cache entries using the function pointer 
  793. * from the specified set.
  794. * RETURNS: OK, or ERROR if the cache control is not supported.
  795. */
  796. STATUS cacheDrvFlush 
  797.     (
  798.     CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */
  799.     void * address, /* virtual address */
  800.     size_t bytes /* number of bytes to flush */
  801.     )
  802.     {
  803.     return (CACHE_DRV_FLUSH (pFuncs, address, bytes));
  804.     }
  805. /**************************************************************************
  806. * cacheDrvInvalidate - invalidate data cache for drivers
  807. * This routine invalidates the data cache entries using the function pointer 
  808. * from the specified set.
  809. *
  810. * RETURNS: OK, or ERROR if the cache control is not supported.
  811. */
  812. STATUS cacheDrvInvalidate 
  813.     (
  814.     CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */
  815.     void * address, /* virtual address */
  816.     size_t bytes /* no. of bytes to invalidate */
  817.     )
  818.     {
  819.     return (CACHE_DRV_INVALIDATE (pFuncs, address, bytes));
  820.     }
  821. /**************************************************************************
  822. * cacheDrvVirtToPhys - translate a virtual address for drivers
  823. * This routine performs a virtual-to-physical address translation using the 
  824. * function pointer from the specified set.
  825. * RETURNS: The physical address translation of a virtual address argument.
  826. */
  827. void * cacheDrvVirtToPhys 
  828.     (
  829.     CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */
  830.     void * address /* virtual address */
  831.     )
  832.     {
  833.     return (CACHE_DRV_VIRT_TO_PHYS (pFuncs, address));
  834.     }
  835. /**************************************************************************
  836. * cacheDrvPhysToVirt - translate a physical address for drivers
  837. * This routine performs a physical-to-virtual address translation using the 
  838. * function pointer from the specified set.
  839. * RETURNS: The virtual address that maps to the physical address argument.
  840. */
  841. void * cacheDrvPhysToVirt 
  842.     (
  843.     CACHE_FUNCS * pFuncs, /* pointer to CACHE_FUNCS */
  844.     void * address /* physical address */
  845.     )
  846.     {
  847.     return (CACHE_DRV_PHYS_TO_VIRT (pFuncs, address));
  848.     }