1    /*
     2     * Copyright (c) 2015, 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     *  ======== Mmu.xdc ========
    34     */
    35    
    36    package ti.sysbios.family.arm.a15;
    37    
    38    import xdc.rov.ViewInfo;
    39    
    40    /*!
    41     *  ======== Mmu ========
    42     *  Memory Management Unit Manager.
    43     *
    44     *  This module allows the ARM processor to map a 32-bit virtual address
    45     *  to a 40-bit physical address (supports Large physical address extensions)
    46     *  and enable/disable the MMU. It does this through translation tables
    47     *  in memory. The MMU hardware supports upto 3-levels of translation tables.
    48     *  This module only supports the first 2 levels of translation tables.
    49     *  The level1 translation table is a 32B descriptor table comprising of
    50     *  four 64bit entries. There can be upto 4 level2 translation tables,
    51     *  each 4KB in size and comprising of 512 64bit entries.
    52     *
    53     *  Each entry in the level1 table either gives the base address and
    54     *  defines the attributes of a memory area of size 1GB or gives the
    55     *  address of the next level of translation table and some attributes
    56     *  for that translation.
    57     *
    58     *  Each entry in the level2 table either gives the base address and
    59     *  defines the attributes of a memory area of size 2MB or gives the
    60     *  address of the next level of translation table and some attributes
    61     *  for that translation.
    62     *
    63     *  By default, the MMU level1 and level2 translation tables are initialized
    64     *  with cache-enabled entries for every memory-segment defined in the
    65     *  platform (see {@link #cachePlatformMemory}). Cache-disabled entries are
    66     *  also added for the peripheral addresses used by SYS/BIOS
    67     *  (i.e. Timers, Interrupt controller).
    68     *
    69     *  The level1 translation table is placed in an output section called
    70     *  "ti.sysbios.family.arm.a15.mmuFirstLevelTableSection". Each of the
    71     *  level2 translation tables are placed in output sections called
    72     *  "ti.sysbios.family.arm.a15.mmuSecondLevelTableSection0",
    73     *  "ti.sysbios.family.arm.a15.mmuSecondLevelTableSection1",
    74     *  "ti.sysbios.family.arm.a15.mmuSecondLevelTableSection2", and
    75     *  "ti.sysbios.family.arm.a15.mmuSecondLevelTableSection3". These
    76     *  sections are placed into the platform's default dataMemory and
    77     *  in order to minimize object file size,
    78     *  specified to not be initialized via the "NOLOAD" type on GNU compilers
    79     *  and "NOINIT" on TI compilers.
    80     *
    81     *  This module does not manage the third level descriptor tables.
    82     *
    83     *  The following is an example of how to place the MMU table
    84     *  and how to enable L1/L2 data caching for the address range
    85     *  0x80000000-0x90000000 in the *.cfg file:
    86     *
    87     *  @p(code)
    88     *
    89     *    var Mmu = xdc.useModule('ti.sysbios.family.arm.a15.Mmu');
    90     *
    91     *    // descriptor attribute structure
    92     *    var attrs = new Mmu.DescriptorAttrs();
    93     *
    94     *    // Note: If running in SMP mode, all page table entries for memory
    95     *    //       shared between the SMP cores should mark the memory as
    96     *    //       inner-shareable. This is to ensure that the cached copy of
    97     *    //       the memory region is kept coherent accross cores.
    98     *
    99     *    Mmu.initDescAttrsMeta(attrs);
   100     *    attrs.type = Mmu.DescriptorType_BLOCK;    // BLOCK descriptor
   101     *    attrs.shareable = 3;                      // inner-sharerable
   102     *    attrs.attrIndx = 2;                       // MAIR0 Byte2 describes
   103     *                                              // memory attributes for
   104     *                                              // this level2 entry
   105     *
   106     *    // write memory region attribute in mairRegAttr[2] i.e. MAIR0 Reg Byte2
   107     *    Mmu.setMAIRMeta(2, 0xFF);              // Mark mem regions as cacheable
   108     *
   109     *    // Set the descriptor for each entry in the address range
   110     *    for (var i=0x80000000; i < 0x90000000; i = i + 0x00200000) {
   111     *        // Each 'BLOCK' descriptor entry spans a 2MB address range
   112     *        Mmu.setSecondLevelDescMeta(i, i, attrs);
   113     *    }
   114     *
   115     *    var memmap = Program.cpu.memoryMap;
   116     *    var DDR = null;
   117     *
   118     *    // Find DDR in memory map
   119     *    for (var i=0; i < memmap.length; i++) {
   120     *        if (memmap[i].name == "DDR") {
   121     *            DDR = memmap[i];
   122     *        }
   123     *    }
   124     *
   125     *    // Place the MMU table in the DDR memory segment if it exists
   126     *    if (DDR != null) {
   127     *        var sectionName =
   128     *                  "ti.sysbios.family.arm.a15.mmuSecondLevelTableSection2";
   129     *        Program.sectMap[sectionName] = new Program.SectionSpec();
   130     *        Program.sectMap[sectionName].type = "NOLOAD";
   131     *        Program.sectMap[sectionName].loadSegment = "DDR";
   132     *    }
   133     *    else {
   134     *        print("No DDR memory segment was found");
   135     *    }
   136     *
   137     *  @p
   138     *
   139     *  The following example demonstrates how to add a peripheral's address
   140     *  to the MMU table so that it can be accessed by code at runtime:
   141     *
   142     *  @p(code)
   143     *    var Cache = xdc.useModule('ti.sysbios.family.arm.a15.Cache');
   144     *    var Mmu = xdc.useModule('ti.sysbios.family.arm.a15.Mmu');
   145     *
   146     *    // Enable the cache
   147     *    Cache.enableCache = true;
   148     *
   149     *    // Enable the MMU (Required for L1/L2 data caching)
   150     *    Mmu.enableMMU = true;
   151     *
   152     *    // descriptor attribute structure
   153     *    var peripheralAttrs = new Mmu.DescriptorAttrs();
   154     *
   155     *    Mmu.initDescAttrsMeta(peripheralAttrs);
   156     *
   157     *    peripheralAttrs.type = Mmu.DescriptorType_BLOCK;  // BLOCK descriptor
   158     *    peripheralAttrs.noExecute = true;                 // not executable
   159     *    peripheralAttrs.accPerm = 0;                      // read/write at PL1
   160     *    peripheralAttrs.attrIndx = 1;                     // MAIR0 Byte1 describes
   161     *                                                      // memory attributes for
   162     *                                                      // each BLOCK MMU entry
   163     *
   164     *    // write memory region attribute in mairRegAttr[1] i.e. MAIR0 Reg Byte1
   165     *    Mmu.setMAIRMeta(1, 0x0);    // Mark mem regions as strongly ordered memory
   166     *
   167     *    // Define the base address of the 2 MB page
   168     *    // the peripheral resides in.
   169     *    var peripheralBaseAddr = 0xa0400000;
   170     *
   171     *    // Configure the corresponding MMU page descriptor accordingly
   172     *    Mmu.setSecondLevelDescMeta(peripheralBaseAddr,
   173     *                               peripheralBaseAddr,
   174     *                               peripheralAttrs);
   175     *  @p
   176     *
   177     *  The following example demonstrates how to modify the first level MMU entry
   178     *  at runtime. This example changes the descriptor type of the first level
   179     *  table entry from Table (default) to Block (maps memory region of size 1GB).
   180     *
   181     *  @p(code)
   182     *  ...
   183     *
   184     *  Void main(Int argc, Char * argv[])
   185     *  {
   186     *      Mmu_DescriptorAttrs attrs;
   187     *      Mmu_initDescAttrs(&attrs);
   188     *
   189     *     // Note: If running in SMP mode, all page table entries for memory
   190     *     //       shared between the SMP cores should mark the memory as
   191     *     //       inner-shareable. This is to ensure that the cached copy of
   192     *     //       the memory region is kept coherent accross cores.
   193     *
   194     *      attrs.type = Mmu_DescriptorType_BLOCK;
   195     *      attrs.shareable = 3;            // inner-shareable
   196     *      attrs.accPerm = 1;              // read/write at any privelege level
   197     *      attrs.attrIndx = 3;             // Use MAIR0 Register Byte 3 for
   198     *                                      // determining the memory attributes
   199     *                                      // for each MMU entry
   200     *
   201     *      // Note: If running in SMP mode, Mmu_setMAIR() and
   202     *      //       Mmu_setFirstLevelDesc() should not be called with Hwi, Swi
   203     *      //       or Tasking disabled.
   204     *
   205     *      // attrIndx[2] = 0b0 selects MAIR0
   206     *      // attrIndx[1:0] = 0b11 selects Byte 3 in MAIR0
   207     *      //
   208     *      // A value of 0x4F is written to Byte 3 of MAIR0. This marks the memory
   209     *      // as Normal Memory that is outer non-cacheable and inner write-back
   210     *      // cacheable for both reads and writes.
   211     *
   212     *      Mmu_setMAIR(3, 0x4F);
   213     *
   214     *      // Update the first level table's MMU entry for 0x80000000 with the
   215     *      // new attributes.
   216     *      Mmu_setFirstLevelDesc((Ptr)0x80000000, (UInt64)0x80000000, &attrs);
   217     *  }
   218     *
   219     *  @p
   220     *
   221     *  The following example demonstrates how to modify the memory attributes
   222     *  for a second level MMU entry at runtime.
   223     *
   224     *  @p(code)
   225     *  ...
   226     *
   227     *  Void main(Int argc, Char * argv[])
   228     *  {
   229     *      Mmu_DescriptorAttrs attrs;
   230     *      Mmu_initDescAttrs(&attrs);
   231     *
   232     *      attrs.type = Mmu_DescriptorType_BLOCK;
   233     *      attrs.shareable = 0;            // non-shareable
   234     *      attrs.accPerm = 1;              // read/write at any privelege level
   235     *      attrs.attrIndx = 4;             // Use MAIR1 Register Byte 0 for
   236     *                                      // determining the memory attributes
   237     *                                      // for each MMU entry
   238     *
   239     *      // Note: If running in SMP mode, Mmu_setMAIR() and
   240     *      //       Mmu_setSecondLevelDesc() should not be called with Hwi, Swi
   241     *      //       or Tasking disabled.
   242     *
   243     *      // attrIndx[2] = 0b1 selects MAIR1
   244     *      // attrIndx[1:0] = 0b00 selects Byte 0 in MAIR1
   245     *      //
   246     *      // A value of 0x4F is written to Byte 0 of MAIR1. This marks the memory
   247     *      // as Normal Memory that is outer non-cacheable and inner write-back
   248     *      // cacheable for both reads and writes.
   249     *
   250     *      Mmu_setMAIR(4, 0x4F);
   251     *
   252     *      // Update the MMU entry for 0x80000000 with the new attributes.
   253     *      Mmu_setSecondLevelDesc((Ptr)0x80000000, (UInt64)0x80000000, &attrs);
   254     *  }
   255     *
   256     *  @p
   257     *
   258     *  The following example demonstrates how to use setFirstLevelDesc() to create
   259     *  a mapping from the first level descriptor table to the second level
   260     *  descriptor table for an unmapped first level entry.
   261     *
   262     *  @p(code)
   263     *  ...
   264     *
   265     *  Void main(Int argc, Char * argv[])
   266     *  {
   267     *      UInt32 peripheralBaseAddr;
   268     *      Mmu_DescriptorAttrs attrs;
   269     *      Mmu_initDescAttrs(&attrs);
   270     *
   271     *      attrs.type = Mmu_DescriptorType_TABLE;
   272     *
   273     *      // Note: If running in SMP mode, Mmu_setMAIR(), Mmu_setFirstLevelDesc()
   274     *      //       and Mmu_setSecondLevelDesc() should not be called with Hwi, Swi
   275     *      //       or Tasking disabled.
   276     *
   277     *      // This example assumes that the first level descriptor table does
   278     *      // not have a valid entry for virtual address 0x40000000-0x7FFFFFFF.
   279     *      // The below call will map this virtual address range in the first
   280     *      // level table to the correponding second level descriptor table.
   281     *      Mmu_setFirstLevelDesc((Ptr)0x40000000, (UInt64)0x0, &attrs);
   282     *
   283     *      // Note: Second argument to Mmu_setFirstLevelDesc() is ignored
   284     *      //       when attrs.type is DescriptorType_TABLE.
   285     *
   286     *
   287     *      attrs.type = Mmu.DescriptorType_BLOCK;  // BLOCK descriptor
   288     *      attrs.noExecute = true;                 // not executable
   289     *      attrs.accPerm = 0;                      // read/write at PL1
   290     *      attrs.attrIndx = 1;                     // MAIR0 Byte1 describes
   291     *                                              // memory attributes for
   292     *                                              // each BLOCK MMU entry
   293     *
   294     *      // write memory region attribute in mairRegAttr[1] i.e. MAIR0 Reg Byte1
   295     *      Mmu_setMAIRMeta(1, 0x0); // Mark mem regions as strongly ordered memory
   296     *
   297     *      // Define the base address of the 2 MB page
   298     *      // the peripheral resides in.
   299     *      peripheralBaseAddr = 0x40400000;
   300     *
   301     *      // Now that there is a first level entry for virtual addresses
   302     *      // 0x40000000-0x7FFFFFFF that maps these addresses to a second
   303     *      // level descriptor table, we can add a second level entry that
   304     *      // maps the peripheral base address to a physical address.
   305     *      Mmu_setSecondLevelDesc(peripheralBaseAddr, peripheralBaseAddr, &attrs);
   306     *  }
   307     *
   308     *  @p
   309     *
   310     *  Notes:
   311     *  @p(blist)
   312     *      -There are size and alignment requirements on the third
   313     *       level descriptor tables depending on the page size.
   314     *      -See the {@link http://infocenter.arm.com/help/topic/com.arm.doc.ddi0406c/index.html ARM v7AR Architecture Reference Manual}
   315     *       for more info.
   316     *  @p
   317     *
   318     */
   319    
   320    @Template ("./Mmu.xdt") /* generate function to init MMU page table */
   321    @DirectCall
   322    
   323    module Mmu
   324    {
   325        const UInt NUM_LEVEL1_ENTRIES = 4;
   326    
   327        const UInt NUM_LEVEL2_ENTRIES = 512;
   328    
   329        // -------- ROV views --------
   330    
   331        /*! @_nodoc */
   332        metaonly struct PageView {
   333            String      Type;
   334            String      AddrVirtual;
   335            String      AddrPhysical;
   336            String      NextLevelTablePtr;
   337            Bool        NSTable;
   338            String      APTable;
   339            Bool        XNTable;
   340            Bool        PXNTable;
   341            Bool        NoExecute;
   342            Bool        PrivNoExecute;
   343            Bool        Contiguous;
   344            Bool        NotGlobal;
   345            Bool        AccessFlag;
   346            String      Shareable;
   347            String      AccessPerm;
   348            Bool        NonSecure;
   349            String      MemAttr;
   350            String      AttrIndx;
   351        };
   352    
   353        @Facet
   354        metaonly config ViewInfo.Instance rovViewInfo =
   355            ViewInfo.create({
   356                viewMap: [
   357                    ['Level1View', {
   358                        type: ViewInfo.MODULE_DATA,
   359                        viewInitFxn: 'viewLevel1Page',
   360                        structName: 'PageView'
   361                    }],
   362                    ['Level2View', {
   363                        type: ViewInfo.TREE_TABLE,
   364                        viewInitFxn: 'viewLevel2Page',
   365                        structName: 'PageView'
   366                    }]
   367               ]
   368           });
   369    
   370        /*!
   371         *  ======== First and Second Level descriptors ========
   372         *
   373         *  Different descriptor type encodings:
   374         *  @p(blist)
   375         *  - Invalid or Fault entry (0b00 or 0b10)
   376         *  - Block descriptor entry (0b01)
   377         *  - Table descriptor entry (0b11)
   378         *  @p
   379         *
   380         *  If a First-level table contains only one entry, it would be skipped,
   381         *  and the TTBR points to the Second-level table. This happens if the
   382         *  VA address range is 30 bits or less.
   383         */
   384        enum DescriptorType {
   385            DescriptorType_INVALID0 = 0,   /*! Virtual address is unmapped     */
   386            DescriptorType_BLOCK = 1,      /*! Block descriptor                */
   387            DescriptorType_INVALID1 = 2,   /*! Virtual address is unmapped     */
   388            DescriptorType_TABLE = 3       /*! Next-level table address        */
   389        };
   390    
   391        /*!
   392         *  Structure for setting first and second level descriptor entries
   393         *
   394         *  nsTable, apTable, xnTable and pxnTable fields are used only for
   395         *  DescriptorType.TABLE
   396         *
   397         *  noExecute, privNoExecute, contiguous, notGlobal, accessFlag, shareable,
   398         *  accPerm, nonSecure and attrIndx fields are used only for
   399         *  DescriptorType.BLOCK
   400         */
   401        struct DescriptorAttrs {
   402            DescriptorType type;    /*! first level descriptor type             */
   403            Bool  nsTable;          /*! security level for subsequent levels    */
   404            UInt8 apTable;          /*! access perm limit for subsequent levels */
   405            Bool  xnTable;          /*! XN limit for subsequent levels          */
   406            Bool  pxnTable;         /*! PXN limit for subsequent levels         */
   407            Bool  noExecute;        /*! execute-never bit                       */
   408            Bool  privNoExecute;    /*! privileged execute-never bit            */
   409            Bool  contiguous;       /*! hint bit indicating 16 adjacent table
   410                                        entries point to contiguos memory       */
   411            Bool  notGlobal;        /*! not global bit                          */
   412            Bool  accessFlag;       /*! access flag                             */
   413            UInt8 shareable;        /*! shareability field value 0-3            */
   414            UInt8 accPerm;          /*! access permission bits value 0-3        */
   415            Bool  nonSecure;        /*! non-secure bit                          */
   416            UInt8 attrIndx;         /*! stage 1 memory attributes index field for
   417                                        the indicated MAIRn register value 0-7  */
   418            UInt8 reserved;         /*! Bits[58:55] reserved for software use   */
   419        };
   420    
   421        /*!
   422         *  ======== A_nullPointer ========
   423         *  Assert raised when a pointer is null
   424         */
   425        config xdc.runtime.Assert.Id A_nullPointer  = {
   426            msg: "A_nullPointer: Pointer is null"
   427        };
   428    
   429        /*!
   430         *  ======== A_unknownDescType ========
   431         *  Assert raised when the descriptor type is not recognized.
   432         */
   433        config xdc.runtime.Assert.Id A_unknownDescType =
   434            {msg: "A_unknownDescType: Descriptor type is not recognized"};
   435    
   436        /*!
   437         *  ======== A_disableUnsupported ========
   438         *  Assert raised if Mmu_disable() called when running in SMP mode.
   439         */
   440        config xdc.runtime.Assert.Id A_disableUnsupported =
   441            {msg: "A_disableUnsupported: MMU disable is not supported in SMP mode."};
   442    
   443        /*! default descriptor attributes structure */
   444        config DescriptorAttrs defaultAttrs = {
   445            type: DescriptorType_TABLE, /* TABLE descriptor */
   446            nsTable: false,         /* security level for subsequent levels    */
   447            apTable: 0,             /* access perm limit for subsequent levels */
   448            xnTable: false,         /* XN limit for subsequent levels          */
   449            pxnTable: false,        /* PXN limit for subsequent levels         */
   450            noExecute: false,       /* execute-never bit                       */
   451            privNoExecute: false,   /* privileged execute-never bit            */
   452            contiguous: false,      /* hint bit indicating 16 adjacent table
   453                                       entries point to contiguos memory       */
   454            notGlobal: false,       /* not global bit                          */
   455            accessFlag: true,       /* access flag                             */
   456            shareable: 0,           /* shareability field                      */
   457            accPerm: 0,             /* access permission bits                  */
   458            nonSecure: false,       /* non-secure bit                          */
   459            attrIndx: 0,            /* stage 1 memory attributes index field
   460                                       for the indicated MAIRn register        */
   461            reserved: 0             /* Bits[58:55] reserved for software use   */
   462        };
   463    
   464        /*!
   465         *  ======== enableMMU ========
   466         *  Configuration parameter to enable MMU.
   467         */
   468        config Bool enableMMU = true;
   469    
   470        /*!
   471         *  ======== errata798181 ========
   472         *  Enable workaround for ARM errata 798181.
   473         *
   474         *  Errata 798181 brief description:
   475         *  Moving a virtual page that is being accessed by an active process
   476         *  can lead to unexpected behavior.
   477         */
   478        config Bool errata798181 = true;
   479    
   480        /*!
   481         *  ======== cachePlatformMemory ========
   482         *  Flag to automatically mark platform's code/data/stack memory as
   483         *  cacheable in MMU descriptor table
   484         *
   485         *  By default, all memory regions defined in the platform an
   486         *  application is built with are marked as cacheable.
   487         *
   488         *  @see xdc.bld.Program#platform
   489         *
   490         *  If manual configuration of memory regions is required, set
   491         *  this config parameter to 'false'.
   492         */
   493        metaonly config Bool cachePlatformMemory = true;
   494    
   495        /*!
   496         *  ======== setMAIRMeta ========
   497         *  Statically sets the memory attribute encoding in the MAIRn register.
   498         *
   499         *  MAIR0 and MAIR1 provide the memory attribute encodings to the possible
   500         *  {@link #DescriptorAttrs attrIndx} values in a Long-descriptor format
   501         *  translation table entry for stage 1 translations (see {@link #setMAIR}
   502         *  for more details).
   503         *
   504         *  @param(attrIndx)     Select appropriate MAIR register (0 or 1)
   505         *                       and byte offset within selected register
   506         *  @param(attr)         Memory attribute encoding
   507         */
   508        metaonly Void setMAIRMeta(UInt attrIndx, UInt attr);
   509    
   510        /*!
   511         *  ======== initDescAttrsMeta ========
   512         *  Initializes the descriptor attribute structure
   513         *
   514         *   @param(attrs)        Pointer to descriptor attribute struct
   515         */
   516        metaonly Void initDescAttrsMeta(DescriptorAttrs *descAttrs);
   517    
   518        /*!
   519         *  ======== setFirstLevelDescMeta ========
   520         *  Statically sets the descriptor for the virtual address.
   521         *
   522         *  The first level table entry for the virtual address is mapped
   523         *  to either a physical address with the attributes specified or
   524         *  maps to a second level descriptor table. The descriptor table
   525         *  is effective when the MMU is enabled.
   526         *
   527         *  If {@link #DescriptorAttrs attrs}.type is set to
   528         *  Mmu.DescriptorType_TABLE then the physical address which is
   529         *  passed as the second argument to setFirstLevelDescMeta() is
   530         *  ignored and the virtual address (aligned to 1GB) is mapped to
   531         *  the corresponding second level descriptor table.
   532         *
   533         *  @see ti.sysbios.family.arm.a15.Mmu
   534         *
   535         *  @param(virtualAddr)  The modified virtual address
   536         *  @param(phyAddr)      The physical address
   537         *  @param(attrs)        Pointer to first level descriptor attribute struct
   538         */
   539        metaonly Void setFirstLevelDescMeta(Ptr virtualAddr, UInt64 phyAddr,
   540                                            DescriptorAttrs attrs);
   541    
   542        /*!
   543         *  ======== setSecondLevelDescMeta ========
   544         *  Statically sets the descriptor for the virtual address.
   545         *
   546         *  The second level table entry for the virtual address is mapped
   547         *  to the physical address with the attributes specified. The
   548         *  descriptor table is effective when the MMU is enabled.
   549         *
   550         *  @see ti.sysbios.family.arm.a15.Mmu
   551         *
   552         *  @param(virtualAddr)  The modified virtual address
   553         *  @param(phyAddr)      The physical address
   554         *  @param(attrs)        Pointer to second level descriptor attribute struct
   555         */
   556        metaonly Void setSecondLevelDescMeta(Ptr virtualAddr, UInt64 phyAddr,
   557                                            DescriptorAttrs attrs);
   558    
   559        /*!
   560         *  ======== disable ========
   561         *  Disables the MMU.
   562         *
   563         *  If the MMU is already disabled, then simply return.
   564         *  Otherwise this function does the following:
   565         *  @p(blist)
   566         *  - If the L1 data cache is enabled, write back invalidate all
   567         *  of L1 data cache.
   568         *  - If the L1 program cache is enabled, invalidate all of L1
   569         *  program cache.
   570         *  @p
   571         *
   572         *  This function is not supported when running in SMP mode and
   573         *  will generate an assertion failure if called.
   574         *
   575         *  On ARM cores like Cortex-A15, both the cache and MMU need to be
   576         *  enabled for data caching to work. Also, on certain SoC's like
   577         *  Keystone 2, the caches need to be enabled for the inter-core
   578         *  lock (used in SMP mode) to work. Therefore, disabling the MMU
   579         *  is not permitted when running in SMP mode.
   580         *
   581         *  @a(Note)
   582         *  This function does not change the cache L1 data/program settings.
   583         */
   584        Void disable();
   585    
   586        /*!
   587         *  ======== enable ========
   588         *  Enables the MMU.
   589         *
   590         *  If the MMU is already enabled, then simply return.
   591         *  Otherwise this function does the following:
   592         *  @p(blist)
   593         *  If the L1 program cache is enabled, invalidate all of L1
   594         *  program cache.
   595         *  @p
   596         *
   597         *  This function enables the MMU on the core it is called from.
   598         *
   599         *  @a(Note)
   600         *  This function does not change the L1 data/program cache settings.
   601         */
   602        Void enable();
   603    
   604        /*!
   605         *  @_nodoc
   606         *  ======== getAsid ========
   607         *  Returns the current ASID
   608         *
   609         *  @b(returns)        Current ASID
   610         */
   611        UInt8 getAsid();
   612    
   613        /*!
   614         *  @_nodoc
   615         *  ======== getFirstLevelTableAddr ========
   616         *  Returns the first level MMU table base address
   617         *
   618         *  @b(returns)        MMU table base address
   619         */
   620        Ptr getFirstLevelTableAddr();
   621    
   622        /*!
   623         *  @_nodoc
   624         *  ======== getSecondLevelTableAddr ========
   625         *  Returns the MMU second level table base address
   626         *
   627         *  In LPAE mode, there can be upto 4 second level tables. This API
   628         *  takes an index as an argument and uses it to determine which
   629         *  second level table address to return.
   630         *
   631         *  @b(returns)        MMU table base address
   632         *  @param(idx)        Second level table index
   633         */
   634        Ptr getSecondLevelTableAddr(UInt8 idx);
   635    
   636        /*!
   637         *  ======== initDescAttrs() ========
   638         *  Initializes the descriptor attribute structure
   639         *
   640         *  @param(attrs)      Pointer to descriptor attribute struct
   641         */
   642        Void initDescAttrs(DescriptorAttrs *descAttrs);
   643    
   644        /*!
   645         *  ======== isEnabled ========
   646         *  Determines if the MMU is enabled
   647         */
   648        Bool isEnabled();
   649    
   650        /*!
   651         *  ======== setMAIR ========
   652         *  Sets the memory attribute encoding in the MAIRn register.
   653         *
   654         *  MAIR0 and MAIR1 provide the memory attribute encodings to the possible
   655         *  {@link #DescriptorAttrs attrIndx} values in a long-descriptor format
   656         *  translation table entry for stage 1 translations.
   657         *
   658         *  {@link #DescriptorAttrs attrIndx}[1:0] selects the ATTRn bit-field in
   659         *  the selected MAIR register.
   660         *
   661         *  {@link #DescriptorAttrs attrIndx}[2] selects the MAIR register.
   662         *  @p(blist)
   663         *   - If {@link #DescriptorAttrs attrIndx}[2] == 0, use MAIR0
   664         *   - If {@link #DescriptorAttrs attrIndx}[2] == 1, use MAIR1
   665         *  @p
   666         *
   667         *  Memory Attribute Indirection Register (MAIR) 0 and 1 bit assignments:
   668         *  @p(code)
   669         *        |31     |    24|23     |     16|15     |      8|7      |      0|
   670         *         --------------------------------------------------------------
   671         *  MAIR0 |     ATTR3    |     ATTR2     |     ATTR1     |     ATTR0     |
   672         *         --------------------------------------------------------------
   673         *  MAIR1 |     ATTR7    |     ATTR6     |     ATTR5     |     ATTR4     |
   674         *         --------------------------------------------------------------
   675         *  @p
   676         *
   677         *  SYS/BIOS assigns the following defaults to MAIR0 ATTR0, ATTR1 and ATTR2:
   678         *  @p(code)
   679         *  ATTR0 -> 0x44 (mark memory region as non-cacheable normal memory)
   680         *  ATTR1 -> 0x00 (mark memory region as strongly ordered and non-cacheable)
   681         *  ATTR2 -> 0xFF (mark memory region as normal memory, RW cacheable and
   682         *  RW allocate)
   683         *  @p
   684         *
   685         *  The level1 and level2 MMU Table entries use the above default
   686         *  attributes created by this module and should preferably not be
   687         *  changed. Please note that if the default value assigned to ATTR0 is
   688         *  changed, then the {@link #cachePlatformMemory} config param may not
   689         *  behave correctly as it uses this attribute to mark the memory as
   690         *  non-cacheable normal memory. If ATTR1 or ATTR2 are changed, it will
   691         *  affect all existing MMU Table entries which use ATTR1 or ATTR2.
   692         *
   693         *  For more details on MAIR0 and MAIR1 encodings please refer
   694         *  {@link http://infocenter.arm.com/help/topic/com.arm.doc.ddi0406c/index.html v7A ARM Architecture Reference Manual}
   695         *
   696         *  @param(attrIndx)     Select appropriate MAIR register (0 or 1)
   697         *                       and byte offset within the selected register
   698         *  @param(attr)         Memory attribute encoding
   699         *
   700         *  @a(Note)
   701         *  This function only invalidates the TLB and does not flush the cache.
   702         *  If the cacheability attribute of a region of memory is changed by
   703         *  modifying the MAIR entry for the region, the application needs to
   704         *  flush and invalidate the region of memory from the cache.
   705         *
   706         *  @a(Note)
   707         *  If running in SMP mode, this function broadcasts to the other cores
   708         *  and ensures the MAIR entry is updated on all cores. Therefore, this
   709         *  function should not be called with Hwi, Swi or Tasking disabled as
   710         *  that would cause the inter-core lock to be taken by the current core
   711         *  and will prevent the function from broadcasting a MAIR update request
   712         *  to the other cores. If not running in SMP mode, it is okay to call
   713         *  this function with Hwi, Swi or Tasking disabled.
   714         */
   715        Void setMAIR(UInt attrIndx, UInt attr);
   716    
   717        /*!
   718         *  ======== setFirstLevelDesc ========
   719         *  Sets the descriptor for the virtual address.
   720         *
   721         *  The first level table entry for the virtual address is mapped
   722         *  to either a physical address with the attributes specified or
   723         *  maps to a second level descriptor table. The descriptor table
   724         *  is effective when the MMU is enabled.
   725         *
   726         *  If {@link #DescriptorAttrs attrs}.type is set to
   727         *  DescriptorType_TABLE then the physical address which is
   728         *  passed as the second argument to setFirstLevelDesc() is
   729         *  ignored and the virtual address (aligned to 1GB) is mapped to
   730         *  the corresponding second level descriptor table.
   731         *
   732         *  @see ti.sysbios.family.arm.a15.Mmu
   733         *
   734         *  @param(virtualAddr) The modified virtual address
   735         *  @param(phyAddr)     The physical address
   736         *  @param(attrs)       Pointer to first level descriptor attribute struct
   737         *
   738         *  @a(Note)
   739         *  If running in SMP mode, this function broadcasts to the other cores
   740         *  to ensure all cores execute a barrier instruction and the MMU table
   741         *  updates are visible to them. Therefore, this function should not be
   742         *  called with Hwi, Swi or Tasking disabled as that would cause the
   743         *  inter-core lock to be taken by the current core and will prevent the
   744         *  function from broadcasting to the other cores. If not running in
   745         *  SMP mode, it is okay to call this function with Hwi, Swi or Tasking
   746         *  disabled.
   747         */
   748        Void setFirstLevelDesc(Ptr virtualAddr, UInt64 phyAddr,
   749                               DescriptorAttrs *attrs);
   750    
   751        /*!
   752         *  ======== setSecondLevelDesc ========
   753         *  Sets the descriptor for the virtual address.
   754         *
   755         *  The second level table entry for the virtual address is mapped
   756         *  to the physical address with the attributes specified. The
   757         *  descriptor table is effective when the MMU is enabled.
   758         *
   759         *  @see ti.sysbios.family.arm.a15.Mmu
   760         *
   761         *  @param(virtualAddr) The modified virtual address
   762         *  @param(phyAddr)     The physical address
   763         *  @param(attrs)       Pointer to second level descriptor attribute struct
   764         *
   765         *  @a(Note)
   766         *  If running in SMP mode, this function broadcasts to the other cores
   767         *  to ensure all cores execute a barrier instruction and the MMU table
   768         *  updates are visible to them. Therefore, this function should not be
   769         *  called with Hwi, Swi or Tasking disabled as that would cause the
   770         *  inter-core lock to be taken by the current core and will prevent the
   771         *  function from broadcasting to the other cores. If not running in
   772         *  SMP mode, it is okay to call this function with Hwi, Swi or Tasking
   773         *  disabled.
   774         */
   775        Void setSecondLevelDesc(Ptr virtualAddr, UInt64 phyAddr,
   776                                DescriptorAttrs *attrs);
   777    
   778        /*!
   779         *  @_nodoc
   780         *  ======== startup ========
   781         *  startup function to initialize MMU module
   782         */
   783        Void startup();
   784    
   785        /*!
   786         *  @_nodoc
   787         *  ======== switchContext ========
   788         *  Switches the ASID and changes the MMU table base address
   789         *
   790         *  Note: This function does not validate the mmuTable pointer
   791         *
   792         *  @param(asid)        ASID to switch to
   793         *  @param(mmuTable)    MMU table base address to switch to
   794         */
   795        Void switchContext(UInt8 asid, Ptr mmuTable);
   796    
   797        /*!
   798         *  ======== tlbInv ========
   799         *  Invalidate the TLB entries (both data and instruction) for the range of
   800         *  memory within the specified starting address and byte count. The range
   801         *  of addresses operated on gets quantized to page size.
   802         */
   803        Void tlbInv(Ptr startAddr, SizeT byteCnt);
   804    
   805        /*!
   806         *  ======== tlbInvAll ========
   807         *  Invalidate entire TLB (both data and instruction)
   808         */
   809        Void tlbInvAll();
   810    
   811    internal:
   812    
   813        /*! static array to hold first level dscriptor table */
   814        metaonly config UInt32 firstLevelTableBuf[];
   815    
   816        /*! static array to hold second level dscriptor table */
   817        metaonly config UInt32 secondLevelTableBuf[NUM_LEVEL1_ENTRIES][];
   818    
   819        /*!
   820         *  Memory Attribute Indirection Register 0 and 1
   821         */
   822        config UInt mairRegAttr[8];
   823    
   824        /*!
   825         *  ======== init ========
   826         *  initialize mmu registers
   827         */
   828        Void init();
   829    
   830        /*!
   831         *  ======== enableAsm ========
   832         *  Assembly function to enable the MMU.
   833         */
   834        Void enableAsm();
   835    
   836        /*!
   837         *  ======== disableAsm ========
   838         *  Assembly function to disable the MMU.
   839         */
   840        Void disableAsm();
   841    
   842        /*!
   843         *  ======== flushLevel1PageTable ========
   844         *  Does a MMU table walk to determine if all pages corresponding
   845         *  to a given virtual address are valid before flushing the cache.
   846         *  This ensures that we do not attempt to flush an unmapped block
   847         *  of memory.
   848         */
   849        Void flushLevel1PageTable(Ptr virtualAddr, UInt64 desc);
   850    
   851        /*!
   852         *  ======== flushLevel2PageTable ========
   853         *  Does a MMU table walk to determine if all pages corresponding
   854         *  to a given virtual address are valid before flushing the cache.
   855         *  This ensures that we do not attempt to flush an unmapped block
   856         *  of memory.
   857         */
   858        Void flushLevel2PageTable(Ptr virtualAddr, UInt64 desc);
   859    
   860        /*!
   861         *  ======== writeMAIRAsm ========
   862         */
   863        Void writeMAIRAsm(UInt attrIndx, UInt attr);
   864    
   865        /*!
   866         *  ======== setMAIRCoreX ========
   867         */
   868        Void setMAIRCoreX(UArg attrs);
   869    
   870        /*! function generated to zero out firs and second level descriptor tables */
   871        Void clearTableBuf();
   872    
   873        /*! function generated to initialize first level descriptor table */
   874        Void initFirstLevelTableBuf();
   875    
   876        /*! function generated to initialize second level descriptor table */
   877        Void initSecondLevelTableBuf();
   878    
   879        /*! function call isb barrier instruction */
   880        Void instructionSync(UArg arg);
   881    
   882        /*! Module state */
   883        struct Module_State {
   884            /*
   885             *  32 Byte array for first-level descriptors
   886             */
   887            UInt64 firstLevelTableBuf[];
   888    
   889            /*
   890             *  4 KByte array for second-level descriptors
   891             */
   892            UInt64 secondLevelTableBuf[NUM_LEVEL1_ENTRIES][];
   893    
   894            /*
   895             *  Memory Attribute Indirection Register 0 and 1
   896             */
   897            volatile UInt mairRegAttr[8];
   898        }
   899    }