1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 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")
321 @DirectCall
322
323 module Mmu
324 {
325 const UInt NUM_LEVEL1_ENTRIES = 4;
326
327 const UInt NUM_LEVEL2_ENTRIES = 512;
328
329
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,
446 nsTable: false,
447 apTable: 0,
448 xnTable: false,
449 pxnTable: false,
450 noExecute: false,
451 privNoExecute: false,
452 contiguous: false, 453
454 notGlobal: false,
455 accessFlag: true,
456 shareable: 0,
457 accPerm: 0,
458 nonSecure: false,
459 attrIndx: 0, 460
461 reserved: 0
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 886
887 UInt64 firstLevelTableBuf[];
888
889 890 891
892 UInt64 secondLevelTableBuf[NUM_LEVEL1_ENTRIES][];
893
894 895 896
897 volatile UInt mairRegAttr[8];
898 }
899 }