1    /*
     2     * Copyright (c) 2013, Texas Instruments Incorporated
     3     * All rights reserved.
     4     *
     5     * Redistribution and use in source and binary forms, with or without
     6     * modification, are permitted provided that the following conditions
     7     * are met:
     8     *
     9     * *  Redistributions of source code must retain the above copyright
    10     *    notice, this list of conditions and the following disclaimer.
    11     *
    12     * *  Redistributions in binary form must reproduce the above copyright
    13     *    notice, this list of conditions and the following disclaimer in the
    14     *    documentation and/or other materials provided with the distribution.
    15     *
    16     * *  Neither the name of Texas Instruments Incorporated nor the names of
    17     *    its contributors may be used to endorse or promote products derived
    18     *    from this software without specific prior written permission.
    19     *
    20     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    21     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    23     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
    24     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    25     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    26     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
    27     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
    28     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
    29     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    30     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    31     */
    32    /*
    33     *  ======== MemoryProtect.xdc ========
    34     *
    35     *
    36     */
    37    
    38    package ti.sysbios.family.c64p;
    39    
    40    /*!
    41     *  ======== MemoryProtect ========
    42     *  MemoryProtect Module
    43     *
    44     *  This module provide an API to {@link #getPA() get} and to
    45     *  {@link #setPA() set} the permission attributes of a memory range.
    46     *  A memory range can be set to user {@link #MPPA_UX executable}, 
    47     *  user {@link #MPPA_UW writable}, user {@link #MPPA_UR readable},
    48     *  supervisor {@link #MPPA_SX executable}, supervisor 
    49     *  {@link #MPPA_SW writable}, or supervisor {@link #MPPA_SR readable}.
    50     *  Setting a memory range to only user readable, writable or executable
    51     *  should be done with caution because BIOS executes in supervisor mode.
    52     *  Whenever setting the permission attributes of a memory range,
    53     *  the {@link #MPPA_LOCAL local} CPU access field must be set, if the
    54     *  local CPU accesses the memory range.  If the local field is not set,
    55     *  an exception is generated if the CPU tries to access the memory range.
    56     *
    57     *  This module is to be used in correlation with the
    58     *  {@link ti.sysbios.family.c64p.Exception Exception} module.
    59     *  When this module is in use, external exceptions are enabled by default.
    60     *  Any memory protection fault which arises generates an exception.
    61     *  This exception is processed and decoded by the Exception module.
    62     *
    63     *  An example of setting Local L2 RAM to be supervisor read-only and
    64     *  CPU accessible:
    65     *
    66     *  @p(code)
    67     *    UInt32 paMask;
    68     *    paMask = MemoryProtect_MPPA_LOCAL |
    69     *             MemoryProtect_MPPA_SR;
    70     *              
    71     *    MemoryProtect_setPA((Ptr)0x11800000, 0x40000, paMask);
    72     *  @p
    73     *
    74     *  @p(html)
    75     *  <h3> Calling Context </h3>
    76     *  <table border="1" cellpadding="3">
    77     *    <colgroup span="1"></colgroup> <colgroup span="5" align="center"></colgroup>
    78     *
    79     *    <tr><th> Function               </th><th>  Hwi   </th><th>  Swi   </th><th>  Task  </th><th>  Main  </th><th>  Startup  </th></tr>
    80     *    <!--                                                                                                                 -->
    81     *    <tr><td> {@link #getPA}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    82     *    <tr><td> {@link #setPA}         </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td><td>   Y    </td></tr>
    83     *    <tr><td colspan="6"> Definitions: <br />
    84     *       <ul>
    85     *         <li> <b>Hwi</b>: API is callable from a Hwi thread. </li>
    86     *         <li> <b>Swi</b>: API is callable from a Swi thread. </li>
    87     *         <li> <b>Task</b>: API is callable from a Task thread. </li>
    88     *         <li> <b>Main</b>: API is callable during any of these phases: </li>
    89     *           <ul>
    90     *             <li> In your module startup after this module is started (e.g. Mod_Module_startupDone() returns TRUE). </li>
    91     *             <li> During xdc.runtime.Startup.lastFxns. </li>
    92     *             <li> During main().</li>
    93     *             <li> During BIOS.startupFxns.</li>
    94     *           </ul>
    95     *         <li> <b>Startup</b>: API is callable during any of these phases:</li>
    96     *           <ul>
    97     *             <li> During xdc.runtime.Startup.firstFxns.</li>
    98     *             <li> In your module startup before this module is started (e.g. Mod_Module_startupDone() returns FALSE).</li>
    99     *           </ul>
   100     *       </ul>
   101     *    </td></tr>
   102     *
   103     *  </table>
   104     *  @p
   105     */
   106    
   107    @ModuleStartup
   108    @DirectCall
   109    module MemoryProtect
   110    {
   111        // -------- Module Types --------
   112    
   113        /* 
   114         *  MPPA Permission Attribute Register bitmasks.
   115         */
   116        const UInt32 MPPA_UX    = 0x00000001;   /*! User mode may execute       */
   117        const UInt32 MPPA_UW    = 0x00000002;   /*! User mode may write         */
   118        const UInt32 MPPA_UR    = 0x00000004;   /*! User mode may read          */
   119        const UInt32 MPPA_SX    = 0x00000008;   /*! Supervisor mode may execute */
   120        const UInt32 MPPA_SW    = 0x00000010;   /*! Supervisor mode may write   */
   121        const UInt32 MPPA_SR    = 0x00000020;   /*! Supervisor mode read        */
   122        const UInt32 MPPA_LOCAL = 0x00000100;   /*! Local CPU may access        */
   123    
   124        /*!
   125         *  ======== getPA ========
   126         *  Gets the PA (Permission Attribute) corresponding to addr.
   127         *
   128         *  @param(addr)    address of memory location for which the PA applies
   129         *  @param(paMask)  ptr to location where PA mask for addr is stored
   130         *
   131         *  @b(returns)     if address doesn't belong to any configured MPC then
   132         *                  FALSE, otherwise TRUE and *paMask contains addr's
   133         *                  MPPA setting
   134         */
   135        Bool getPA(Ptr addr, UInt32 *paMask);
   136    
   137        /*!
   138         *  ======== setPA ========
   139         *  Sets the PA (Permission Attribute) corresponding to addr/size.
   140         *
   141         *  The PA is applied to all addresses that are spanned by the
   142         *  memory block.
   143         *
   144         *  @param(addr)    begin address of memory block for which the PA applies
   145         *  @param(size)    size of memory block
   146         *  @param(paMask)  PA mask to assign for the memory block
   147         *
   148         *  @b(returns)     if address doesn't belong to any configured MPC then
   149         *                  FALSE, otherwise TRUE and PA was written to addr's
   150         *                  MPPA register
   151         */
   152        Bool setPA(Ptr addr, SizeT size, UInt32 paMask);
   153    
   154        /*!@_nodoc
   155         *  ======== getPageSize ========
   156         *  Gets the page size corresponding to addr.
   157         *
   158         *  @param(addr)    address of memory location for which the PA applies
   159         *  @param(pageSize) pointer to location where the page size is stored
   160         *
   161         *  @b(returns)     FALSE - address doesn't belong to any configured MPC
   162         *                  TRUE - *pageSize contains addr's MPC page size
   163         */
   164        Bool getPageSize(Ptr addr, UInt *pageSize);
   165        
   166        /*!@_nodoc
   167         *  ======== getPrivMode ========
   168         *  Retrieves the current privilege mode
   169         *
   170         *  @b(returns)     current privilege mode
   171         */
   172        UInt getPrivMode();
   173    
   174        /*!@_nodoc
   175         *  ======== setPrivMode ========
   176         *  Sets the privilege mode
   177         *
   178         *  @param(mode)    the privilege mode to set
   179         */
   180        Void setPrivMode(UInt mode);
   181    
   182        
   183    internal:
   184    
   185        /*!
   186         *  Struct defining the bit range of an address
   187         */
   188        struct BitRange {
   189            Char msb;
   190            Char lsb;
   191        };
   192    
   193        /*!
   194         *  Each MPC needs to implement MPLCK.
   195         *  DMC/PMC/UMA all conform to the struct below.
   196         */
   197        struct Lock {
   198            volatile UInt32 mpLk0;      /* lock bits 31-0 */
   199            volatile UInt32 mpLk1;      /* lock bits 63-32 */
   200            volatile UInt32 mpLk2;      /* lock bits 95-64 */
   201            volatile UInt32 mpLk3;      /* lock bits 127-96 */
   202            volatile UInt32 mpLkCmd;    /* lock command register */
   203            volatile UInt32 mpLkStat;   /* lock status register */
   204        };
   205    
   206        /*!
   207         *  Struct defining the fault registers
   208         */
   209        struct Fault {
   210            volatile UInt32 mpFar;      /* MPC Fault Address Register */
   211            volatile UInt32 mpFsr;      /* MPC Fault Status Register */
   212            volatile UInt32 mpFcr;      /* MPC Fault Clear Register */
   213        };
   214    
   215        /*!
   216         *  Key represents the 128-bit key used for locking
   217         *  and unlocking a controller's permission attribute entries.
   218         *  It is used for writing to the MPLK0-MPLK3 registers.
   219         */
   220        struct Key {
   221            UInt32  key0;       /* bits 0-31 of 128-bit key */
   222            UInt32  key1;       /* bits 32-63 of 128-bit key */
   223            UInt32  key2;       /* bits 64-95 of 128-bit key */
   224            UInt32  key3;       /* bits 96-127 of 128-bit key */
   225        };
   226    
   227        /*!
   228         *  Struct defining a controller
   229         */
   230        struct Controller {
   231            Fault   *mpFault;       /* addr of MP Fault registers */
   232            Lock    *mpLck;         /* addr of MP Lock registers */
   233            UInt32  *mppaTab;       /* addr of base of MP PA table */
   234            UInt32  *mpCfg;         /* addr of MP Configuration register */
   235            UInt32  nPages;         /* # pages in the MPC */
   236            UInt32  evtNum;         /* Event number for controller */
   237        };
   238    
   239        /*!
   240         *  The following values relate to indexing into the module state
   241         *  controller array.  Subtract 1 from the value before using it as an
   242         *  index into the 0-based array (NONE isn't used to index the array).
   243         */
   244        const UInt NONE  = 0;
   245        const UInt UMAP0 = 1;
   246        const UInt UMAP1 = 2;
   247        const UInt DMC   = 3;
   248        const UInt PMC   = 4;
   249        const UInt UMC   = UMAP0;
   250        
   251        /*! lock/unlock values */
   252        const UInt LCKUNLOCK  = 0x00000001;
   253        const UInt LCKLOCK    = 0x00000002;
   254        const UInt LCKKEYR    = 0x00000004;
   255        const UInt LKSTATLK   = 0x00000001;
   256    
   257        /*! The key values used for locking/unlocking PA table */
   258        config Key key = {
   259            key0: 0x90abcdef,
   260            key1: 0x12345678,
   261            key2: 0x87654321,
   262            key3: 0xfedcba09
   263        };
   264    
   265        /*!
   266         *  Region Extract Masks table indexed by [controller(0-3)][region(0-1)].
   267         *  The constants used are fixed based on the GEM architecture spec.
   268         *  They are based on the minimum theoretical page size (lower constant)
   269         *  and the number of pages (higher constant minus lower constant).
   270         *  However, in reality, the actual minimum page size is floored at
   271         *  some minimum (i.e., the "size" parameter can't, per the
   272         *  HW design spec, be lower than some minimum (2 for DMC/PMC, 6 for UMC).
   273         */
   274        config BitRange regExtMasks[4][2];
   275    
   276        /*!
   277         *  This array is used to map the MegaByte field of an address
   278         *  (0x00N00000) to the controller that controls that address.
   279         *  An MPC's address range falls within and is wholy contained
   280         *  in the MegaByte hex digit.
   281         */
   282        config Char megaByte2MPC[16];
   283    
   284        /*!
   285         *  Array of addresses that mark the begin of region 0 for each MPC.
   286         *  Each MPC contains two regions (0 & 1), however, the first two
   287         *  entries correspond to the two "regions" of UMC (UMC_P0 & UMC_P1),
   288         *  and as such the entries for them are forced to the max address
   289         *  value such that any compare that uses them will be < them,
   290         *  thus indicating region 0.
   291         */
   292        config UInt regionCompare[4];
   293    
   294        /*!
   295         *  Array of addresses that mark the end of region 0 for each MPC.
   296         */
   297        config UInt regionEnd[4];
   298    
   299        /*! L1 program memory controller */
   300        config Controller pmcCtrl;
   301        
   302        /*! L1 data memory controller */
   303        config Controller dmcCtrl;
   304    
   305        /*! L2 unified memory controller */
   306        config Controller umcCtrl;
   307    
   308        /*!
   309         *  ======== decodeRegion ========
   310         *  Determine the beginning and end page numbers for region.
   311         *
   312         *  Validate begAddr/endAddr range to be within internal address space.
   313         *  Return region (UMAP0/UMAP1/DMC/PMC), beginning and ending page
   314         *  numbers if valid.  Returns -1 if complete address range is not valid.
   315         */
   316        Int decodeRegion(UInt32 begAddr, UInt32 endAddr,
   317                         UInt32 *begPage, UInt32 *endPage);
   318    
   319        /*!
   320         *  ======== getAddrPageSize ========
   321         *  Returns the page size corresponding to addr.
   322         */
   323        Int getAddrPageSize(Ptr addr);
   324    
   325        /*!
   326         *  ======== lock ========
   327         *  Locks the permission attribute.
   328         *
   329         *  Locks the permission attribute table entries for the
   330         *  specified controller, using the specified key.
   331         */
   332        Void lock(Controller *ctrl, Key *key);
   333        
   334        /*!
   335         *  ======== makeLocal ========
   336         *  Convert address into a local address
   337         *
   338         *  Validate addr to be a GEM internal address & convert addr into
   339         *  its local address if global.  Returns TRUE if addr is a valid GEM
   340         *  internal address, and fills space with local/global code (1/0).
   341         *  Returns FALSE if addr is not a valid GEM internal address.  space
   342         *  is valid only when TRUE is returned.
   343         */
   344        Bool makeLocal(UInt *addr, UInt *space);
   345        
   346        /*!
   347         *  ======== readPA ========
   348         *  Reads the permission attribute
   349         *
   350         *  Returns the permission attribute for the specified
   351         *  page within the specified controller.
   352         */
   353        UInt32 readPA(Controller *ctrl, UInt page);
   354        
   355        /*!
   356         *  ======== unlock ========
   357         *  Unlocks the permission attribute.
   358         *
   359         *  Unlocks the permission attribute table entries for the
   360         *  specified controller, using the specified key.
   361         */
   362        Void unlock(Controller *ctrl, Key *key);
   363    
   364        /*!
   365         *  ======== writePA ========
   366         *  Writes the permission attribute
   367         *
   368         *  Writes the permission attribute perm for the specified
   369         *  page within the specified controller.  The permission attribute
   370         *  entries need to be unlocked first and then locked afterwards.
   371         */
   372        Void writePA(Controller *ctrl, UInt page, UInt32 perm);
   373    
   374        /* Module state */
   375        struct Module_State {
   376            Controller *controllers[];
   377        }
   378    }