module ti.sysbios.family.arm.a15.Mmu |
|
|
|
Memory Management Unit Manager
This module allows the ARM processor to map a 32-bit virtual address
to a 40-bit physical address (supports Large physical address extensions)
and enable/disable the MMU. It does this through translation tables
in memory. The MMU hardware supports upto 3-levels of translation tables.
This module only supports the first 2 levels of translation tables.
The level1 translation table is a 32B descriptor table comprising of
four 64bit entries. There can be upto 4 level2 translation tables,
each 4KB in size and comprising of 512 64bit entries.
[
more ... ]
#include <ti/sysbios/family/arm/a15/Mmu.h>
Functions |
Void | |
Void | |
Void | |
Bool | |
Void | |
Void | |
Void | |
Functions common to all target modules |
|
|
Defines |
#define | |
#define | |
Typedefs |
typedef struct | |
typedef enum | |
Constants |
| |
| |
| |
extern const Bool | |
DETAILS
This module allows the ARM processor to map a 32-bit virtual address
to a 40-bit physical address (supports Large physical address extensions)
and enable/disable the MMU. It does this through translation tables
in memory. The MMU hardware supports upto 3-levels of translation tables.
This module only supports the first 2 levels of translation tables.
The level1 translation table is a 32B descriptor table comprising of
four 64bit entries. There can be upto 4 level2 translation tables,
each 4KB in size and comprising of 512 64bit entries.
Each entry in the level1 table either gives the base address and
defines the attributes of a memory area of size 1GB or gives the
address of the next level of translation table and some attributes
for that translation.
Each entry in the level2 table either gives the base address and
defines the attributes of a memory area of size 2MB or gives the
address of the next level of translation table and some attributes
for that translation.
By default, the MMU level1 and level2 translation tables are initialized
with cache-enabled entries for every memory-segment defined in the
platform (see
cachePlatformMemory). Cache-disabled entries are
also added for the peripheral addresses used by SYS/BIOS
(i.e. Timers, Interrupt controller).
The level1 translation table is placed in an output section called
"ti.sysbios.family.arm.a15.mmuFirstLevelTableSection". Each of the
level2 translation table is placed in output sections called
"ti.sysbios.family.arm.a15.mmuSecondLevelTableSection0",
"ti.sysbios.family.arm.a15.mmuSecondLevelTableSection1",
"ti.sysbios.family.arm.a15.mmuSecondLevelTableSection2", and
"ti.sysbios.family.arm.a15.mmuSecondLevelTableSection3". These
sections are placed into the platform's default dataMemory and
in order to minimize object file size,
specified to not be initialized via the "NOLOAD" type on GNU compilers
and "NOINIT" on TI compilers.
This module does not manage the third level descriptor tables.
The following is an example of how to place the MMU table
and how to enable L1/L2 data caching for the address range
0x80000000-0x90000000 in the *.cfg file:
var Mmu = xdc.useModule('ti.sysbios.family.arm.a15.Mmu');
// descriptor attribute structure
var attrs = new Mmu.DescriptorAttrs();
Mmu.initDescAttrsMeta(attrs);
attrs.type = Mmu.DescriptorType_BLOCK; // BLOCK descriptor
attrs.shareable = 3; // inner-sharerable
attrs.attrIndx = 2; // MAIR0 Byte2 describes
// memory attributes for
// this level2 entry
// write memory region attribute in mairRegAttr[2] i.e. MAIR0 Reg Byte2
Mmu.setMAIRMeta(2, 0xFF); // Mark mem regions as cacheable
// Set the descriptor for each entry in the address range
for (var i=0x80000000; i < 0x90000000; i = i + 0x00200000) {
// Each 'BLOCK' descriptor entry spans a 2MB address range
Mmu.setSecondLevelDescMeta(i, i, attrs);
}
var memmap = Program.cpu.memoryMap;
var DDR = null;
// Find DDR in memory map
for (var i=0; i < memmap.length; i++) {
if (memmap[i].name == "DDR") {
DDR = memmap[i];
}
}
// Place the MMU table in the DDR memory segment if it exists
if (DDR != null) {
var sectionName =
"ti.sysbios.family.arm.a15.mmuSecondLevelTableSection2";
Program.sectMap[sectionName] = new Program.SectionSpec();
Program.sectMap[sectionName].type = "NOLOAD";
Program.sectMap[sectionName].loadSegment = "DDR";
}
else {
print("No DDR memory segment was found");
}
The following example demonstrates how to add a peripheral's address
to the MMU table so that it can be accessed by code at runtime:
var Cache = xdc.useModule('ti.sysbios.family.arm.a15.Cache');
var Mmu = xdc.useModule('ti.sysbios.family.arm.a15.Mmu');
// Enable the cache
Cache.enableCache = true;
// Enable the MMU (Required for L1/L2 data caching)
Mmu.enableMMU = true;
// descriptor attribute structure
var peripheralAttrs = new Mmu.DescriptorAttrs();
Mmu.initDescAttrsMeta(peripheralAttrs);
peripheralAttrs.type = Mmu.DescriptorType_BLOCK; // BLOCK descriptor
peripheralAttrs.noExecute = true; // not executable
peripheralAttrs.accPerm = 0; // read/write at PL1
peripheralAttrs.attrIndx = 1; // MAIR0 Byte1 describes
// memory attributes for
// each BLOCK MMU entry
// write memory region attribute in mairRegAttr[1] i.e. MAIR0 Reg Byte1
Mmu.setMAIRMeta(1, 0x0); // Mark mem regions as strongly ordered memory
// Define the base address of the 2 MB page
// the peripheral resides in.
var peripheralBaseAddr = 0xa0400000;
// Configure the corresponding MMU page descriptor accordingly
Mmu.setSecondLevelDescMeta(peripheralBaseAddr,
peripheralBaseAddr,
peripheralAttrs);
The following example demonstrates how to modify the first level MMU entry
at runtime. This example changes the descriptor type of the first level
table entry from Table (default) to Block (maps memory region of size 1GB).
...
Void main(Int argc, Char * argv[])
{
Mmu_DescriptorAttrs attrs;
Mmu_initDescAttrs(&attrs);
attrs.type = Mmu_DescriptorType_BLOCK;
attrs.shareable = 0; // non-shareable
attrs.accPerm = 1; // read/write at any privelege level
attrs.attrIndx = 3; // Use MAIR0 Register Byte 3 for
// determining the memory attributes
// for each MMU entry
// attrIndx[2] = 0b0 selects MAIR0
// attrIndx[1:0] = 0b11 selects Byte 3 in MAIR0
//
// A value of 0x4F is written to Byte 3 of MAIR0. This marks the memory
// as Normal Memory that is outer non-cacheable and inner write-back
// cacheable for both reads and writes.
Mmu_setMAIR(3, 0x4F);
// Update the first level table's MMU entry for 0x80000000 with the
// new attributes.
Mmu_setFirstLevelDesc((Ptr)0x80000000, (UInt64)0x80000000, &attrs);
}
The following example demonstrates how to modify the memory attributes
for a second level MMU entry at runtime.
...
Void main(Int argc, Char * argv[])
{
Mmu_DescriptorAttrs attrs;
Mmu_initDescAttrs(&attrs);
attrs.type = Mmu_DescriptorType_BLOCK;
attrs.shareable = 0; // non-shareable
attrs.accPerm = 1; // read/write at any privelege level
attrs.attrIndx = 4; // Use MAIR1 Register Byte 0 for
// determining the memory attributes
// for each MMU entry
// attrIndx[2] = 0b1 selects MAIR1
// attrIndx[1:0] = 0b00 selects Byte 0 in MAIR1
//
// A value of 0x4F is written to Byte 0 of MAIR1. This marks the memory
// as Normal Memory that is outer non-cacheable and inner write-back
// cacheable for both reads and writes.
Mmu_setMAIR(4, 0x4F);
// Update the MMU entry for 0x80000000 with the new attributes.
Mmu_setSecondLevelDesc((Ptr)0x80000000, (UInt64)0x80000000, &attrs);
}
Notes:
const Mmu_NUM_LEVEL1_ENTRIES |
|
#define Mmu_NUM_LEVEL1_ENTRIES (UInt)4
const Mmu_NUM_LEVEL2_ENTRIES |
|
#define Mmu_NUM_LEVEL2_ENTRIES (UInt)512
enum Mmu_DescriptorType |
|
Different descriptor type encodings:
typedef enum Mmu_DescriptorType {
Mmu_DescriptorType_INVALID0,
// Virtual address is unmapped
Mmu_DescriptorType_BLOCK,
// Block descriptor
Mmu_DescriptorType_INVALID1,
// Virtual address is unmapped
Mmu_DescriptorType_TABLE
// Next-level table address
} Mmu_DescriptorType;
DETAILS
- Invalid or Fault entry (0b00 or 0b10)
- Block descriptor entry (0b01)
- Table descriptor entry (0b11)
If a First-level table contains only one entry, it would be skipped,
and the TTBR points to the Second-level table. This happens if the
VA address range is 30 bits or less.
struct Mmu_DescriptorAttrs |
|
Structure for setting first and second level descriptor entries
typedef struct Mmu_DescriptorAttrs {
// first level descriptor type
Bool nsTable;
// security level for subsequent levels
UInt8 apTable;
// access perm limit for subsequent levels
Bool xnTable;
// XN limit for subsequent levels
Bool pxnTable;
// PXN limit for subsequent levels
Bool noExecute;
// execute-never bit
Bool privNoExecute;
// privileged execute-never bit
Bool contiguous;
// hint bit indicating 16 adjacent table
entries point to contiguos memory
Bool notGlobal;
// not global bit
Bool accessFlag;
// access flag
UInt8 shareable;
// shareability field value 0-3
UInt8 accPerm;
// access permission bits value 0-3
Bool nonSecure;
// non-secure bit
UInt8 attrIndx;
// stage 1 memory attributes index field for
the indicated MAIRn register value 0-7
UInt8 reserved;
// Bits[58:55] reserved for software use
} Mmu_DescriptorAttrs;
DETAILS
nsTable, apTable, xnTable and pxnTable fields are used only for
DescriptorType.TABLE
noExecute, privNoExecute, contiguous, notGlobal, accessFlag, shareable,
accPerm, nonSecure and attrIndx fields are used only for
DescriptorType.BLOCK
config Mmu_A_nullPointer // module-wide |
|
Assert raised when a pointer is null
config Mmu_A_unknownDescType // module-wide |
|
Assert raised when the descriptor type is not recognized
extern const Assert_Id Mmu_A_unknownDescType;
config Mmu_defaultAttrs // module-wide |
|
default descriptor attributes structure
config Mmu_enableMMU // module-wide |
|
Configuration parameter to enable MMU
extern const Bool Mmu_enableMMU;
Mmu_disable() // module-wide |
|
Disables the MMU
DETAILS
If the MMU is already disabled, then simply return.
Otherwise this function does the following:
- If the L1 data cache is enabled, write back invalidate all
of L1 data cache.
- If the L1 program cache is enabled, invalidate all of L1
program cache.
NOTE
This function does not change the cache L1 data/program settings.
Mmu_enable() // module-wide |
|
Enables the MMU
DETAILS
If the MMU is already enabled, then simply return.
Otherwise this function does the following:
- If the L1 program cache is enabled, invalidate all of L1
program cache.
NOTE
This function does not change the L1 data/program cache settings.
Mmu_initDescAttrs() // module-wide |
|
Initializes the descriptor attribute structure
ARGUMENTS
attrs
Pointer to descriptor attribute struct
Mmu_isEnabled() // module-wide |
|
Determines if the MMU is enabled
Mmu_setFirstLevelDesc() // module-wide |
|
Sets the descriptor for the virtual address
ARGUMENTS
virtualAddr
The modified virtual address
phyAddr
The physical address
attrs
Pointer to first level descriptor attribute struct
DETAILS
The first level table entry for the virtual address is mapped
to the physical address with the attributes specified. The
descriptor table is effective when the MMU is enabled.
SEE
Mmu_setMAIR() // module-wide |
|
Sets the memory attribute encoding in the MAIRn register
Void Mmu_setMAIR(UInt attrIndx, UInt attr);
ARGUMENTS
attrIndx
Select appropriate MAIR register (0 or 1)
and byte offset within the selected register
attr
Memory attribute encoding
DETAILS
MAIR0 and MAIR1 provide the memory attribute encodings to the possible
attrIndx values in a long-descriptor format
translation table entry for stage 1 translations.
attrIndx[1:0] selects the ATTRn bit-field in
the selected MAIR register.
attrIndx[2] selects the MAIR register.
Memory Attribute Indirection Register (MAIR) 0 and 1 bit assignments:
|31 | 24|23 | 16|15 | 8|7 | 0|
--------------------------------------------------------------
MAIR0 | ATTR3 | ATTR2 | ATTR1 | ATTR0 |
--------------------------------------------------------------
MAIR1 | ATTR7 | ATTR6 | ATTR5 | ATTR4 |
--------------------------------------------------------------
SYS/BIOS assigns the following defaults to MAIR0 ATTR0, ATTR1 and ATTR2:
ATTR0 -> 0x44 (mark memory region as non-cacheable normal memory)
ATTR1 -> 0x00 (mark memory region as strongly ordered and non-cacheable)
ATTR2 -> 0xFF (mark memory region as normal memory, RW cacheable and
RW allocate)
The level1 and level2 MMU Table entries use the above default
attributes created by this module and should preferably not be
changed. Please note that if the default value assigned to ATTR0 is
changed, then the
cachePlatformMemory config param may not
behave correctly as it uses this attribute to mark the memory as
non-cacheable normal memory. If ATTR1 or ATTR2 are changed, it will
affect all existing MMU Table entries which use ATTR1 or ATTR2.
For more details on MAIR0 and MAIR1 encodings please refer
v7A ARM Architecture Reference Manual
Mmu_setSecondLevelDesc() // module-wide |
|
Sets the descriptor for the virtual address
ARGUMENTS
virtualAddr
The modified virtual address
phyAddr
The physical address
attrs
Pointer to second level descriptor attribute struct
DETAILS
The second level table entry for the virtual address is mapped
to the physical address with the attributes specified. The
descriptor table is effective when the MMU is enabled.
SEE
Module-Wide Built-Ins |
|
// Get this module's unique id
Bool Mmu_Module_startupDone();
// Test if this module has completed startup
// The heap from which this module allocates memory
Bool Mmu_Module_hasMask();
// Test whether this module has a diagnostics mask
Bits16 Mmu_Module_getMask();
// Returns the diagnostics mask for this module
Void Mmu_Module_setMask(Bits16 mask);
// Set the diagnostics mask for this module
var Mmu = xdc.useModule('ti.sysbios.family.arm.a15.Mmu');
module-wide constants & types
module-wide config parameters
msg: "A_nullPointer: Pointer is null"
};
msg: "A_unknownDescType: Descriptor type is not recognized"
};
nsTable: false,
apTable: 0,
xnTable: false,
pxnTable: false,
noExecute: false,
privNoExecute: false,
contiguous: false,
notGlobal: false,
accessFlag: true,
shareable: 0,
accPerm: 0,
nonSecure: false,
attrIndx: 0,
reserved: 0
};
module-wide functions
const Mmu.NUM_LEVEL1_ENTRIES |
|
const Mmu.NUM_LEVEL1_ENTRIES = 4;
C SYNOPSIS
const Mmu.NUM_LEVEL2_ENTRIES |
|
const Mmu.NUM_LEVEL2_ENTRIES = 512;
C SYNOPSIS
enum Mmu.DescriptorType |
|
Different descriptor type encodings:
values of type Mmu.DescriptorType
const Mmu.DescriptorType_INVALID0;
// Virtual address is unmapped
const Mmu.DescriptorType_BLOCK;
// Block descriptor
const Mmu.DescriptorType_INVALID1;
// Virtual address is unmapped
const Mmu.DescriptorType_TABLE;
// Next-level table address
DETAILS
- Invalid or Fault entry (0b00 or 0b10)
- Block descriptor entry (0b01)
- Table descriptor entry (0b11)
If a First-level table contains only one entry, it would be skipped,
and the TTBR points to the Second-level table. This happens if the
VA address range is 30 bits or less.
C SYNOPSIS
struct Mmu.DescriptorAttrs |
|
Structure for setting first and second level descriptor entries
var obj = new Mmu.DescriptorAttrs;
// first level descriptor type
obj.nsTable = Bool ...
// security level for subsequent levels
obj.apTable = UInt8 ...
// access perm limit for subsequent levels
obj.xnTable = Bool ...
// XN limit for subsequent levels
obj.pxnTable = Bool ...
// PXN limit for subsequent levels
obj.noExecute = Bool ...
// execute-never bit
obj.privNoExecute = Bool ...
// privileged execute-never bit
obj.contiguous = Bool ...
// hint bit indicating 16 adjacent table
entries point to contiguos memory
obj.notGlobal = Bool ...
// not global bit
obj.accessFlag = Bool ...
// access flag
obj.shareable = UInt8 ...
// shareability field value 0-3
obj.accPerm = UInt8 ...
// access permission bits value 0-3
obj.nonSecure = Bool ...
// non-secure bit
obj.attrIndx = UInt8 ...
// stage 1 memory attributes index field for
the indicated MAIRn register value 0-7
obj.reserved = UInt8 ...
// Bits[58:55] reserved for software use
DETAILS
nsTable, apTable, xnTable and pxnTable fields are used only for
DescriptorType.TABLE
noExecute, privNoExecute, contiguous, notGlobal, accessFlag, shareable,
accPerm, nonSecure and attrIndx fields are used only for
DescriptorType.BLOCK
C SYNOPSIS
config Mmu.A_nullPointer // module-wide |
|
Assert raised when a pointer is null
msg: "A_nullPointer: Pointer is null"
};
C SYNOPSIS
config Mmu.A_unknownDescType // module-wide |
|
Assert raised when the descriptor type is not recognized
msg: "A_unknownDescType: Descriptor type is not recognized"
};
C SYNOPSIS
config Mmu.defaultAttrs // module-wide |
|
default descriptor attributes structure
nsTable: false,
apTable: 0,
xnTable: false,
pxnTable: false,
noExecute: false,
privNoExecute: false,
contiguous: false,
notGlobal: false,
accessFlag: true,
shareable: 0,
accPerm: 0,
nonSecure: false,
attrIndx: 0,
reserved: 0
};
C SYNOPSIS
config Mmu.enableMMU // module-wide |
|
Configuration parameter to enable MMU
Mmu.enableMMU = Bool true;
C SYNOPSIS
metaonly config Mmu.cachePlatformMemory // module-wide |
|
Flag to automatically mark platform's code/data/stack memory as
cacheable in MMU descriptor table
Mmu.cachePlatformMemory = Bool true;
DETAILS
By default, all memory regions defined in the platform an
application is built with are marked as cacheable.
If manual configuration of memory regions is required, set
this config parameter to 'false'.
SEE
metaonly config Mmu.common$ // module-wide |
|
Common module configuration parameters
DETAILS
All modules have this configuration parameter. Its name
contains the '$' character to ensure it does not conflict with
configuration parameters declared by the module. This allows
new configuration parameters to be added in the future without
any chance of breaking existing modules.
metaonly config Mmu.rovViewInfo // module-wide |
|
metaonly Mmu.initDescAttrsMeta() // module-wide |
|
Initializes the descriptor attribute structure
ARGUMENTS
attrs
Pointer to descriptor attribute struct
metaonly Mmu.setFirstLevelDescMeta() // module-wide |
|
Statically sets the descriptor for the virtual address
Mmu.
setFirstLevelDescMeta(
Ptr virtualAddr,
UInt64 phyAddr,
Mmu.DescriptorAttrs attrs)
returns Void
ARGUMENTS
virtualAddr
The modified virtual address
phyAddr
The physical address
attrs
Pointer to first level descriptor attribute struct
DETAILS
The first level table entry for the virtual address is mapped
to the physical address with the attributes specified. The
descriptor table is effective when the MMU is enabled.
SEE
metaonly Mmu.setMAIRMeta() // module-wide |
|
Statically sets the memory attribute encoding in the MAIRn register
Mmu.setMAIRMeta(UInt attrIndx, UInt attr) returns Void
ARGUMENTS
attrIndx
Select appropriate MAIR register (0 or 1)
and byte offset within selected register
attr
Memory attribute encoding
DETAILS
MAIR0 and MAIR1 provide the memory attribute encodings to the possible
attrIndx values in a Long-descriptor format
translation table entry for stage 1 translations (see
setMAIR
for more details).
metaonly Mmu.setSecondLevelDescMeta() // module-wide |
|
Statically sets the descriptor for the virtual address
Mmu.
setSecondLevelDescMeta(
Ptr virtualAddr,
UInt64 phyAddr,
Mmu.DescriptorAttrs attrs)
returns Void
ARGUMENTS
virtualAddr
The modified virtual address
phyAddr
The physical address
attrs
Pointer to second level descriptor attribute struct
DETAILS
The second level table entry for the virtual address is mapped
to the physical address with the attributes specified. The
descriptor table is effective when the MMU is enabled.
SEE
generated on Sat, 21 Dec 2013 00:08:55 GMT