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

VxWorks

开发平台:

C/C++

  1. /* cacheArchLib.c - I80X86 cache management library */
  2. /* Copyright 1984-2002 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01r,15apr02,pai  Removed sysCpuProbe() call, as the CPU probe is separated
  8.                  from the cache library configuration (SPR 74951).
  9. 01q,07mar02,hdn  added CLFLUSH macros.  cleaned up (spr 73360)
  10. 01p,04dec01,hdn  made SNOOP_ENABLE dataMode independent of CPU type
  11.  added cacheArchDmaMallocSnoop() and cacheArchDmaFreeSnoop()
  12. 01o,20nov01,hdn  doc clean up for 5.5
  13. 01n,02nov01,hdn  enabled SSE and SSE2.
  14. 01m,23aug01,hdn  added PENTIUM4 support
  15. 01l,15feb99,hdn  added support for PentiumPro's bus snoop.
  16. 01k,09apr98,hdn  added support for PentiumPro.
  17. 01j,17jun96,hdn  stopped to use a return value of sysCpuProbe().
  18. 01i,21sep95,hdn  added support for NS486.
  19. 01h,01nov94,hdn  added a check of sysProcessor for Pentium
  20. 01g,27oct94,hdn  cleaned up.
  21. 01f,04oct94,hdn  added a checking and setting the cache mode.
  22. 01e,29may94,hdn  changed a macro I80486 to sysProcessor.
  23. 01d,05nov93,hdn  added cacheArchFlush().
  24. 01c,30jul93,hdn  added cacheArchDmaMalloc(), cacheArchDmaFree().
  25. 01b,27jul93,hdn  added cacheArchClearEntry().
  26. 01a,08jun93,hdn  written.
  27. */
  28. /*
  29. DESCRIPTION
  30. This library contains architecture-specific cache library functions for
  31. the Intel 80X86 family caches.
  32. The 386 family does not have a cache, though it has the prefetch queue.  
  33. The 486 family includes a unified L1 cache for both instructions and data.
  34. The P5(Pentium) family includes separate L1 instruction and data caches.  
  35. The data cache supports a writeback or writethrough update policy.
  36. The P6(PentiumPro, II, III) family includes a separate L1 instruction and 
  37. data caches, and unified internal L2 cache.  The MESI cache protocol 
  38. maintains consistency in the L1 and L2 caches in both uni-processor and
  39. multi-processor system.  The P7(Pentium4) family includes the trace cache 
  40. that caches decoded instructions, L1 data cache and L2 unified cache.  
  41. The CLFLUSH instruction allows selected cache line to be flushed from 
  42. memory.
  43. INCLUDE FILES: cacheLib.h
  44. SEE ALSO: cacheLib, vmLib, Intel Architecture Software Developer's Manual
  45. */
  46. /* LINTLIBRARY */
  47. #include "vxWorks.h"
  48. #include "errnoLib.h"
  49. #include "cacheLib.h"
  50. #include "stdlib.h"
  51. #include "private/memPartLibP.h"
  52. #include "private/vmLibP.h"
  53. #include "private/funcBindP.h"
  54. #include "regs.h"
  55. /* externals */
  56. IMPORT UINT sysProcessor;
  57. IMPORT CPUID sysCpuId;
  58. /* globals */
  59. int cacheFlushBytes = CLFLUSH_DEF_BYTES; /* def bytes flushed by CLFLUSH */
  60. /* forward declarations */
  61. LOCAL void * cacheArchDmaMallocSnoop (size_t bytes);
  62. LOCAL STATUS cacheArchDmaFreeSnoop (void * pBuf);
  63. /*******************************************************************************
  64. *
  65. * cacheArchLibInit - initialize the cache library
  66. * This routine initializes the cache library for Intel 80X86
  67. * processors.  The caching mode CACHE_WRITETHROUGH is available for the x86
  68. * processor family.  It initializes the function pointers.
  69. *
  70. * RETURNS: OK.
  71. */
  72. STATUS cacheArchLibInit
  73.     (
  74.     CACHE_MODE instMode, /* instruction cache mode */
  75.     CACHE_MODE dataMode /* data cache mode */
  76.     )
  77.     {
  78.     static BOOL cacheArchLibInitDone = FALSE;
  79.     if (!cacheArchLibInitDone) /* do it only once */
  80.         {
  81. /* get bytes flushed by CLFLUSH instruction if supported */
  82. if (sysCpuId.featuresEdx & CPUID_CLFLUSH)
  83.     cacheFlushBytes = (sysCpuId.featuresEbx & CPUID_CHUNKS) >> 5;
  84. cacheArchLibInitDone = TRUE; /* mark the done-flag TRUE */
  85.         }
  86.     /* 386 family does not have cache and WBINVD instruction */
  87.     if (sysProcessor != X86CPU_386)
  88. {
  89.         cacheLib.enableRtn = cacheArchEnable; /* cacheEnable() */
  90.         cacheLib.disableRtn = cacheArchDisable; /* cacheDisable() */
  91.         cacheLib.lockRtn = cacheArchLock; /* cacheLock() */
  92.         cacheLib.unlockRtn = cacheArchUnlock; /* cacheUnlock() */
  93.         cacheLib.dmaMallocRtn = (FUNCPTR)cacheArchDmaMalloc;
  94.         cacheLib.dmaFreeRtn = (FUNCPTR)cacheArchDmaFree;
  95.         cacheLib.dmaVirtToPhysRtn = NULL;
  96.         cacheLib.dmaPhysToVirtRtn = NULL;
  97.         cacheLib.textUpdateRtn = NULL;
  98. /* note: return type of cachePen4Flush() and cacheI86Flush() are void */
  99.         if (sysCpuId.featuresEdx & CPUID_CLFLUSH) /* cacheFlush() */
  100.     {
  101.             cacheLib.flushRtn    = (FUNCPTR)cachePen4Flush; /* w CLFLUSH */
  102.     cacheLib.clearRtn    = (FUNCPTR)cachePen4Clear; /* w CLFLUSH */
  103.             cacheLib.invalidateRtn = (FUNCPTR)cachePen4Clear; /* w CLFLUSH */
  104.     }
  105. else
  106.     {
  107.             cacheLib.flushRtn    = (FUNCPTR)cacheI86Flush; /* w WBINVD */
  108.     cacheLib.clearRtn    = (FUNCPTR)cacheI86Clear; /* w WBINVD */
  109.             cacheLib.invalidateRtn = (FUNCPTR)cacheI86Clear; /* w WBINVD */
  110.     }
  111.         cacheLib.pipeFlushRtn = NULL;
  112. }
  113.     /* fully coherent cache needs nothing */
  114.     if (dataMode & CACHE_SNOOP_ENABLE)
  115. {
  116.         cacheLib.lockRtn = NULL; /* cacheLock() */
  117.         cacheLib.unlockRtn = NULL; /* cacheUnlock() */
  118.         cacheLib.clearRtn = NULL; /* cacheClear() */
  119.         cacheLib.dmaMallocRtn   = (FUNCPTR)cacheArchDmaMallocSnoop;
  120.         cacheLib.dmaFreeRtn = (FUNCPTR)cacheArchDmaFreeSnoop;
  121.         cacheLib.flushRtn = NULL; /* cacheFlush() */
  122.         cacheLib.invalidateRtn  = NULL; /* cacheClear() */
  123. }
  124.     /* check for parameter errors */
  125.     if ((instMode & CACHE_WRITEALLOCATE) || 
  126. (dataMode & CACHE_WRITEALLOCATE) ||
  127.         (instMode & CACHE_NO_WRITEALLOCATE) || 
  128. (dataMode & CACHE_NO_WRITEALLOCATE) ||
  129.         (instMode & CACHE_BURST_ENABLE) || 
  130. (dataMode & CACHE_BURST_ENABLE) ||
  131.         (instMode & CACHE_BURST_DISABLE) || 
  132. (dataMode & CACHE_BURST_DISABLE))
  133. return (ERROR);
  134.     /* reset to the known state(disabled), since the current mode is unknown */
  135.     if (sysProcessor != X86CPU_386)
  136.         cacheI86Reset (); /* reset and disable a cache */
  137.     cacheDataMode = dataMode; /* save dataMode for enable */
  138.     cacheDataEnabled = FALSE; /* d-cache is currently off */
  139.     cacheMmuAvailable = FALSE; /* no mmu yet */
  140.     return (OK);
  141.     }
  142. /*******************************************************************************
  143. *
  144. * cacheArchEnable - enable a cache
  145. *
  146. * This routine enables the cache.
  147. *
  148. * RETURNS: OK.
  149. *
  150. * NOMANUAL
  151. */
  152. STATUS cacheArchEnable
  153.     (
  154.     CACHE_TYPE cache /* cache to enable */
  155.     )
  156.     {
  157.     cacheI86Enable ();
  158.     if (cache == DATA_CACHE)
  159. {
  160. cacheDataEnabled = TRUE;
  161. cacheFuncsSet ();
  162. }
  163.     return (OK);
  164.     }
  165. /*******************************************************************************
  166. *
  167. * cacheArchDisable - disable a cache
  168. *
  169. * This routine disables the cache.
  170. *
  171. * RETURNS: OK.
  172. *
  173. * NOMANUAL
  174. */
  175. STATUS cacheArchDisable
  176.     (
  177.     CACHE_TYPE cache /* cache to disable */
  178.     )
  179.     {
  180.     cacheI86Disable ();
  181.     if (cache == DATA_CACHE)
  182. {
  183. cacheDataEnabled = FALSE; /* data cache is off */
  184. cacheFuncsSet (); /* update data function ptrs */
  185. }
  186.     return (OK);
  187.     }
  188. /*******************************************************************************
  189. *
  190. * cacheArchLock - lock entries in a cache
  191. *
  192. * This routine locks all entries in the cache.
  193. *
  194. * RETURNS: OK.
  195. *
  196. * NOMANUAL
  197. */
  198. STATUS cacheArchLock
  199.     (
  200.     CACHE_TYPE cache,  /* cache to lock */
  201.     void * address, /* address to lock */
  202.     size_t bytes /* bytes to lock (ENTIRE_CACHE) */
  203.     )
  204.     {
  205.     cacheI86Lock ();
  206.     return (OK);
  207.     }
  208. /*******************************************************************************
  209. *
  210. * cacheArchUnlock - unlock a cache
  211. *
  212. * This routine unlocks all entries in the cache.
  213. *
  214. * RETURNS: OK.
  215. *
  216. * NOMANUAL
  217. */
  218. STATUS cacheArchUnlock
  219.     (
  220.     CACHE_TYPE cache,  /* cache to unlock */
  221.     void * address, /* address to unlock */
  222.     size_t bytes /* bytes to unlock (ENTIRE_CACHE) */
  223.     )
  224.     {
  225.     cacheI86Unlock ();
  226.     return (OK);
  227.     }
  228. /*******************************************************************************
  229. *
  230. * cacheArchClear - clear all entries from a cache
  231. *
  232. * This routine clears all entries from the cache.  
  233. *
  234. * RETURNS: OK.
  235. *
  236. * NOMANUAL
  237. */
  238. STATUS cacheArchClear
  239.     (
  240.     CACHE_TYPE cache,  /* cache to clear */
  241.     void * address, /* address to clear */
  242.     size_t bytes /* bytes to clear */
  243.     )
  244.     {
  245.     if (sysCpuId.featuresEdx & CPUID_CLFLUSH)
  246. cachePen4Clear (cache, address, bytes);
  247.     else
  248. WRS_ASM ("wbinvd");
  249.     return (OK);
  250.     }
  251. /*******************************************************************************
  252. *
  253. * cacheArchFlush - flush all entries from a cache
  254. *
  255. * This routine flushs all entries from the cache.  
  256. *
  257. * RETURNS: OK.
  258. *
  259. * NOMANUAL
  260. */
  261. STATUS cacheArchFlush
  262.     (
  263.     CACHE_TYPE cache,  /* cache to clear */
  264.     void * address, /* address to clear */
  265.     size_t bytes /* bytes to clear */
  266.     )
  267.     {
  268.     if (sysCpuId.featuresEdx & CPUID_CLFLUSH)
  269. cachePen4Flush (cache, address, bytes);
  270.     else
  271. WRS_ASM ("wbinvd");
  272.     return (OK);
  273.     }
  274. /*******************************************************************************
  275. *
  276. * cacheArchClearEntry - clear an entry from a cache
  277. *
  278. * This routine clears a specified entry from the cache.
  279. * The 386 family processors do not have a cache, thus it does nothing.  The 486, 
  280. * P5(Pentium), and P6(PentiumPro, II, III) family processors do have a cache but 
  281. * does not support a line by line cache control, thus it performs WBINVD 
  282. * instruction.  The P7(Pentium4) family processors support the line by line 
  283. * cache control with CLFLUSH instruction, thus flushes the specified cache line.
  284. *
  285. * RETURNS: OK
  286. */
  287. STATUS cacheArchClearEntry
  288.     (
  289.     CACHE_TYPE cache, /* cache to clear entry for */
  290.     void * address /* entry to clear */
  291.     )
  292.     {
  293.     if (sysProcessor == X86CPU_386)
  294.         return (OK);
  295.     if (sysCpuId.featuresEdx & CPUID_CLFLUSH)
  296. cachePen4Clear (cache, address, cacheFlushBytes);
  297.     else
  298. WRS_ASM ("wbinvd");
  299.     return (OK);
  300.     }
  301. /*******************************************************************************
  302. *
  303. * cacheArchDmaMalloc - allocate a cache-safe buffer
  304. *
  305. * This routine attempts to return a pointer to a section of memory
  306. * that will not experience cache coherency problems.  This routine
  307. * is only called when MMU support is available 
  308. * for cache control.
  309. *
  310. * INTERNAL
  311. * We check if the cache is actually on before allocating the memory.  It
  312. * is possible that the user wants Memory Management Unit (MMU)
  313. * support but does not need caching.
  314. *
  315. * RETURNS: A pointer to a cache-safe buffer, or NULL.
  316. *
  317. * SEE ALSO: cacheArchDmaFree(), cacheDmaMalloc()
  318. *
  319. * NOMANUAL
  320. */
  321. void *cacheArchDmaMalloc 
  322.     (
  323.     size_t      bytes /* size of cache-safe buffer */
  324.     )
  325.     {
  326.     void *pBuf;
  327.     int   pageSize;
  328.     if ((pageSize = VM_PAGE_SIZE_GET ()) == ERROR)
  329. return (NULL);
  330.     /* make sure bytes is a multiple of pageSize */
  331.     bytes = ROUND_UP (bytes, pageSize);
  332.     if ((_func_valloc == NULL) || 
  333. ((pBuf = (void *)(* _func_valloc) (bytes)) == NULL))
  334. return (NULL);
  335.     VM_STATE_SET (NULL, pBuf, bytes,
  336.   VM_STATE_MASK_CACHEABLE, VM_STATE_CACHEABLE_NOT);
  337.     return (pBuf);
  338.     }
  339. /*******************************************************************************
  340. *
  341. * cacheArchDmaFree - free the buffer acquired by cacheArchDmaMalloc()
  342. *
  343. * This routine returns to the free memory pool a block of memory previously
  344. * allocated with cacheArchDmaMalloc().  The buffer is marked cacheable.
  345. *
  346. * RETURNS: OK, or ERROR if cacheArchDmaMalloc() cannot be undone.
  347. *
  348. * SEE ALSO: cacheArchDmaMalloc(), cacheDmaFree()
  349. *
  350. * NOMANUAL
  351. */
  352. STATUS cacheArchDmaFree
  353.     (
  354.     void *pBuf /* ptr returned by cacheArchDmaMalloc() */
  355.     )
  356.     {
  357.     BLOCK_HDR * pHdr; /* pointer to block header */
  358.     STATUS status = OK; /* return value */
  359.     if (vmLibInfo.vmLibInstalled)
  360. {
  361. pHdr = BLOCK_TO_HDR (pBuf);
  362. status = VM_STATE_SET (NULL,pBuf,(pHdr->nWords * 2) - sizeof(BLOCK_HDR),
  363.        VM_STATE_MASK_CACHEABLE, VM_STATE_CACHEABLE);
  364. }
  365.     free (pBuf); /* free buffer after modified */
  366.     return (status);
  367.     }
  368. /*******************************************************************************
  369. *
  370. * cacheArchDmaMallocSnoop - allocate a cache line aligned buffer
  371. *
  372. * This routine attempts to return a pointer to a section of memory in the
  373. * SNOOP_ENABLED cache mode.  This routine is called regardless of the current
  374. * MMU or CACHE status.  And does not change cache attribute of the buffer.
  375. *
  376. * RETURNS: A pointer to a cache line aligned buffer, or NULL.
  377. *
  378. * SEE ALSO: cacheArchDmaFreeSnoop(), cacheDmaMalloc()
  379. *
  380. * NOMANUAL
  381. */
  382. LOCAL void * cacheArchDmaMallocSnoop 
  383.     (
  384.     size_t      bytes /* size of cache-safe buffer */
  385.     )
  386.     {
  387.     void * pBuf;
  388.     /* make sure bytes is a multiple of cache line size */
  389.     bytes = ROUND_UP (bytes, _CACHE_ALIGN_SIZE);
  390.     /* allocate memory at cache line boundary */
  391.     if ((pBuf = memalign (_CACHE_ALIGN_SIZE, bytes)) == NULL)
  392. return (NULL);
  393.     return (pBuf);
  394.     }
  395. /*******************************************************************************
  396. *
  397. * cacheArchDmaFreeSnoop - free the buffer acquired by cacheArchDmaMallocSnoop()
  398. *
  399. * This routine returns to the free memory pool a block of memory previously
  400. * allocated with cacheArchDmaMallocSnoop().  The cache attribute of the buffer 
  401. * does not change.
  402. *
  403. * RETURNS: OK always.
  404. *
  405. * SEE ALSO: cacheArchDmaMallocSnoop(), cacheDmaFree()
  406. *
  407. * NOMANUAL
  408. */
  409. LOCAL STATUS cacheArchDmaFreeSnoop
  410.     (
  411.     void * pBuf /* ptr returned by cacheArchDmaMallocSnoop() */
  412.     )
  413.     {
  414.     free (pBuf); /* free buffer */
  415.     return (OK);
  416.     }