1    /*
     2     * Copyright (c) 2013-2019, 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         *  ======== numXMCRegions ========
   126         */
   127        const UInt numXMCRegions = 16;
   128    
   129        /*!
   130         *  ======== RegionSize ========
   131         */
   132        enum RegionSize {
   133            RegionSize_4K   = 0x0B,
   134            RegionSize_8K   = 0x0C,
   135            RegionSize_16K  = 0x0D,
   136            RegionSize_32K  = 0x0E,
   137            RegionSize_64K  = 0x0F,
   138            RegionSize_128K = 0x10,
   139            RegionSize_256K = 0x11,
   140            RegionSize_512K = 0x12,
   141            RegionSize_1M   = 0x13,
   142            RegionSize_2M   = 0x14,
   143            RegionSize_4M   = 0x15,
   144            RegionSize_8M   = 0x16,
   145            RegionSize_16M  = 0x17,
   146            RegionSize_32M  = 0x18,
   147            RegionSize_64M  = 0x19,
   148            RegionSize_128M = 0x1A,
   149            RegionSize_256M = 0x1B,
   150            RegionSize_512M = 0x1C,
   151            RegionSize_1G   = 0x1D,
   152            RegionSize_2G   = 0x1E,
   153            RegionSize_4G   = 0x1F
   154        };
   155    
   156        /*!
   157         *  ======== setXMCRegion ========
   158         *  Set XMC region mapping and permission attributes
   159         *
   160         *  The C66 CorePac XMC (eXtended Memory Controller) controls access to
   161         *  L2 SRAM.  It contains 16 MPAX registers that define memory translations
   162         *  and address extensions along with their associated permission
   163         *  attributes.  Regions can overlap one another, with higher numbered
   164         *  regions taking priority over lower ones.  Regions 0 & 1 are
   165         *  automatically populated by XMC with power up configuratoin values
   166         *  which map the entire 4GB logical address space to the corresponding
   167         *  physical address space.  These region mappings allow safe fallback
   168         *  handling for addresses that are not otherwise mapped in higher MPAX
   169         *  registers.
   170         *
   171         *  Addresses < 0x0C000000 do not reach the XMC, so baseAddr should be
   172         *  greater than or equal to 0x0C000000.
   173         *
   174         *  @param(regionId)      XMC region (segment) number
   175         *  @param(baseAddr)      XMC region logical address
   176         *  @param(size)          XMC region size
   177         *  @param(rAddr35_12)    XMC region translated/extended address bits 35:12
   178         *  @param(paMask)        XMC region permission bits
   179         *
   180         *  @b(returns)  if baseAddr < 0x0C000000 or regionId >= numXMCRegions
   181         *               then FALSE, othersize TRUE and the region is mapped with
   182         *               permission attributes paMask.
   183         */
   184        Bool setXMCRegion(Int8 id, Ptr baseAddr, RegionSize size, Ptr rAddr35_12,
   185                         UInt32 paMask);
   186    
   187        /*!
   188         *  ======== getPA ========
   189         *  Gets the PA (Permission Attribute) corresponding to addr.
   190         *
   191         *  @param(addr)    address of memory location for which the PA applies
   192         *  @param(paMask)  ptr to location where PA mask for addr is stored
   193         *
   194         *  @b(returns)     if address doesn't belong to any configured MPC then
   195         *                  FALSE, otherwise TRUE and *paMask contains addr's
   196         *                  MPPA setting
   197         */
   198        Bool getPA(Ptr addr, UInt32 *paMask);
   199    
   200        /*!
   201         *  ======== setPA ========
   202         *  Sets the PA (Permission Attribute) corresponding to addr/size.
   203         *
   204         *  The PA is applied to all addresses that are spanned by the
   205         *  memory block.
   206         *
   207         *  @param(addr)    begin address of memory block for which the PA applies
   208         *  @param(size)    size of memory block
   209         *  @param(paMask)  PA mask to assign for the memory block
   210         *
   211         *  @b(returns)     if address doesn't belong to any configured MPC then
   212         *                  FALSE, otherwise TRUE and PA was written to addr's
   213         *                  MPPA register
   214         */
   215        Bool setPA(Ptr addr, SizeT size, UInt32 paMask);
   216    
   217        /*!@_nodoc
   218         *  ======== getPageSize ========
   219         *  Gets the page size corresponding to addr.
   220         *
   221         *  @param(addr)    address of memory location for which the PA applies
   222         *  @param(pageSize) pointer to location where the page size is stored
   223         *
   224         *  @b(returns)     FALSE - address doesn't belong to any configured MPC
   225         *                  TRUE - *pageSize contains addr's MPC page size
   226         */
   227        Bool getPageSize(Ptr addr, UInt *pageSize);
   228        
   229        /*!@_nodoc
   230         *  ======== getPrivMode ========
   231         *  Retrieves the current privilege mode
   232         *
   233         *  @b(returns)     current privilege mode
   234         */
   235        UInt getPrivMode();
   236    
   237        /*!@_nodoc
   238         *  ======== setPrivMode ========
   239         *  Sets the privilege mode
   240         *
   241         *  @param(mode)    the privilege mode to set
   242         */
   243        Void setPrivMode(UInt mode);
   244    
   245        
   246    internal:
   247    
   248        /*!
   249         *  Struct defining the bit range of an address
   250         */
   251        struct BitRange {
   252            Char msb;
   253            Char lsb;
   254        };
   255    
   256        /*!
   257         *  Each MPC needs to implement MPLCK.
   258         *  DMC/PMC/UMA all conform to the struct below.
   259         */
   260        struct Lock {
   261            volatile UInt32 mpLk0;      /* lock bits 31-0 */
   262            volatile UInt32 mpLk1;      /* lock bits 63-32 */
   263            volatile UInt32 mpLk2;      /* lock bits 95-64 */
   264            volatile UInt32 mpLk3;      /* lock bits 127-96 */
   265            volatile UInt32 mpLkCmd;    /* lock command register */
   266            volatile UInt32 mpLkStat;   /* lock status register */
   267        };
   268    
   269        /*!
   270         *  Struct defining the fault registers
   271         */
   272        struct Fault {
   273            volatile UInt32 mpFar;      /* MPC Fault Address Register */
   274            volatile UInt32 mpFsr;      /* MPC Fault Status Register */
   275            volatile UInt32 mpFcr;      /* MPC Fault Clear Register */
   276        };
   277    
   278        /*!
   279         *  Key represents the 128-bit key used for locking
   280         *  and unlocking a controller's permission attribute entries.
   281         *  It is used for writing to the MPLK0-MPLK3 registers.
   282         */
   283        struct Key {
   284            UInt32  key0;       /* bits 0-31 of 128-bit key */
   285            UInt32  key1;       /* bits 32-63 of 128-bit key */
   286            UInt32  key2;       /* bits 64-95 of 128-bit key */
   287            UInt32  key3;       /* bits 96-127 of 128-bit key */
   288        };
   289    
   290        /*!
   291         *  Struct defining a controller
   292         */
   293        struct Controller {
   294            Fault   *mpFault;       /* addr of MP Fault registers */
   295            Lock    *mpLck;         /* addr of MP Lock registers */
   296            UInt32  *mppaTab;       /* addr of base of MP PA table */
   297            UInt32  *mpCfg;         /* addr of MP Configuration register */
   298            UInt32  nPages;         /* # pages in the MPC */
   299            UInt32  evtNum;         /* Event number for controller */
   300        };
   301    
   302        /*!
   303         *  The following values relate to indexing into the module state
   304         *  controller array.  Subtract 1 from the value before using it as an
   305         *  index into the 0-based array (NONE isn't used to index the array).
   306         */
   307        const UInt NONE  = 0;
   308        const UInt UMAP0 = 1;
   309        const UInt UMAP1 = 2;
   310        const UInt DMC   = 3;
   311        const UInt PMC   = 4;
   312        const UInt UMC   = UMAP0;
   313        
   314        /*! lock/unlock values */
   315        const UInt LCKUNLOCK  = 0x00000001;
   316        const UInt LCKLOCK    = 0x00000002;
   317        const UInt LCKKEYR    = 0x00000004;
   318        const UInt LKSTATLK   = 0x00000001;
   319    
   320        /*! The key values used for locking/unlocking PA table */
   321        config Key key = {
   322            key0: 0x90abcdef,
   323            key1: 0x12345678,
   324            key2: 0x87654321,
   325            key3: 0xfedcba09
   326        };
   327    
   328        /*!
   329         *  Region Extract Masks table indexed by [controller(0-3)][region(0-1)].
   330         *  The constants used are fixed based on the GEM architecture spec.
   331         *  They are based on the minimum theoretical page size (lower constant)
   332         *  and the number of pages (higher constant minus lower constant).
   333         *  However, in reality, the actual minimum page size is floored at
   334         *  some minimum (i.e., the "size" parameter can't, per the
   335         *  HW design spec, be lower than some minimum (2 for DMC/PMC, 6 for UMC).
   336         */
   337        config BitRange regExtMasks[4][2];
   338    
   339        /*!
   340         *  This array is used to map the MegaByte field of an address
   341         *  (0x00N00000) to the controller that controls that address.
   342         *  An MPC's address range falls within and is wholy contained
   343         *  in the MegaByte hex digit.
   344         */
   345        config Char megaByte2MPC[16];
   346    
   347        /*!
   348         *  Array of addresses that mark the begin of region 0 for each MPC.
   349         *  Each MPC contains two regions (0 & 1), however, the first two
   350         *  entries correspond to the two "regions" of UMC (UMC_P0 & UMC_P1),
   351         *  and as such the entries for them are forced to the max address
   352         *  value such that any compare that uses them will be < them,
   353         *  thus indicating region 0.
   354         */
   355        config UInt regionCompare[4];
   356    
   357        /*!
   358         *  Array of addresses that mark the end of region 0 for each MPC.
   359         */
   360        config UInt regionEnd[4];
   361    
   362        /*! L1 program memory controller */
   363        config Controller pmcCtrl;
   364        
   365        /*! L1 data memory controller */
   366        config Controller dmcCtrl;
   367    
   368        /*! L2 unified memory controller */
   369        config Controller umcCtrl;
   370    
   371        /*!
   372         *  ======== decodeRegion ========
   373         *  Determine the beginning and end page numbers for region.
   374         *
   375         *  Validate begAddr/endAddr range to be within internal address space.
   376         *  Return region (UMAP0/UMAP1/DMC/PMC), beginning and ending page
   377         *  numbers if valid.  Returns -1 if complete address range is not valid.
   378         */
   379        Int decodeRegion(UInt32 begAddr, UInt32 endAddr,
   380                         UInt32 *begPage, UInt32 *endPage);
   381    
   382        /*!
   383         *  ======== getAddrPageSize ========
   384         *  Returns the page size corresponding to addr.
   385         */
   386        Int getAddrPageSize(Ptr addr);
   387    
   388        /*!
   389         *  ======== lock ========
   390         *  Locks the permission attribute.
   391         *
   392         *  Locks the permission attribute table entries for the
   393         *  specified controller, using the specified key.
   394         */
   395        Void lock(Controller *ctrl, Key *key);
   396        
   397        /*!
   398         *  ======== makeLocal ========
   399         *  Convert address into a local address
   400         *
   401         *  Validate addr to be a GEM internal address & convert addr into
   402         *  its local address if global.  Returns TRUE if addr is a valid GEM
   403         *  internal address, and fills space with local/global code (1/0).
   404         *  Returns FALSE if addr is not a valid GEM internal address.  space
   405         *  is valid only when TRUE is returned.
   406         */
   407        Bool makeLocal(UInt *addr, UInt *space);
   408        
   409        /*!
   410         *  ======== readPA ========
   411         *  Reads the permission attribute
   412         *
   413         *  Returns the permission attribute for the specified
   414         *  page within the specified controller.
   415         */
   416        UInt32 readPA(Controller *ctrl, UInt page);
   417        
   418        /*!
   419         *  ======== unlock ========
   420         *  Unlocks the permission attribute.
   421         *
   422         *  Unlocks the permission attribute table entries for the
   423         *  specified controller, using the specified key.
   424         */
   425        Void unlock(Controller *ctrl, Key *key);
   426    
   427        /*!
   428         *  ======== writePA ========
   429         *  Writes the permission attribute
   430         *
   431         *  Writes the permission attribute perm for the specified
   432         *  page within the specified controller.  The permission attribute
   433         *  entries need to be unlocked first and then locked afterwards.
   434         */
   435        Void writePA(Controller *ctrl, UInt page, UInt32 perm);
   436    
   437        /* Module state */
   438        struct Module_State {
   439            Controller *controllers[];
   440        }
   441    }