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