This module allows the processor to map a virtual address to a
different physical address and enable/disable the MMU. It does this
through a translation table in memory. The translation table is
16KB and manages only the first level descriptor table. Each entry
in the table defines the memory translation of a page of size 1MB
(or 16MB if using supersections).
By default, the MMU translation table is initialized with
entries for every memory segment defined in the platform.
Entries are also added for the peripheral addresses used by
SYS/BIOS (i.e. Timers, Interrupt controller).
The translation table is placed in
an output section called "ti.sysbios.family.shared.vayu.mmuTableSection".
This section is 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 second level descriptor tables.
A 'SECTION' mapped access requires only a first level fetch. In
this case, there is no need for a second level descriptor table.
A 'PAGE_TABLE' mapped access requires a second level
descriptor table which can be supplied by the user.
The following is an example of how to place the MMU table
for the address range 0x80000000-0x90000000 in the *.cfg file:
var Mmu = xdc.useModule('ti.sysbios.family.shared.vayu.Mmu');
// Enable the MMU
Mmu.enableMMU = true;
// descriptor attribute structure
var attrs = {
type: Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
supersection: false
};
// Set the descriptor for each entry in the address range
for (var i=0x80000000; i < 0x90000000; i = i + 0x00100000) {
// Each 'SECTION' descriptor entry spans a 1MB address range
Mmu.setFirstLevelDescMeta(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.shared.vayu.mmuTableSection";
Program.sectMap[sectionName] = new Program.SectionSpec();
Program.sectMap[sectionName].type = "NOINIT"; // NOLOAD for GNU Tools
Program.sectMap[sectionName].loadSegment = "DDR";
}
else {
print("No DDR memory segment was found");
}
#include <ti/sysbios/family/shared/vayu/Mmu.h>
Int main()
{
Int i, j;
Bool ret;
// Add and lock 16 TLB entries. Once the entries are locked, they
// cannot be evicted by the table walking logic when the MMU is enabled.
for (i = 0x90000000, j = 0; j < 16; i+= 0x1000, j++) {
ret = Mmu_writeTLBEntry((Ptr)i, (Ptr)i, Mmu_PageSize_SMALL);
if (!ret) {
// FAILED: Could not lock TLB entry. TLB is full with locked
// entries.
...
}
}
...
BIOS_start();
}
#include <ti/sysbios/family/shared/vayu/Mmu.h>
Int func()
{
Int i, j;
// Unlock all TLB entries by setting locked entries base value to 0
Mmu_setTLBLockBaseValue(0);
// Clear (or flush) TLB entries pointed to by given virtual address.
for (i = 0x90000000, j = 0; j < 16; i+= 0x1000, j++) {
Mmu_clearTLBEntry((Ptr)i);
}
...
}
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/family/shared/vayu/Mmu.h>
#define MMU_LEVEL2DESC_LARGEPAGE 0x1
#define MMU_LEVEL2DESC_SMALLPAGE 0x2
#pragma DATA_ALIGN(mmuL2Table, 4096); // align to 4KB
UInt32 mmuL2Table[256];
Void main(Int argc, Char * argv[])
{
Mmu_FirstLevelDescAttrs attrs;
Int i, j;
// initialize the second level descriptors
for (i = 0x80000000, j = 0; j < 256; i+= 0x1000, j++) {
mmuL2Table[j] = (i & 0xFFFFF000) | MMU_LEVEL2DESC_SMALLPAGE;
// For large pages use below line instead:
// mmuL2Table[j] = (i & 0xFFFF0000) | MMU_LEVEL2DESC_LARGEPAGE;
}
// first level descriptor properites
Mmu_initDescAttrs(&attrs);
attrs.type = Mmu_FirstLevelDesc_PAGE_TABLE; // set to a page table descriptor
// Set the first level descriptor for the virtual address 0x80000000.
// No need to disable the MMU. The API should internally disable and
// re-enable it.
Mmu_setFirstLevelDesc((Ptr)0x80000000, &mmuL2Table, &attrs);
BIOS_start();
}
...
enum Mmu_FirstLevelDesc |
|
First Level descriptors
typedef enum Mmu_FirstLevelDesc {
Mmu_FirstLevelDesc_FAULT,
// Virtual address is unmapped
Mmu_FirstLevelDesc_PAGE_TABLE,
// Page table addr descriptor
Mmu_FirstLevelDesc_SECTION
// Section descriptor
} Mmu_FirstLevelDesc;
DETAILS
Different descriptor type encodings:
0b00 -> Invalid or Fault entry
0b01 -> Page table entry
0b10 -> Section descriptor
enum Mmu_PageSize |
|
Page size
typedef enum Mmu_PageSize {
Mmu_PageSize_SECTION,
// Section (1 MB)
Mmu_PageSize_LARGE,
// Large page (64 KB)
Mmu_PageSize_SMALL,
// Small page (4 KB)
Mmu_PageSize_SUPERSECTION
// Supersection (16 MB)
} Mmu_PageSize;
struct Mmu_FirstLevelDescAttrs |
|
Structure for setting first level descriptor entries
typedef struct Mmu_FirstLevelDescAttrs {
// first level descriptor type
Bool supersection;
// is a supersection
} Mmu_FirstLevelDescAttrs;
DETAILS
See the 'Memory Management Units' section of the device TRM for
more details.
config Mmu_A_baseValueOutOfRange // module-wide |
|
Assert raised when TLB lock entries base value out of range
extern const Assert_Id Mmu_A_baseValueOutOfRange;
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_baseAddr // module-wide |
|
MMU base address
DETAILS
If not specified, will be automatically set at runtime.
config Mmu_defaultAttrs // module-wide |
|
default descriptor attributes structure
config Mmu_enableMMU // module-wide |
|
Configuration parameter to enable MMU
extern const Bool Mmu_enableMMU;
config Mmu_numTLBEntries // module-wide |
|
Number of TLB Cache entries
extern const UInt Mmu_numTLBEntries;
Mmu_clearTLBEntry() // module-wide |
|
Clears (or flushes) a TLB entry
Void Mmu_clearTLBEntry(Ptr virtualAddr);
ARGUMENTS
virtualAddr
The modified virtual Address
DETAILS
This function flushes all TLB entries (including protected
entries) pointed to by the given virtual address. It can be
used to delete a TLB entry after it has been unlocked.
NOTE
This API internally disables and re-enables the MMU.
Since the MMU hardware does not permit disabling the MMU
while an interrupt is pending, this API should not be called
with any interrupts still pending.
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. This function does not
change the cache L1 data/program settings. If the L2 unified
cache is enabled, it is written back and invalidated.
This function also disables the table walking logic and
performs a global TLB flush. The global TLB flush does not
affect protected TLB entries.
NOTE
The MMU hardware does not permit disabling the MMU
while an interrupt is pending. If this API is called with
an interrupt still pending, the MMU will generate an error.
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. This function does not change the L1
data/program cache settings. If the L2 unified cache is
enabled, it is written back and invalidated.
This function also explicitly enables the table walking
logic and performs a global TLB flush. The global TLB
flush does not affect protected TLB entries.
Mmu_initDescAttrs() // module-wide |
|
Initializes the first level descriptor attribute structure
ARGUMENTS
attrs
Pointer to first level 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.
NOTE
This API internally disables and re-enables the MMU.
Since the MMU hardware does not permit disabling the MMU
while an interrupt is pending, this API should not be called
with any interrupts still pending. It is recommended to
call this function from within main() before calling
BIOS_start().
Mmu_setTLBLockBaseValue() // module-wide |
|
Sets the TLB locked entries base value to the given value
Void Mmu_setTLBLockBaseValue(UInt basevalue);
ARGUMENTS
basevalue
TLB locked entries base value
DETAILS
First n TLB entries (with n < total number of TLB entries) can be
protected from being overwritten with new translations. n is equal
to the TLB locked entries base value.
This function can be used to unlock TLB entries. Once an
entry is unlocked, it can be cleared using
clearTLBEntry()
function.
NOTE
This API internally disables and re-enables the MMU.
Since the MMU hardware does not permit disabling the MMU
while an interrupt is pending, this API should not be called
with any interrupts still pending.
Mmu_writeTLBEntry() // module-wide |
|
Manually adds a TLB entry and locks it
Bool Mmu_writeTLBEntry(
Ptr virtualAddr,
Ptr physicalAddr,
Mmu_PageSize size);
ARGUMENTS
virtualAddr
The modified virtual address
phyAddr
The physical address
size
TLB page size.
RETURNS
TRUE - Entry succesfully written and locked, OR,
FALSE - Write failed. No free TLB entries.
DETAILS
This function ready the TLB lock base value and uses it to
select a victim TLB entry to write to. Once the new TLB
entry is written, it increments the TLB lock base value to
lock the entry. The TLB entries added using this function
are marked as protected and therefore are not affected by
global TLB flush operations.
NOTE
Due to the mechanism used to lock TLB entries, it is
not possible to unlock a random locked TLB entry. All TLB
entries in front need to be unlocked first. For example,
if the first 4 TLB entries (i.e. TLB index 0, 1, 2 & 3) are
locked and the second TLB entry (i.e. TLB index 1) needs to
be unlocked, then the TLB entries with indices 1, 2 & 3
have to all be unlocked in order to unlock TLB entry
with index 1. This can be done by calling
setTLBLockBaseValue() function.
This API internally disables and re-enables the MMU.
Since the MMU hardware does not permit disabling the MMU
while an interrupt is pending, this API should not be called
with any interrupts still pending. It is recommended to
call this function from within main() before calling
BIOS_start().
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
enum Mmu.FirstLevelDesc |
|
First Level descriptors
values of type Mmu.FirstLevelDesc
const Mmu.FirstLevelDesc_FAULT;
// Virtual address is unmapped
const Mmu.FirstLevelDesc_PAGE_TABLE;
// Page table addr descriptor
const Mmu.FirstLevelDesc_SECTION;
// Section descriptor
DETAILS
Different descriptor type encodings:
0b00 -> Invalid or Fault entry
0b01 -> Page table entry
0b10 -> Section descriptor
C SYNOPSIS
enum Mmu.PageSize |
|
Page size
values of type Mmu.PageSize
const Mmu.PageSize_SECTION;
// Section (1 MB)
const Mmu.PageSize_LARGE;
// Large page (64 KB)
const Mmu.PageSize_SMALL;
// Small page (4 KB)
const Mmu.PageSize_SUPERSECTION;
// Supersection (16 MB)
C SYNOPSIS
struct Mmu.FirstLevelDescAttrs |
|
Structure for setting first level descriptor entries
var obj = new Mmu.FirstLevelDescAttrs;
// first level descriptor type
obj.supersection = Bool ...
// is a supersection
DETAILS
See the 'Memory Management Units' section of the device TRM for
more details.
C SYNOPSIS
config Mmu.A_baseValueOutOfRange // module-wide |
|
Assert raised when TLB lock entries base value out of range
msg: "A_baseValueOutOfRange: TLB lock entries base value out of range"
};
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.baseAddr // module-wide |
|
MMU base address
DETAILS
If not specified, will be automatically set at runtime.
C SYNOPSIS
config Mmu.defaultAttrs // module-wide |
|
default descriptor attributes structure
C SYNOPSIS
config Mmu.enableMMU // module-wide |
|
Configuration parameter to enable MMU
Mmu.enableMMU = Bool false;
C SYNOPSIS
config Mmu.numTLBEntries // module-wide |
|
Number of TLB Cache entries
Mmu.numTLBEntries = UInt 32;
C SYNOPSIS
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.setFirstLevelDescMeta() // module-wide |
|
Statically 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 or points to the level 2 descriptor
table. The descriptor table is effective when the MMU is enabled.