vmLib.c
上传用户:baixin
上传日期:2008-03-13
资源大小:4795k
文件大小:39k
开发平台:

MultiPlatform

  1. /* vmLib.c - architecture-independent virtual memory support library (VxVMI Option) */
  2. /* Copyright 1984-2001 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 02a,02apr02,dtr  Adding PPC860.
  8. 01z,16nov01,to   declare global variables in vmData.c to avoid getting multiple
  9.                  vm*Lib.o pulled
  10. 01y,26jul01,scm  add extended small page table support for XScale...
  11. 01x,03mar00,zl   merged SH support into T2
  12. 01w,30mar99,jdi  doc: fixed table formatting that refgen can't handle.
  13. 01v,14mar99,jdi  doc: removed refs to config.h and/or configAll.h (SPR 25663).
  14. 01u,21feb99,jdi  doc: listed errnos.
  15. 01t,02jul96,ms   replaced "%" with "NOT_PAGE_ALIGNED" to fix SPR 6833.
  16. 01s,04mar96,ms   made null for PPC.
  17. 01r,13sep93,caf  made null for MIPS.
  18. 01s,18nov93,edm  changed BOOL mmuPhysAddrShifted to int mmuPhysAddrShift.
  19. 01r,05apr93,edm  added support for physical addresses->page number option.
  20. 01q,19feb93,jdi  doc: add VxVMI option label and Availability section.
  21. 01p,12feb93,jdi  doc tweaks.
  22. 01o,12feb93,rdc  changed scheme for sharing data structures with mmuLib. Doc.
  23. 01n,09feb93,rdc  added vmTextPageProtect.  
  24. 01m,21oct92,jdi  doc change as per pme.
  25. 01l,19oct92,jcf  cleanup. fixed vmLibInit.
  26. 01k,14oct92,jdi  made vmContextInit() NOMANUAL.
  27. 01j,02oct92,jdi  documentation cleanup.
  28. 01i,01oct92,jcf  added cacheFuncsSet() to attach mmu to cache support.
  29. 01h,22sep92,rdc  changed NUM_PAGE_STATES to 256.  
  30.  changed globalPageBlockArray to be type UINT8 instead of BOOL.
  31. 01g,23aug92,jcf  cleanup.
  32. 01f,30jul92,rdc  added pointer to vmTranslate routine to vmLibInfo. 
  33. 01e,27jul92,rdc  moved  "vmLib.c" to "vmBaseLib.c", and installed the
  34.  unbundled vmLib.c here.
  35. 01d,21jul92,rdc  took out mutex in vmStateSet so callable from int level.
  36. 01c,13jul92,rdc  changed reference to vmLib.h to vmLibP.h.
  37. 01b,09jul92,rdc  changed indirect routine pointer configuration.
  38. 01a,08jul92,rdc  written.
  39. */
  40. /*
  41. DESCRIPTION
  42. This library provides an architecture-independent interface to the CPU's
  43. memory management unit (MMU).  Although vmLib is implemented with
  44. architecture-specific libraries, application code need never reference
  45. directly the architecture-dependent code in these libraries.
  46. A fundamental goal in the design of vmLib was to permit transparent
  47. backward compatibility with previous versions of VxWorks that did not use
  48. the MMU.  System designers may opt to disable the MMU because of timing
  49. constraints, and some architectures do not support MMUs; therefore VxWorks
  50. functionality must not be dependent on the MMU.  The resulting design
  51. permits a transparent configuration with no change in the programming
  52. environment (but the addition of several protection features, such as text
  53. segment protection) and the ability to disable virtual memory in systems
  54. that require it.
  55. The vmLib library provides a mechanism for creating virtual memory contexts,
  56. vmContextCreate().  These contexts are not automatically created for individual 
  57. tasks, but may be created dynamically by tasks, and swapped in and out 
  58. in an application specific manner. 
  59. All virtual memory contexts share a global transparent mapping of virtual
  60. to physical memory for all of local memory and the local hardware device
  61. space (defined in sysLib.c for each board port in the `sysPhysMemDesc'
  62. data structure).  When the system is initialized, all of local physical
  63. memory is accessible at the same address in virtual memory (this is done
  64. with calls to vmGlobalMap().)  Modifications made to this global mapping
  65. in one virtual memory context appear in all virtual memory contexts.  For
  66. example, if the exception vector table (which resides at address 0 in
  67. physical memory) is made read only by calling vmStateSet() on virtual
  68. address 0, the vector table will be read only in all virtual memory
  69. contexts.
  70. Private virtual memory can also be created.  When physical pages are
  71. mapped to virtual memory that is not in the global transparent region,
  72. this memory becomes accessible only in the context in which it was
  73. mapped.  (The physical pages will also be accessible in the transparent
  74. translation at the physical address, unless the virtual pages in the
  75. global transparent translation region are explicitly invalidated.)  State
  76. changes (writability, validity, etc.) to a section of private virtual
  77. memory in a virtual memory context do not appear in other contexts.  To
  78. facilitate the allocation of regions of virtual space, vmGlobalInfoGet()
  79. returns a pointer to an array of booleans describing which portions of the
  80. virtual address space are devoted to global memory.  Each successive array
  81. element corresponds to contiguous regions of virtual memory the size of
  82. which is architecture-dependent and which may be obtained with a call to
  83. vmPageBlockSizeGet().  If the boolean array element is true, the
  84. corresponding region of virtual memory, a "page block", is reserved for
  85. global virtual memory and should not be used for private virtual memory.
  86. (If vmMap() is called to map virtual memory previously defined as global,
  87. the routine will return an error.)
  88. All the state information for a block of virtual memory can be set in a
  89. single call to vmStateSet().  It performs parameter checking and checks
  90. the validity of the specified virtual memory context.  It may also be used
  91. to set architecture-dependent state information.  See vmLib.h for additional
  92. architecture-dependent state information.
  93. The routine vmContextShow() in vmShow displays the virtual memory context
  94. for a specified context.  For more information, see the manual entry for
  95. this routine.
  96. CONFIGURATION:
  97. Full MMU support (vmLib, and optionally, vmShow) is included in VxWorks
  98. when the configuration macro INCLUDE_MMU_FULL is defined.  If the
  99. configuration macro INCLUDE_MMU_BASIC is also defined, the default is
  100. full MMU support (unbundled).
  101. The sysLib.c library contains a data structure called `sysPhysMemDesc',
  102. which is an array of PHYS_MEM_DESC structures.  Each element of the array
  103. describes a contiguous section of physical memory.  The description of
  104. this memory includes its physical address, the virtual address where it
  105. should be mapped (typically, this is the same as the physical address, but
  106. not necessarily so), an initial state for the memory, and a mask defining
  107. which state bits in the state value are to be set.  Default configurations
  108. are defined for each board support package (BSP), but these mappings may
  109. be changed to suit user-specific system configurations.  For example, the
  110. user may need to map additional VME space where the backplane network
  111. interface data structures appear.
  112. INTERNAL
  113. Mutual exclusion is provided in all operations that modify and examine
  114. translation tables;  routines in mmuLib need not provide mutual exclusion
  115. mechanisms for translation tables.
  116. AVAILABILITY
  117. This library and vmShow are distributed as the unbundled virtual memory
  118. support option, VxVMI.  A scaled down version, vmBaseLib, is
  119. provided with VxWorks for systems that do not permit optional use of the
  120. MMU, or for architectures that require certain features of the MMU to
  121. perform optimally (in particular, architectures that rely heavily on
  122. caching, but do not support bus snooping, and thus require the ability to
  123. mark interprocessor communications buffers as non-cacheable.)  Most
  124. routines in vmBaseLib are referenced internally by VxWorks; they are not
  125. callable by application code.
  126. INCLUDE FILES: vmLib.h 
  127. SEE ALSO: sysLib, vmShow,
  128. .pG "Virtual Memory"
  129. */
  130. #include "vxWorks.h"
  131. #if     (CPU_FAMILY != MIPS)  && ((CPU_FAMILY!=PPC) || (CPU==PPC860))
  132. #include "private/vmLibP.h"
  133. #include "stdlib.h"
  134. #include "mmuLib.h"
  135. #include "private/classLibP.h"
  136. #include "private/objLibP.h"
  137. #include "errno.h"
  138. #include "cacheLib.h"
  139. #include "sysLib.h"
  140. #include "private/semLibP.h"
  141. /* macros and defines */
  142. /* detect if addr is in global virtual memory */
  143. #define ADDR_IN_GLOBAL_SPACE(vAddr) (globalPageBlockArray[(unsigned) vAddr / mmuPageBlockSize])
  144. /* compute if page is aligned without using "%" (SPR 6833) */
  145. #define NOT_PAGE_ALIGNED(addr) (((UINT)(addr)) & ((UINT)vmPageSize - 1))
  146. /* macros to reference mmuLib routines indirectly through mmuLibFunc table */
  147. #define MMU_LIB_INIT         (*(mmuLibFuncs.mmuLibInit))
  148. #define MMU_TRANS_TBL_CREATE  (*(mmuLibFuncs.mmuTransTblCreate))
  149. #define MMU_TRANS_TBL_DELETE  (*(mmuLibFuncs.mmuTransTblDelete))
  150. #define MMU_ENABLE     (*(mmuLibFuncs.mmuEnable))
  151. #define MMU_STATE_SET     (*(mmuLibFuncs.mmuStateSet))
  152. #define MMU_STATE_GET     (*(mmuLibFuncs.mmuStateGet))
  153. #define MMU_PAGE_MAP     (*(mmuLibFuncs.mmuPageMap))
  154. #define MMU_GLOBAL_PAGE_MAP  (*(mmuLibFuncs.mmuGlobalPageMap))
  155. #define MMU_TRANSLATE     (*(mmuLibFuncs.mmuTranslate))
  156. #define MMU_CURRENT_SET  (*(mmuLibFuncs.mmuCurrentSet))
  157. IMPORT int mmuPageBlockSize; /* initialized by mmuLib.c */
  158. IMPORT STATE_TRANS_TUPLE *mmuStateTransArray; /* initialized by mmuLib.c */
  159. IMPORT int mmuStateTransArraySize; /* initialized by mmuLib.c */
  160. IMPORT MMU_LIB_FUNCS mmuLibFuncs;  /* initialized by mmuLib.c */
  161. IMPORT int                      mmuPhysAddrShift;       /* see vmData.c */
  162. /* imports */
  163. IMPORT void sysInit ();
  164. IMPORT void etext ();
  165. /* class declaration */
  166. LOCAL VM_CONTEXT_CLASS vmContextClass;
  167. VM_CONTEXT_CLASS_ID vmContextClassId = &vmContextClass;
  168. /* state translation tables - these tables are initialized in vmLibInit,
  169.  * and are used to translate between architecture-independent and architecture
  170.  * dependent states. arch indep. state info uses 8 bits - 2^8=256 possible
  171.  * states 
  172.  */
  173. #define NUM_PAGE_STATES 256
  174. /* locals */
  175. LOCAL UINT vmStateTransTbl[NUM_PAGE_STATES];
  176. LOCAL UINT vmMaskTransTbl[NUM_PAGE_STATES];
  177. LOCAL LIST vmContextList; /* XXX delete ? */
  178. LOCAL int  vmPageSize;
  179. LOCAL VM_CONTEXT sysVmContext;       /* initial vm context */
  180. LOCAL VM_CONTEXT * currentContext = NULL;
  181. LOCAL SEMAPHORE  globalMemMutex;
  182. /* globals */
  183. UINT8 *globalPageBlockArray;
  184. int    mutexOptionsVmLib = SEM_Q_PRIORITY |SEM_DELETE_SAFE | SEM_INVERSION_SAFE;
  185. LOCAL STATUS vmTextPageProtect (void *textPageAddr, BOOL protect);
  186. /*******************************************************************************
  187. *
  188. * vmLibInit - initialize the virtual memory support module (VxVMI Option)
  189. *
  190. * This routine initializes the virtual memory context class.
  191. * It is called only once during system initialization.
  192. *
  193. * AVAILABILITY
  194. * This routine is distributed as a component of the unbundled virtual memory
  195. * support option, VxVMI.
  196. *
  197. * RETURNS: OK.
  198. */
  199. STATUS vmLibInit 
  200.     (
  201.     int pageSize /* size of page */
  202.     )
  203.     {
  204.     int i;
  205.     int  j;
  206.     UINT  newState;
  207.     UINT  newMask;
  208.     int  arraySize;
  209.     if (vmLibInfo.vmLibInstalled) /* only install vmLib once */
  210. return (OK);
  211.     if (pageSize == 0)
  212. return (ERROR); /* check for reasonable parameter */
  213.     vmPageSize = pageSize;
  214.     classInit ((OBJ_CLASS *) &vmContextClass.coreClass, sizeof (VM_CONTEXT), 
  215.        OFFSET(VM_CONTEXT, objCore), (FUNCPTR) vmContextCreate, 
  216.        NULL, NULL);
  217.     /* initialize the mutual exclusion semaphore that protects the global
  218.      * memory mappings.
  219.      */
  220.     semMInit (&globalMemMutex, mutexOptionsVmLib);
  221.     /* initialize the page state translation table.  This table is used to
  222.      * translate betseen architecture-independent state values and architecture
  223.      * dependent state values */
  224.     for (i = 0; i < NUM_PAGE_STATES; i++)
  225. {
  226. newState = 0;
  227. for (j = 0; j < mmuStateTransArraySize; j++)
  228.     {
  229.     STATE_TRANS_TUPLE *thisTuple = &mmuStateTransArray[j];
  230.     UINT archIndepState = thisTuple->archIndepState;
  231.     UINT archDepState = thisTuple->archDepState;
  232.     UINT archIndepMask = thisTuple->archIndepMask;
  233.     if ((i & archIndepMask) == archIndepState)
  234. newState |= archDepState;
  235.     }
  236. vmStateTransTbl [i] = newState;
  237. }
  238.     /* initialize the page state mask translation table.  This table is used to
  239.      * translate betseen architecture-independent state masks and architecture
  240.      * dependent state masks */
  241.     for (i = 0; i < NUM_PAGE_STATES; i++)
  242. {
  243. newMask = 0;
  244. for (j = 0; j < mmuStateTransArraySize; j++)
  245.     {
  246.     STATE_TRANS_TUPLE *thisTuple = &mmuStateTransArray[j];
  247.     UINT archIndepMask = thisTuple->archIndepMask;
  248.     UINT archDepMask = thisTuple->archDepMask;
  249.     if ((i & archIndepMask) == archIndepMask)
  250. newMask |= archDepMask;
  251.     }
  252. vmMaskTransTbl [i] = newMask;
  253. }
  254.     /* allocate memory for global page block array to keep track of which
  255.      * sections of virtual memory are reserved for global virtual memory.
  256.      * number of page blocks in virtual space = (2**32)/pageBlockSize.
  257.      */
  258.     /* what we really want is: 2^32/mmuPageBlockSize, but we can't 
  259.        represent 2^32, so we assume mmuPageBlockSize is even, and divide
  260.        everything by 2 so we can do 32 bit arithmatic */
  261.     arraySize = (UINT) 0x80000000 / (mmuPageBlockSize / 2);
  262.     globalPageBlockArray = (UINT8 *) calloc (arraySize, sizeof (UINT8));
  263.     if (globalPageBlockArray == NULL)
  264.         return (ERROR);
  265.     lstInit (&vmContextList);  /* XXX not currently used */
  266.     vmLibInfo.pVmStateSetRtn    = vmStateSet; 
  267.     vmLibInfo.pVmStateGetRtn    = vmStateGet;
  268.     vmLibInfo.pVmEnableRtn      = vmEnable;
  269.     vmLibInfo.pVmPageSizeGetRtn = vmPageSizeGet;
  270.     vmLibInfo.pVmTranslateRtn   = vmTranslate;
  271.     vmLibInfo.pVmTextProtectRtn = vmTextPageProtect;
  272.     vmLibInfo.vmLibInstalled    = TRUE;
  273.     cacheMmuAvailable = TRUE;
  274.     cacheFuncsSet (); /* update cache funtion pointers */
  275.     return (OK);
  276.     }
  277. /*******************************************************************************
  278. *
  279. * vmGlobalMapInit - initialize global mapping (VxVMI Option)
  280. *
  281. * This routine is a convenience routine that creates and installs a virtual
  282. * memory context with global mappings defined for each contiguous memory
  283. * segment defined in the physical memory descriptor array passed as an
  284. * argument.  The context ID returned becomes the current virtual memory
  285. * context.  
  286. *
  287. * The physical memory descriptor also contains state information
  288. * used to initialize the state information in the MMU's translation table
  289. * for that memory segment.  The following state bits may be or'ed together:
  290. *
  291. * .TS
  292. * tab(|);
  293. * l2 l2 l .
  294. * VM_STATE_VALID    | VM_STATE_VALID_NOT    | valid/invalid
  295. * VM_STATE_WRITABLE | VM_STATE_WRITABLE_NOT | writable/write-protected
  296. * VM_STATE_CACHEABLE| VM_STATE_CACHEABLE_NOT| cacheable/not-cacheable
  297. * .TE
  298. *
  299. * Additionally, mask bits are or'ed together in the `initialStateMask' structure
  300. * element to describe which state bits are being specified in the `initialState'
  301. * structure element:
  302. *
  303. *  VM_STATE_MASK_VALID
  304. *  VM_STATE_MASK_WRITABLE
  305. *  VM_STATE_MASK_CACHEABLE
  306. *
  307. * If the <enable> parameter is TRUE, the MMU is enabled upon return.  
  308. * The vmGlobalMapInit() routine should be called only after vmLibInit() has been
  309. * called.
  310. *
  311. * AVAILABILITY
  312. * This routine is distributed as a component of the unbundled virtual memory
  313. * support option, VxVMI.
  314. *
  315. * RETURNS: A pointer to a newly created virtual memory context, or
  316. * NULL if the memory cannot be mapped.
  317. */
  318. VM_CONTEXT_ID vmGlobalMapInit 
  319.     (
  320.     PHYS_MEM_DESC *pMemDescArray,  /* pointer to array of mem descs    */
  321.     int numDescArrayElements, /* num of elements in pMemDescArray */
  322.     BOOL enable /* enable virtual memory            */
  323.     )
  324.     {
  325.     int i;
  326.     PHYS_MEM_DESC *thisDesc;
  327.     /* set up global transparent mapping of physical to virtual memory */
  328.     for (i = 0; i < numDescArrayElements; i++)
  329.         {
  330.         thisDesc = &pMemDescArray[i];
  331.         /* map physical directly to virtual and set initial state */
  332.         if (vmGlobalMap ((void *) thisDesc->virtualAddr, 
  333.  (void *) thisDesc->physicalAddr,
  334.  thisDesc->len) == ERROR)
  335.             {
  336.     return (NULL);
  337.             }
  338.         }
  339.     /* create default virtual memory context */
  340.     if (vmContextInit (&sysVmContext) == ERROR)
  341. {
  342. return (NULL);
  343. }
  344.     /* set the state of all the global memory we just created */ 
  345.     for (i = 0; i < numDescArrayElements; i++)
  346.         {
  347.         thisDesc = &pMemDescArray[i];
  348. if (vmStateSet (&sysVmContext, thisDesc->virtualAddr, thisDesc->len,
  349. thisDesc->initialStateMask, thisDesc->initialState) == ERROR)
  350.     return (NULL);
  351.         }
  352.     currentContext = &sysVmContext;
  353.     MMU_CURRENT_SET (sysVmContext.mmuTransTbl);
  354.     if (enable)
  355. if (MMU_ENABLE (TRUE) == ERROR)
  356.     return (NULL);
  357.     return (&sysVmContext);
  358.     }
  359. /*******************************************************************************
  360. *
  361. * vmContextCreate - create a new virtual memory context (VxVMI Option)
  362. *
  363. * This routine creates a new virtual memory context.  The newly created
  364. * context does not become the current context until explicitly installed by
  365. * a call to vmCurrentSet().  Modifications to the context state (mappings,
  366. * state changes, etc.) may be performed on any virtual memory context, even
  367. * if it is not the current context.
  368. *
  369. * This routine should not be called from interrupt level.
  370. *
  371. * AVAILABILITY
  372. * This routine is distributed as a component of the unbundled virtual memory
  373. * support option, VxVMI.
  374. *
  375. * RETURNS: A pointer to a new virtual memory context, or 
  376. * NULL if the allocation or initialization fails.
  377. */
  378. VM_CONTEXT_ID vmContextCreate (void)
  379.     {
  380.     VM_CONTEXT_ID context;
  381.     /* call the vm class's memory allocator to get memory for the object */
  382.     context = (VM_CONTEXT *) objAlloc ((OBJ_CLASS *) vmContextClassId);
  383.     if (context == NULL)
  384. return (NULL);
  385.     if (vmContextInit (context) == ERROR)
  386. {
  387. objFree ((OBJ_CLASS *) vmContextClassId, (char *) context);
  388. return (NULL);
  389. }
  390.     
  391.     return (context);
  392.     }
  393. /*******************************************************************************
  394. *
  395. * vmContextInit - initialize VM_CONTEXT structures
  396. *
  397. * This routine may be used to initialize static definitions of VM_CONTEXT
  398. * structures, instead of dynamically creating the object with
  399. * vmContextCreate().  Note that virtual memory contexts created in this
  400. * manner may not be deleted.
  401. *
  402. * This routine should not be called from interrupt level.
  403. *
  404. * AVAILABILITY
  405. * This routine is distributed as a component of the unbundled virtual memory
  406. * support option, VxVMI.
  407. *
  408. * RETURNS: OK, or ERROR if the translation table cannot be created.
  409. *
  410. * NOMANUAL
  411. */
  412. STATUS vmContextInit 
  413.     (
  414.     VM_CONTEXT *pContext
  415.     )
  416.     {
  417.     objCoreInit (&pContext->objCore, (CLASS_ID) vmContextClassId);
  418.     semMInit (&pContext->sem, mutexOptionsVmLib);
  419.     pContext->mmuTransTbl = MMU_TRANS_TBL_CREATE ();
  420.     if (pContext->mmuTransTbl == NULL)
  421. return (ERROR);
  422.     lstAdd (&vmContextList, &pContext->links);
  423.     return (OK);
  424.     }
  425. /*******************************************************************************
  426. *
  427. * vmContextDelete - delete a virtual memory context (VxVMI Option)
  428. *
  429. * This routine deallocates the underlying translation table associated with
  430. * a virtual memory context.  It does not free the physical memory already
  431. * mapped into the virtual memory space.
  432. *
  433. * This routine should not be called from interrupt level.
  434. *
  435. * AVAILABILITY
  436. * This routine is distributed as a component of the unbundled virtual memory
  437. * support option, VxVMI.
  438. *
  439. * RETURNS: OK, or ERROR if <context> is not a valid context descriptor or
  440. * if an error occurs deleting the translation table.
  441. */
  442. STATUS vmContextDelete 
  443.     (
  444.     VM_CONTEXT_ID context
  445.     )
  446.     {
  447.     if (OBJ_VERIFY (context, vmContextClassId) != OK)
  448. return (ERROR);
  449.     /* take the context's mutual exclusion semaphore - this is really 
  450.      * inadequate.
  451.      */
  452.     semTake (&context->sem, WAIT_FOREVER);
  453.     /* invalidate the object */
  454.     objCoreTerminate (&context->objCore);
  455.     if (MMU_TRANS_TBL_DELETE (context->mmuTransTbl) == ERROR)
  456. return (ERROR);
  457.     lstDelete (&vmContextList, &context->links);
  458.     free (context);
  459.     return (OK);
  460.     }
  461. /*******************************************************************************
  462. *
  463. * vmStateSet - change the state of a block of virtual memory (VxVMI Option)
  464. *
  465. * This routine changes the state of a block of virtual memory.  Each page
  466. * of virtual memory has at least three elements of state information:
  467. * validity, writability, and cacheability.  Specific architectures may
  468. * define additional state information; see vmLib.h for additional
  469. * architecture-specific states.  Memory accesses to a page marked as
  470. * invalid will result in an exception.  Pages may be invalidated to prevent
  471. * them from being corrupted by invalid references.  Pages may be defined as
  472. * read-only or writable, depending on the state of the writable bits.
  473. * Memory accesses to pages marked as not-cacheable will always result in a
  474. * memory cycle, bypassing the cache.  This is useful for multiprocessing,
  475. * multiple bus masters, and hardware control registers.
  476. *
  477. * The following states are provided and may be or'ed together in the 
  478. * state parameter:  
  479. *
  480. * .TS
  481. * tab(|);
  482. * l2 l2 l .
  483. * VM_STATE_VALID     | VM_STATE_VALID_NOT     | valid/invalid
  484. * VM_STATE_WRITABLE  | VM_STATE_WRITABLE_NOT  | writable/write-protected
  485. * VM_STATE_CACHEABLE | VM_STATE_CACHEABLE_NOT | cacheable/not-cacheable
  486. * .TE
  487. *
  488. * Additionally, the following masks are provided so that only specific
  489. * states may be set.  These may be or'ed together in the `stateMask' parameter. 
  490. *
  491. *  VM_STATE_MASK_VALID
  492. *  VM_STATE_MASK_WRITABLE
  493. *  VM_STATE_MASK_CACHEABLE
  494. *
  495. * If <context> is specified as NULL, the current context is used.
  496. *
  497. * This routine is callable from interrupt level.
  498. *
  499. * AVAILABILITY
  500. * This routine is distributed as a component of the unbundled virtual memory
  501. * support option, VxVMI.
  502. *
  503. * RETURNS: OK or, ERROR if the validation fails, <pVirtual> is not on a page
  504. * boundary, <len> is not a multiple of page size, or the
  505. * architecture-dependent state set fails for the specified virtual address.
  506. *
  507. * ERRNO: 
  508. * S_vmLib_NOT_PAGE_ALIGNED,
  509. * S_vmLib_BAD_STATE_PARAM,
  510. * S_vmLib_BAD_MASK_PARAM
  511. */
  512. STATUS vmStateSet 
  513.     (
  514.     VM_CONTEXT_ID context,  /* context - NULL == currentContext         */
  515.     void *pVirtual,  /* virtual address to modify state of       */
  516.     int len,  /* len of virtual space to modify state of  */
  517.     UINT stateMask,  /* state mask                               */
  518.     UINT state /* state                                    */
  519.     )
  520.     {
  521.     FAST int pageSize  = vmPageSize;
  522.     FAST char * thisPage  = (char *) pVirtual;
  523.     FAST UINT  numBytesProcessed = 0;
  524.     UINT  archDepState;
  525.     UINT  archDepStateMask;
  526.     STATUS  retVal  = OK;
  527.     if (!vmLibInfo.vmLibInstalled)
  528. return (ERROR);
  529.     if (context == NULL)
  530. context = currentContext;
  531.     if (OBJ_VERIFY (context, vmContextClassId) != OK)
  532. return (ERROR);
  533.     if (NOT_PAGE_ALIGNED (thisPage))
  534. {
  535. errno = S_vmLib_NOT_PAGE_ALIGNED;
  536.         return (ERROR); 
  537. }
  538.     if (NOT_PAGE_ALIGNED (len))
  539. {
  540. errno = S_vmLib_NOT_PAGE_ALIGNED;
  541.         return (ERROR); 
  542. }
  543.     if (state > NUM_PAGE_STATES)
  544. {
  545. errno = S_vmLib_BAD_STATE_PARAM;
  546. return (ERROR);
  547. }
  548.     if (stateMask > NUM_PAGE_STATES)
  549. {
  550. errno = S_vmLib_BAD_MASK_PARAM;
  551. return (ERROR);
  552. }
  553.     archDepState = vmStateTransTbl [state];
  554.     archDepStateMask = vmMaskTransTbl [stateMask];
  555.     while (numBytesProcessed < len)
  556.         {
  557.         if (MMU_STATE_SET (context->mmuTransTbl, thisPage,
  558.                          archDepStateMask, archDepState) == ERROR)
  559.            {
  560.    retVal = ERROR;
  561.    break;
  562.    }
  563.         thisPage += pageSize;
  564. numBytesProcessed += pageSize;
  565. }
  566.     return (retVal);
  567.     }
  568. /*******************************************************************************
  569. *
  570. * vmStateGet - get the state of a page of virtual memory (VxVMI Option)
  571. *
  572. * This routine extracts state bits with the following masks: 
  573. *
  574. *  VM_STATE_MASK_VALID
  575. *  VM_STATE_MASK_WRITABLE
  576. *  VM_STATE_MASK_CACHEABLE
  577. *
  578. * Individual states may be identified with the following constants:
  579. *
  580. * .TS
  581. * tab(|);
  582. * l2 l2 l .
  583. * VM_STATE_VALID    | VM_STATE_VALID_NOT     | valid/invalid
  584. * VM_STATE_WRITABLE | VM_STATE_WRITABLE_NOT  | writable/write-protected
  585. * VM_STATE_CACHEABLE| VM_STATE_CACHEABLE_NOT | cacheable/not-cacheable
  586. * .TE
  587. *
  588. * For example, to see if a page is writable, the following code would be used:
  589. *
  590. * .CS
  591. *     vmStateGet (vmContext, pageAddr, &state);
  592. *     if ((state & VM_STATE_MASK_WRITABLE) & VM_STATE_WRITABLE)
  593. *        ...
  594. * .CE
  595. *
  596. * If <context> is specified as NULL, the current virtual memory context 
  597. * is used.
  598. *
  599. * This routine is callable from interrupt level.
  600. *
  601. * AVAILABILITY
  602. * This routine is distributed as a component of the unbundled virtual memory
  603. * support option, VxVMI.
  604. *
  605. * RETURNS: OK, or ERROR if <pageAddr> is not on a page boundary, the
  606. * validity check fails, or the architecture-dependent state get fails for
  607. * the specified virtual address.
  608. *
  609. * ERRNO: S_vmLib_NOT_PAGE_ALIGNED
  610. */
  611. STATUS vmStateGet 
  612.     (
  613.     VM_CONTEXT_ID context,  /* context - NULL == currentContext */
  614.     void *pPageAddr,  /* virtual page addr                */
  615.     UINT *pState /* where to return state            */
  616.     )
  617.     {
  618.     UINT archDepStateGotten;
  619.     int j;
  620.     if (context == NULL)
  621. context = currentContext;
  622.     if (OBJ_VERIFY (context, vmContextClassId) != OK)
  623. return (ERROR);
  624.     if (NOT_PAGE_ALIGNED (pPageAddr))
  625. {
  626. errno = S_vmLib_NOT_PAGE_ALIGNED;
  627.         return (ERROR); 
  628. }
  629.     *pState = 0;
  630.     if (MMU_STATE_GET (context->mmuTransTbl,
  631.        pPageAddr, &archDepStateGotten) == ERROR)
  632. return (ERROR);
  633.     /* translate from arch dependent state to arch independent state */
  634.     for (j = 0; j < mmuStateTransArraySize; j++)
  635. {
  636. STATE_TRANS_TUPLE *thisTuple = &mmuStateTransArray[j];
  637. UINT archDepMask = thisTuple->archDepMask;
  638. UINT archDepState = thisTuple->archDepState;
  639. UINT archIndepState = thisTuple->archIndepState;
  640. if ((archDepStateGotten & archDepMask) == archDepState)
  641.     *pState |= archIndepState;
  642. }
  643.     return (OK);
  644.     }
  645. /*******************************************************************************
  646. *
  647. * vmMap - map physical space into virtual space (VxVMI Option)
  648. *
  649. * This routine maps physical pages into a contiguous block of virtual
  650. * memory.  <virtualAddr> and <physicalAddr> must be on page boundaries, and
  651. * <len> must be evenly divisible by the page size.  After the call to
  652. * vmMap(), the state of all pages in the the newly mapped virtual memory is
  653. * valid, writable, and cacheable.
  654. *
  655. * The vmMap() routine can fail if the specified virtual address space
  656. * conflicts with the translation tables of the global virtual memory space.
  657. * The global virtual address space is architecture-dependent and is
  658. * initialized at boot time with calls to vmGlobalMap() by
  659. * vmGlobalMapInit().  If a conflict results, `errno' is set to
  660. * S_vmLib_ADDR_IN_GLOBAL_SPACE.  To avoid this conflict, use
  661. * vmGlobalInfoGet() to ascertain which portions of the virtual address space
  662. * are reserved for the global virtual address space.  If <context> is
  663. * specified as NULL, the current virtual memory context is used.
  664. *
  665. * This routine should not be called from interrupt level.
  666. *
  667. * AVAILABILITY
  668. * This routine is distributed as a component of the unbundled virtual memory
  669. * support option, VxVMI.
  670. *
  671. * RETURNS: OK, or ERROR if <virtualAddr> or <physicalAddr> are not 
  672. * on page boundaries, <len> is not a multiple of the page size, 
  673. * the validation fails, or the mapping fails.
  674. *
  675. * ERRNO:
  676. * S_vmLib_NOT_PAGE_ALIGNED,
  677. * S_vmLib_ADDR_IN_GLOBAL_SPACE
  678. */
  679. STATUS vmMap 
  680.     (
  681.     VM_CONTEXT_ID context,  /* context - NULL == currentContext   */
  682.     void *virtualAddr,  /* virtual address                    */
  683.     void *physicalAddr, /* physical address                   */
  684.     UINT len /* len of virtual and physical spaces */
  685.     )
  686.     {
  687.     int pageSize = vmPageSize;
  688.     char *thisVirtPage = (char *) virtualAddr;
  689.     char *thisPhysPage = (char *) physicalAddr;
  690.     FAST UINT numBytesProcessed = 0;
  691.     STATUS retVal = OK;
  692.     if (context == NULL)
  693. context = currentContext;
  694.     if (OBJ_VERIFY (context, vmContextClassId) != OK)
  695. return (ERROR);
  696.     if (NOT_PAGE_ALIGNED (thisVirtPage))
  697. {
  698. errno = S_vmLib_NOT_PAGE_ALIGNED;
  699.         return (ERROR); 
  700. }
  701.     if ((!mmuPhysAddrShift) && (NOT_PAGE_ALIGNED (thisPhysPage)))
  702. {
  703. errno = S_vmLib_NOT_PAGE_ALIGNED;
  704.         return (ERROR); 
  705. }
  706.     if (NOT_PAGE_ALIGNED (len))
  707. {
  708. errno = S_vmLib_NOT_PAGE_ALIGNED;
  709.         return (ERROR); 
  710. }
  711.     /* take mutual exclusion semaphore to protect translation table */
  712.     semTake (&context->sem, WAIT_FOREVER);
  713.     while (numBytesProcessed < len)
  714. {
  715. /* make sure there isn't a conflict with global virtual memory */
  716. if (ADDR_IN_GLOBAL_SPACE (thisVirtPage))
  717.     {
  718.     errno = S_vmLib_ADDR_IN_GLOBAL_SPACE;
  719.     retVal = ERROR;
  720.     break;
  721.     }
  722. if (MMU_PAGE_MAP (context->mmuTransTbl, thisVirtPage, 
  723. thisPhysPage) == ERROR)
  724.     {
  725.     retVal = ERROR;
  726.     break;
  727.     }
  728.         if (vmStateSet (context, thisVirtPage, pageSize,
  729.  VM_STATE_MASK_VALID     |
  730.  VM_STATE_MASK_WRITABLE  |
  731.  VM_STATE_MASK_CACHEABLE |
  732.  VM_STATE_MASK_EX_CACHEABLE,
  733.  VM_STATE_VALID    |
  734.  VM_STATE_WRITABLE |
  735.  VM_STATE_CACHEABLE|
  736.  VM_STATE_EX_CACHEABLE) == ERROR)
  737.     {
  738.     retVal = ERROR;
  739.     break;
  740.     }
  741. thisVirtPage += pageSize;
  742. thisPhysPage += (mmuPhysAddrShift ? 1 : pageSize);
  743. numBytesProcessed += pageSize;
  744. }
  745.     semGive (&context->sem);
  746.     return (retVal);
  747.     }
  748. /*******************************************************************************
  749. *
  750. * vmGlobalMap - map physical pages to virtual space in shared global virtual memory (VxVMI Option)
  751. *
  752. * This routine maps physical pages to virtual space that is shared by all
  753. * virtual memory contexts.  Calls to vmGlobalMap() should be made before any
  754. * virtual memory contexts are created to insure that the shared global
  755. * mappings are included in all virtual memory contexts.  Mappings created
  756. * with vmGlobalMap() after virtual memory contexts are created are not
  757. * guaranteed to appear in all virtual memory contexts.  After the call to
  758. * vmGlobalMap(), the state of all pages in the the newly mapped virtual
  759. * memory is unspecified and must be set with a call to vmStateSet(), once
  760. * the initial virtual memory context is created.
  761. *
  762. * This routine should not be called from interrupt level.
  763. *
  764. * AVAILABILITY
  765. * This routine is distributed as a component of the unbundled virtual memory
  766. * support option, VxVMI.
  767. *
  768. * RETURNS: OK, or ERROR if <virtualAddr> or <physicalAddr> are not 
  769. * on page boundaries, <len> is not a multiple of the page size, 
  770. * or the mapping fails.
  771. *
  772. * ERRNO: S_vmLib_NOT_PAGE_ALIGNED
  773. */
  774. STATUS vmGlobalMap 
  775.     (
  776.     void *virtualAddr,  /* virtual address                    */
  777.     void *physicalAddr, /* physical address                   */
  778.     UINT len /* len of virtual and physical spaces */
  779.     )
  780.     {
  781.     int  pageSize  = vmPageSize;
  782.     char * thisVirtPage  = (char *) virtualAddr;
  783.     char * thisPhysPage  = (char *) physicalAddr;
  784.     FAST UINT  numBytesProcessed  = 0;
  785.     STATUS  retVal  = OK;
  786.     if (!vmLibInfo.vmLibInstalled)
  787. return (ERROR);
  788.     if (NOT_PAGE_ALIGNED (thisVirtPage))
  789. {
  790. errno = S_vmLib_NOT_PAGE_ALIGNED;
  791.         return (ERROR); 
  792. }
  793.     if ((!mmuPhysAddrShift) && (NOT_PAGE_ALIGNED (thisPhysPage)))
  794. {
  795. errno = S_vmLib_NOT_PAGE_ALIGNED;
  796.         return (ERROR); 
  797. }
  798.     if (NOT_PAGE_ALIGNED (len))
  799. {
  800. errno = S_vmLib_NOT_PAGE_ALIGNED;
  801.         return (ERROR); 
  802. }
  803.     semTake (&globalMemMutex, WAIT_FOREVER);
  804.     while (numBytesProcessed < len)
  805. {
  806. if (MMU_GLOBAL_PAGE_MAP (thisVirtPage, thisPhysPage) == ERROR)
  807.     {
  808.     retVal = ERROR;
  809.     break;
  810.     }
  811. /* mark the block containing the page in the globalPageBlockArray as 
  812.          * being global 
  813.  */
  814.         globalPageBlockArray[(unsigned) thisVirtPage / mmuPageBlockSize] = TRUE;
  815. thisVirtPage += pageSize;
  816. thisPhysPage += (mmuPhysAddrShift ? 1 : pageSize);
  817. numBytesProcessed += pageSize;
  818. }
  819.     semGive (&globalMemMutex);
  820.     return (retVal);
  821.     }
  822. /*******************************************************************************
  823. *
  824. * vmGlobalInfoGet - get global virtual memory information (VxVMI Option)
  825. *
  826. * This routine provides a description of those parts of the virtual memory
  827. * space dedicated to global memory.  The routine returns a pointer to an
  828. * array of UINT8.  Each element of the array corresponds to a block of
  829. * virtual memory, the size of which is architecture-dependent and can be
  830. * obtained with a call to vmPageBlockSizeGet().  To determine if a
  831. * particular address is in global virtual memory, use the following code:
  832. *
  833. * .CS
  834. *     UINT8 *globalPageBlockArray = vmGlobalInfoGet ();
  835. *     int pageBlockSize = vmPageBlockSizeGet ();
  836. *    
  837. *     if (globalPageBlockArray[addr/pageBlockSize])
  838. *        ...
  839. * .CE
  840. *
  841. * The array pointed to by the returned pointer is guaranteed to be static as
  842. * long as no calls are made to vmGlobalMap() while the array is being
  843. * examined.  The information in the array can be used to determine what
  844. * portions of the virtual memory space are available for use as private
  845. * virtual memory within a virtual memory context.
  846. *
  847. * This routine is callable from interrupt level.
  848. *
  849. * AVAILABILITY
  850. * This routine is distributed as a component of the unbundled virtual memory
  851. * support option, VxVMI.
  852. *
  853. * RETURNS: A pointer to an array of UINT8.
  854. *
  855. * SEE ALSO: vmPageBlockSizeGet()
  856. */
  857. UINT8 *vmGlobalInfoGet  (void)
  858.     {
  859.     return (globalPageBlockArray);
  860.     }
  861. /*******************************************************************************
  862. *
  863. * vmPageBlockSizeGet - get the architecture-dependent page block size (VxVMI Option)
  864. *
  865. * This routine returns the size of a page block for the current
  866. * architecture.  Each MMU architecture constructs translation tables such
  867. * that a minimum number of pages are pre-defined when a new section of the
  868. * translation table is built.  This minimal group of pages is referred to as
  869. * a "page block." This routine may be used in conjunction with
  870. * vmGlobalInfoGet() to examine the layout of global virtual memory.
  871. *
  872. * This routine is callable from interrupt level.
  873. *
  874. * AVAILABILITY
  875. * This routine is distributed as a component of the unbundled virtual memory
  876. * support option, VxVMI.
  877. *
  878. * RETURNS: The page block size of the current architecture.
  879. *
  880. * SEE ALSO: vmGlobalInfoGet()
  881. */
  882. int vmPageBlockSizeGet  (void)
  883.     {
  884.     return (mmuPageBlockSize);
  885.     }
  886. /*******************************************************************************
  887. *
  888. * vmTranslate - translate a virtual address to a physical address (VxVMI Option)
  889. *
  890. * This routine retrieves mapping information for a virtual address from the
  891. * page translation tables.  If the specified virtual address has never been
  892. * mapped, the returned status can be either OK or ERROR; however, if it is
  893. * OK, then the returned physical address will be -1.  If <context> is
  894. * specified as NULL, the current context is used.
  895. *
  896. * This routine is callable from interrupt level.
  897. *
  898. * AVAILABILITY
  899. * This routine is distributed as a component of the unbundled virtual memory
  900. * support option, VxVMI.
  901. *
  902. * RETURNS: OK, or ERROR if the validation or translation fails.
  903. */
  904. STATUS vmTranslate 
  905.     (
  906.     VM_CONTEXT_ID context,  /* context - NULL == currentContext */
  907.     void *virtualAddr,  /* virtual address                  */
  908.     void **physicalAddr /* place to put result              */
  909.     )
  910.     {
  911.     STATUS retVal;
  912.     if (context == NULL)
  913. context = currentContext;
  914.     if (OBJ_VERIFY (context, vmContextClassId) != OK)
  915. return (ERROR);
  916.     retVal =  MMU_TRANSLATE (context->mmuTransTbl, virtualAddr, physicalAddr);
  917.     return (retVal);
  918.     }
  919. /*******************************************************************************
  920. *
  921. * vmPageSizeGet - return the page size (VxVMI Option)
  922. *
  923. * This routine returns the architecture-dependent page size.
  924. *
  925. * This routine is callable from interrupt level.
  926. *
  927. * AVAILABILITY
  928. * This routine is distributed as a component of the unbundled virtual memory
  929. * support option, VxVMI.
  930. *
  931. * RETURNS: The page size of the current architecture. 
  932. *
  933. */
  934. int vmPageSizeGet (void)
  935.     {
  936.     return (vmPageSize);
  937.     }
  938. /*******************************************************************************
  939. *
  940. * vmCurrentGet - get the current virtual memory context (VxVMI Option)
  941. *
  942. * This routine returns the current virtual memory context.
  943. *
  944. * This routine is callable from interrupt level.
  945. *
  946. * AVAILABILITY
  947. * This routine is distributed as a component of the unbundled virtual memory
  948. * support option, VxVMI.
  949. *
  950. * RETURNS: The current virtual memory context, or
  951. * NULL if no virtual memory context is installed.
  952. */
  953. VM_CONTEXT_ID vmCurrentGet  (void)
  954.     {
  955.     return (currentContext);
  956.     }
  957. /*******************************************************************************
  958. *
  959. * vmCurrentSet - set the current virtual memory context (VxVMI Option)
  960. *
  961. * This routine installs a specified virtual memory context.
  962. *
  963. * This routine is callable from interrupt level.
  964. *
  965. * AVAILABILITY
  966. * This routine is distributed as a component of the unbundled virtual memory
  967. * support option, VxVMI.
  968. *
  969. * RETURNS: OK, or ERROR if the validation or context switch fails.
  970. */
  971. STATUS vmCurrentSet 
  972.     (
  973.     VM_CONTEXT_ID context /* context to install */
  974.     )
  975.     {
  976.     if (OBJ_VERIFY (context, vmContextClassId) != OK)
  977. return (ERROR);
  978.     /* XXX do we need to flush the cpu's cache on a context switch?
  979.      * yes, if the cache operates on virtual addresses (68k does)
  980.      */
  981.     cacheClear (INSTRUCTION_CACHE, 0, ENTIRE_CACHE);
  982.     cacheClear (DATA_CACHE, 0, ENTIRE_CACHE);
  983.     currentContext = context;
  984.     MMU_CURRENT_SET (context->mmuTransTbl);
  985.     return (OK);
  986.     }
  987. /*******************************************************************************
  988. *
  989. * vmEnable - enable or disable virtual memory (VxVMI Option)
  990. *
  991. * This routine turns virtual memory on and off.  Memory management should not
  992. * be turned off once it is turned on except in the case of system shutdown.
  993. *
  994. * This routine is callable from interrupt level.
  995. *
  996. * AVAILABILITY
  997. * This routine is distributed as a component of the unbundled virtual memory
  998. * support option, VxVMI.
  999. *
  1000. * RETURNS: OK, or ERROR if the validation or architecture-dependent code
  1001. * fails.
  1002. */
  1003. STATUS vmEnable 
  1004.     (
  1005.     BOOL enable /* TRUE == enable MMU, FALSE == disable MMU */
  1006.     )
  1007.     {
  1008.     return (MMU_ENABLE (enable));
  1009.     }
  1010. /*******************************************************************************
  1011. *
  1012. * vmTextProtect - write-protect a text segment (VxVMI Option)
  1013. *
  1014. * This routine write-protects the VxWorks text segment and sets a flag so
  1015. * that all text segments loaded by the incremental loader will be
  1016. * write-protected.  The routine should be called after both vmLibInit() and
  1017. * vmGlobalMapInit() have been called.
  1018. *
  1019. * AVAILABILITY
  1020. * This routine is distributed as a component of the unbundled virtual memory
  1021. * support option, VxVMI.
  1022. *
  1023. * RETURNS: OK, or ERROR if the text segment cannot be write-protected.
  1024. *
  1025. * ERRNO: S_vmLib_TEXT_PROTECTION_UNAVAILABLE
  1026. */ 
  1027. STATUS vmTextProtect (void)
  1028.     {
  1029.     UINT begin;
  1030.     UINT end;
  1031. #if (CPU==SH7750 || CPU==SH7729 || CPU==SH7700)
  1032.     UINT memBase = (UINT) etext & 0xe0000000; /* identify logical space */
  1033. #endif
  1034.     if (!vmLibInfo.vmLibInstalled)
  1035. {
  1036. errno = S_vmLib_TEXT_PROTECTION_UNAVAILABLE;
  1037. return (ERROR);
  1038. }
  1039. #if (CPU==SH7750 || CPU==SH7729 || CPU==SH7700)
  1040.     begin = (((UINT) sysInit & 0x1fffffff) | memBase) / vmPageSize * vmPageSize;
  1041. #else
  1042.     begin = (UINT) sysInit / vmPageSize * vmPageSize;
  1043. #endif
  1044.     end   = (UINT) etext   / vmPageSize * vmPageSize + vmPageSize;
  1045.     vmLibInfo.protectTextSegs = TRUE;
  1046.     return (vmStateSet (0, (void *) begin, end - begin, VM_STATE_MASK_WRITABLE,
  1047. VM_STATE_WRITABLE_NOT));
  1048.     }
  1049. /*******************************************************************************
  1050. *
  1051. * vmTextPageProtect - protect or unprotect a page of the text segment
  1052. *
  1053. * RETURNS: 
  1054. */
  1055. LOCAL STATUS vmTextPageProtect
  1056.     (
  1057.     void *textPageAddr,  /* page to change */
  1058.     BOOL protect  /* TRUE = write protect, FALSE = write enable */
  1059.     )
  1060.     {
  1061.     UINT newState = (protect ? VM_STATE_WRITABLE_NOT : VM_STATE_WRITABLE);
  1062.     int retVal = ERROR;
  1063.     
  1064.     if (vmLibInfo.protectTextSegs)
  1065. retVal = vmStateSet (NULL, textPageAddr, vmPageSize, 
  1066.      VM_STATE_MASK_WRITABLE, newState);
  1067.     return (retVal);
  1068.     }
  1069. #endif /* (CPU_FAMILY != MIPS) && (CPU_FAMILY != PPC) */