1    /* 
     2     * Copyright (c) 2012, 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     */
    37    
    38    package ti.sysbios.family.arm.a8;
    39    
    40    import xdc.rov.ViewInfo;
    41    
    42    /*!
    43     *  ======== Mmu ========
    44     *  Memory Management Unit Manager.
    45     *
    46     *  This module allows the ARM processor to map a virtual address to a
    47     *  different physical address and enable/disable the MMU.  It does this
    48     *  through a translation table in memory.  The translation table is
    49     *  16KB and manages only the first level descriptor table.  Each entry
    50     *  in the table defines the properties of memory areas of size 1MB.
    51     *  These properties include memory access permissions, cacheability,
    52     *  bufferability, and domain access.
    53     *  
    54     *  By default, the MMU translation table is initialized with 
    55     *  cache-enabled entries for every memory segment defined in the platform.
    56     *  Cache-disabled entries are also added for the peripheral
    57     *  addresses used by SYS/BIOS (i.e. Timers, Interrupt controller).  
    58     *
    59     *  The translation table is placed in
    60     *  an output section called "ti.sysbios.family.arm.a8.mmuTableSection".
    61     *  This section is placed into the platform's default dataMemory and
    62     *  specified to not be initialized via the "NOINIT" type. 
    63     *
    64     *  This module does not manage the second level descriptor tables.
    65     *  A 'SECTION' mapped access requires only a first level fetch.  In
    66     *  this case, there is no need for a second level descriptor table.
    67     *  A 'PAGE_TABLE' mapped access requires a second level
    68     *  descriptor table which can be supplied by the user.
    69     *
    70     *  The following is an example of how to place the MMU table
    71     *  and how to enable L1 data caching for the address range
    72     *  0x80000000-0x90000000 in the *.cfg file:
    73     *
    74     *  @p(code)
    75     *
    76     *    var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
    77     *    var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
    78     *
    79     *    // Enable the cache
    80     *    Cache.enableCache = true;
    81     *
    82     *    // Enable the MMU (Required for L1/L2 data caching)
    83     *    Mmu.enableMMU = true;
    84     *
    85     *    // descriptor attribute structure
    86     *    var attrs = {
    87     *        type: Mmu.FirstLevelDesc_SECTION,  // SECTION descriptor
    88     *        bufferable: true,                  // bufferable
    89     *        cacheable: true,                   // cacheable
    90     *    };
    91     *
    92     *    // Set the descriptor for each entry in the address range
    93     *    for (var i=0x80000000; i < 0x90000000; i = i + 0x00100000) {
    94     *        // Each 'SECTION' descriptor entry spans a 1MB address range
    95     *        Mmu.setFirstLevelDescMeta(i, i, attrs);
    96     *    }
    97     *
    98     *    var memmap = Program.cpu.memoryMap;
    99     *    var DDR = null;
   100     *    
   101     *    // Find DDR in memory map
   102     *    for (var i=0; i < memmap.length; i++) {
   103     *        if (memmap[i].name == "DDR") {
   104     *            DDR = memmap[i];
   105     *        } 
   106     *    }
   107     *
   108     *    // Place the MMU table in the DDR memory segment if it exists
   109     *    if (DDR != null) {
   110     *        var sectionName = "ti.sysbios.family.arm.a8.mmuTableSection";
   111     *        Program.sectMap[sectionName] = new Program.SectionSpec();
   112     *        Program.sectMap[sectionName].type = "NOINIT";
   113     *        Program.sectMap[sectionName].loadSegment = "DDR";
   114     *    }
   115     *    else {
   116     *        print("No DDR memory segment was found");
   117     *    }
   118     *
   119     *  @p
   120     *
   121     *  The following example demonstrates how to add a peripheral's address
   122     *  to the MMU table so that it can be accessed by code at runtime:
   123     *
   124     *  @p(code)
   125     *    var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
   126     *    var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
   127     *
   128     *    // Enable the cache
   129     *    Cache.enableCache = true;
   130     *
   131     *    // Enable the MMU (Required for L1/L2 data caching)
   132     *    Mmu.enableMMU = true;
   133     *
   134     *    // Force peripheral section to be NON cacheable
   135     *    var peripheralAttrs = {
   136     *        type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
   137     *        bufferable : false,                // bufferable
   138     *        cacheable  : false,                // cacheable
   139     *        shareable  : false,                // shareable
   140     *        noexecute  : true,                 // not executable
   141     *    };
   142     *   
   143     *    // Define the base address of the 1 Meg page 
   144     *    // the peripheral resides in.
   145     *    var peripheralBaseAddr = 0xa0400000;
   146     *
   147     *    // Configure the corresponding MMU page descriptor accordingly
   148     *    Mmu.setFirstLevelDescMeta(peripheralBaseAddr, 
   149     *                              peripheralBaseAddr, 
   150     *                              peripheralAttrs);
   151     *  @p
   152     *     
   153     *  Notes:
   154     *  @p(blist)
   155     *      -The 'Supersection' table descriptor is NOT supported.
   156     *      -The 'not global' page descriptor setting is NOT supported.
   157     *      -The 'non-secure' page descriptor setting is NOT supported.
   158     *      -There are size and alignment requirements on the second
   159     *       level descriptor tables depending on the page size.
   160     *      -See the ARM Architecture Reference Manual for more info.
   161     *  @p
   162     *
   163     */
   164    
   165    @Template ("./Mmu.xdt") /* generate function to init MMU page table */
   166    @ModuleStartup          /* call to initTableBuf() in startup */
   167    
   168    module Mmu
   169    {
   170        // -------- ROV views --------
   171    
   172        /*! @_nodoc */
   173        metaonly struct PageView {
   174            String      Type;
   175            Ptr         AddrVirtual;
   176            Ptr         AddrPhysical;
   177            Ptr         Level2TablePtr;
   178            Bool        Bufferable;
   179            Bool        Cacheable;
   180            Bool        Shareable;
   181            Bool        Noexecute;
   182            String      L1DWritePolicy;
   183            UInt        IMP;
   184            UInt        Domain;
   185            String      Access;
   186        };
   187    
   188        @Facet
   189        metaonly config ViewInfo.Instance rovViewInfo =
   190            ViewInfo.create({
   191                viewMap: [
   192                    ['PageView', {
   193                        type: ViewInfo.MODULE_DATA,
   194                        viewInitFxn: 'viewPages',
   195                        structName: 'PageView'
   196                    }]
   197               ]
   198           });
   199    
   200       /*! First Level descriptors */
   201        enum FirstLevelDesc {
   202            FirstLevelDesc_FAULT = 0,       /*! Virtual address is unmapped */
   203            FirstLevelDesc_PAGE_TABLE = 1,  /*! Page table addr descriptor  */
   204            FirstLevelDesc_SECTION = 2      /*! Section descriptor          */
   205        };
   206    
   207        /*! 
   208         *  Structure for setting first level descriptor entries
   209         *
   210         *  If the 'cacheable' attribute is true and 'bufferable' is true, 
   211         *  L1 data cache operates as a write-back cache.
   212         *  If 'cacheable' is true but 'bufferable' is false,
   213         *  L1 data cache operates as a write-through cache.
   214         *
   215         *  See the 'Translation Tables' section of the ARM v7 Architecture 
   216         *  Reference Manual for more details.
   217         */
   218        struct FirstLevelDescAttrs {
   219            FirstLevelDesc type;    /*! first level descriptor type         */
   220            Bool  bufferable;       /*! is memory section bufferable        */
   221            Bool  cacheable;        /*! is memory section cacheable         */
   222            Bool  shareable;        /*! is memory section shareable         */
   223            Bool  noexecute;        /*! is memory section not executable    */
   224            UInt8 imp;              /*! implementation defined              */
   225            UInt8 domain;           /*! domain access control value 0-15    */
   226            UInt8 accPerm;          /*! access permission bits value 0-3    */
   227        };
   228        
   229        /*!
   230         *  ======== A_nullPointer ========
   231         *  Assert raised when a pointer is null
   232         */
   233        config xdc.runtime.Assert.Id A_nullPointer  = {
   234            msg: "A_nullPointer: Pointer is null"
   235        };
   236    
   237        /*!
   238         *  ======== A_unknownDescType ========
   239         *  Assert raised when the descriptor type is not recognized.
   240         */
   241        config xdc.runtime.Assert.Id A_unknownDescType =
   242            {msg: "A_unknownDescType: Descriptor type is not recognized"};
   243    
   244        /*! default descriptor attributes structure */
   245        config FirstLevelDescAttrs defaultAttrs = {
   246            type: FirstLevelDesc_SECTION,   /* SECTION descriptor           */
   247            bufferable: false,              /* false by default             */
   248            cacheable: false,               /* false by default             */
   249            shareable: false,               /* false by default             */
   250            noexecute: false,               /* false by default             */
   251            imp: 1,                         /* set to 1 for A8 devices      */
   252            domain: 0,                      /* default Domain is 0          */
   253            accPerm: 3,                     /* allow read/write             */
   254        };
   255    
   256        /*!
   257         *  ======== enableMMU ========
   258         *  Configuration parameter to enable MMU.
   259         */
   260        config Bool enableMMU = true;
   261    
   262        /*!
   263         *  ======== cachePlatformMemory ========
   264         *  Flag to automatically mark platform's code/data/stack memory as 
   265         *  cacheable in MMU descriptor table
   266         *
   267         *  By default, all memory regions defined in the platform an 
   268         *  application is built with are marked as cacheable.
   269         *
   270         *  @see xdc.bld.Program#platform
   271         *
   272         *  If manual configuration of memory regions is required, set
   273         *  this config parameter to 'false'.
   274         */
   275        metaonly config Bool cachePlatformMemory = true;
   276    
   277        /*!
   278         *  ======== setFirstLevelDescMeta ========
   279         *  Statically sets the descriptor for the virtual address.
   280         *
   281         *  The first level table entry for the virtual address is mapped
   282         *  to the physical address with the attributes specified. The
   283         *  descriptor table is effective when the MMU is enabled.
   284         *
   285         *  @param(virtualAddr)  The modified virtual address
   286         *  @param(phyAddr)      The physical address
   287         *  @param(attrs)        Pointer to first level descriptor attribute struct
   288         */
   289        metaonly Void setFirstLevelDescMeta(Ptr virtualAddr, Ptr phyAddr,
   290                                            FirstLevelDescAttrs attrs);
   291    
   292        /*! @_nodoc
   293         *  ======== disable ========
   294         *  Disables the MMU.
   295         *
   296         *  If the MMU is already disabled, then simply return.
   297         *  Otherwise this function does the following:
   298         *  If the L1 data cache is enabled, write back invalidate all
   299         *  of L1 data cache.  If the L1 program cache is enabled,
   300         *  invalidate all of L1 program cache. This function does not
   301         *  change the cache L1 data/program settings.
   302         */
   303        @DirectCall
   304        Void disable();
   305        
   306        /*!
   307         *  ======== enable ========
   308         *  Enables the MMU.
   309         *
   310         *  If the MMU is already enabled, then simply return.
   311         *  Otherwise this function does the following:
   312         *  If the L1 program cache is enabled, invalidate all of L1
   313         *  program cache.  This function does not change the L1
   314         *  data/program cache settings.
   315         */
   316        @DirectCall
   317        Void enable();
   318    
   319        /*!
   320         *  ======== initDescAttrs() ========
   321         *  Initializes the first level descriptor attribute structure
   322         *
   323         *  @param(attrs)      Pointer to first level descriptor attribute struct
   324         */
   325        @DirectCall
   326        Void initDescAttrs(FirstLevelDescAttrs *attrs);
   327        
   328        /*!
   329         *  ======== isEnabled ========
   330         *  Determines if the MMU is enabled
   331         */
   332        @DirectCall
   333        Bool isEnabled();
   334        
   335        /*!
   336         *  ======== setFirstLevelDesc ========
   337         *  Sets the descriptor for the virtual address.
   338         *
   339         *  The first level table entry for the virtual address is mapped
   340         *  to the physical address with the attributes specified. The
   341         *  descriptor table is effective when the MMU is enabled.
   342         *
   343         *  @param(virtualAddr)  The modified virtual address
   344         *  @param(phyAddr)      The physical address
   345         *  @param(attrs)        Pointer to first level descriptor attribute struct
   346         */
   347        @DirectCall
   348        Void setFirstLevelDesc(Ptr virtualAddr, Ptr phyAddr,
   349                               FirstLevelDescAttrs *attrs);
   350    
   351    
   352    internal:
   353    
   354        /*! static array to hold first level dscriptor table */
   355        metaonly config UInt32 tableBuf[];
   356        
   357        /*!
   358         *  ======== enableAsm ========
   359         *  Assembly function to enable the MMU.
   360         */
   361        Void enableAsm();
   362    
   363        /*!
   364         *  ======== disableAsm ========
   365         *  Assembly function to disable the MMU.
   366         */
   367        Void disableAsm();
   368    
   369        /*! function generated to initialize first level descriptor table */
   370        Void initTableBuf(Module_State *mod);
   371        
   372        /*! Module state */
   373        struct Module_State {
   374            UInt32 tableBuf[];      /*! 16KB array for first-level descriptors */
   375        }
   376    }
   377    /*
   378     *  @(#) ti.sysbios.family.arm.a8; 2, 0, 0, 0,151; 2-24-2012 11:39:09; /db/vtree/library/trees/avala/avala-q28x/src/ xlibrary
   379    
   380     */
   381