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.c7x;
37
38 /*!
39 * ======== Mmu ========
40 * Memory Management Unit (MMU) Manager
41 *
42 * This module allows the C7x processor to map a 64-bit virtual address
43 * to a 48-bit physical address and enable/disable the MMU. It does this
44 * through translation tables in memory.
45 *
46 * Every application must register a Mmu init function (see {@link #initFunc})
47 * that contains calls to Mmu_map() to configure the MMU.
48 *
49 * *.cfg:
50 * @p(code)
51 * var Mmu = xdc.useModule('ti.sysbios.family.c7x.Mmu');
52 * Mmu.initFunc = "&Mmu_initFuncDefault";
53 * @p
54 *
55 * Example {@link #initFuncDefault Mmu_initFuncDefault()} provided
56 * function for J7 devices:
57 * @p(code)
58 * ...
59 *
60 * Void Mmu_initFuncDefault()
61 * {
62 * Bool ret;
63 * Mmu_MapAttrs attrs;
64 *
65 * Mmu_initMapAttrs(&attrs);
66 *
67 * // MAIR0 has a default memory type that is non-gathering and
68 * // non-reordering with no early write acknowledegement property.
69 * // In other words, strongly ordered memory type.
70 * attrs.attrIndx = Mmu_AttrIndx_MAIR0;
71 *
72 * // Map GICv3 registers
73 * ret = Mmu_map(0x01800000, 0x01800000, 0x00100000, &attrs);
74 * if (!ret) {
75 * goto fail;
76 * }
77 *
78 * // Map DMTimer registers
79 * ret = Mmu_map(0x02400000, 0x02400000, 0x000c0000, &attrs);
80 * if (!ret) {
81 * goto fail;
82 * }
83 *
84 * // Map UART registers
85 * ret = Mmu_map(0x02800000, 0x02800000, 0x00001000, &attrs);
86 * if (!ret) {
87 * goto fail;
88 * }
89 *
90 * // Map System Timer registers
91 * ret = Mmu_map(0x2A430000, 0x2A430000, 0x00001000, &attrs);
92 * if (!ret) {
93 * goto fail;
94 * }
95 *
96 * // MAIR7 has a default attribute type of Inner and Outer
97 * // write-back cacheable
98 * attrs.attrIndx = Mmu_AttrIndx_MAIR7;
99 *
100 * //Map MSMC SRAM
101 * ret = Mmu_map(0x70000000, 0x70000000, 0x00200000, &attrs);
102 * if (!ret) {
103 * goto fail;
104 * }
105 *
106 * return;
107 *
108 * fail:
109 * System_printf("Mmu config failed.\n");
110 * while (1);
111 * }
112 *
113 * @p
114 */
115
116 @DirectCall
117 @Template ("./Mmu.xdt")
118
119 module Mmu
120 {
121 const UInt8 PA_MAX_WIDTH = 48;
122
123 124 125
126 const UInt8 PA_SIZE_ENCODING = 0x5;
127
128
129
130
131
132 /*!
133 * ======== AttrIndx ========
134 * Memory attribute register (MAIR) index
135 *
136 * SYS/BIOS defines default values for MAIR register. See {@link #MAIR0},
137 * {@link #MAIR1}, {@link #MAIR2}, {@link #MAIR3}, {@link #MAIR4},
138 * {@link #MAIR5}, {@link #MAIR6} & {@link #MAIR7} for more info on the
139 * memory type defined by each MAIR register.
140 */
141 enum AttrIndx {
142 AttrIndx_MAIR0 = 0,
143 AttrIndx_MAIR1,
144 AttrIndx_MAIR2,
145 AttrIndx_MAIR3,
146 AttrIndx_MAIR4,
147 AttrIndx_MAIR5,
148 AttrIndx_MAIR6,
149 AttrIndx_MAIR7
150 };
151
152 /*!
153 * @_nodoc
154 * ======== DescriptorType ========
155 * Different descriptor type encodings:
156 * @p(blist)
157 * - Invalid or Fault entry (0b00 or 0b10)
158 * - Block descriptor entry (0b01)
159 * - Table descriptor entry (0b11)
160 * @p
161 */
162 enum DescriptorType {
163 DescriptorType_INVALID0 = 0, /*! Virtual address is unmapped */
164 DescriptorType_BLOCK = 1, /*! Block descriptor */
165 DescriptorType_INVALID1 = 2, /*! Virtual address is unmapped */
166 DescriptorType_TABLE = 3 /*! Next-level table address */
167 };
168
169 /*!
170 * ======== GranuleSize ========
171 * Memory translation {@link #granuleSize} granule size
172 */
173 enum GranuleSize {
174 GranuleSize_4KB = 0x1000,
175 GranuleSize_16KB = 0x4000,
176 GranuleSize_64KB = 0x10000
177 };
178
179 /*!
180 * ======== Shareable ========
181 * Shareability attribute
182 */
183 enum Shareable {
184 Shareable_NONE = 0x0,
185 Shareable_OUTER = 0x2,
186 Shareable_INNER = 0x3
187 };
188
189 /*!
190 * ======== AccessPerm ========
191 * Access Permissions
192 */
193 enum AccessPerm {
194 AccessPerm_PRIV_RW_USER_NONE = 0x0, 195
196 AccessPerm_PRIV_RW_USER_RW = 0x1, 197
198 AccessPerm_PRIV_RO_USER_NONE = 0x2, 199
200 AccessPerm_PRIV_RO_USER_RO = 0x3 201
202 };
203
204 /*! Mmu init function type definition. */
205 typedef Void (*InitFuncPtr)(void);
206
207 /*!
208 * ======== MapAttrs ========
209 * Structure containing attributes for memory map entry
210 */
211 struct MapAttrs {
212 AccessPerm accessPerm; /*! privileged & user access permissions */
213 Bool privExecute; /*! privileged execute permission */
214 Bool userExecute; /*! user execute permission */
215 Shareable shareable; /*! shareability field value 0-3 */
216 AttrIndx attrIndx; /*! stage 1 memory attributes index field
217 for the indicated MAIRn reg value 0-7 */
218 Bool global; /*! global mmu entry ? (used by kernel
219 when memory protection extensions are
220 enabled) */
221 };
222
223
224
225 /*!
226 * ======== A_nullPointer ========
227 * Assert raised when a pointer is null
228 */
229 config xdc.runtime.Assert.Id A_nullPointer = {
230 msg: "A_nullPointer: Pointer is null"
231 };
232
233 /*!
234 * ======== A_vaddrOutOfRange ========
235 * Assert raised when virtual address passed is out of range
236 */
237 config xdc.runtime.Assert.Id A_vaddrOutOfRange = {
238 msg: "A_vaddrOutOfRange: Virtual address is out of range"
239 };
240
241 /*!
242 * ======== A_paddrOutOfRange ========
243 * Assert raised when physical address passed is out of range
244 */
245 config xdc.runtime.Assert.Id A_paddrOutOfRange = {
246 msg: "A_paddrOutOfRange: Physical address is out of range"
247 };
248
249 /*!
250 * ======== A_unalignedVaddr ========
251 * Assert raised if unaligned virtual address passed to Mmu_map().
252 */
253 config xdc.runtime.Assert.Id A_unalignedVaddr =
254 {msg: "A_unalignedVaddr: Virtual address not page aligned"};
255
256 /*!
257 * ======== A_unalignedPaddr ========
258 * Assert raised if unaligned physical address passed to Mmu_map().
259 */
260
261 config xdc.runtime.Assert.Id A_unalignedPaddr =
262 {msg: "A_unalignedPaddr: Physical address not page aligned"};
263
264 /*!
265 * ======== A_unalignedSize ========
266 * Assert raised if unaligned size passed to Mmu_map().
267 */
268 config xdc.runtime.Assert.Id A_unalignedSize =
269 {msg: "A_unalignedSize: Mmu mapping size not page aligned"};
270
271 /*!
272 * ======== defaultMapAttrs ========
273 * default descriptor attributes structure
274 */
275 config MapAttrs defaultMapAttrs = {
276 accessPerm: AccessPerm_PRIV_RW_USER_NONE,
277 privExecute: true,
278 userExecute: false,
279 shareable: Shareable_OUTER,
280 attrIndx: AttrIndx_MAIR0,
281 global: true
282 };
283
284 /*!
285 * ======== enableMMU ========
286 * Configuration parameter to enable MMU.
287 */
288 config Bool enableMMU = true;
289
290 /*!
291 * ======== granuleSize ========
292 * Memory translation granule size. Default is 4KB.
293 *
294 * The granule size determines the smallest page size that can be
295 * mapped with the MMU.
296 */
297 config GranuleSize granuleSize = GranuleSize_4KB;
298
299 /*!
300 * ======== MAIR0 ========
301 * Memory attribute 0.
302 *
303 * Default is memory with non-gathering, non-reordering and no early write
304 * acknowledegement property.
305 */
306 config UInt8 MAIR0 = 0x00;
307
308 /*!
309 * ======== MAIR1 ========
310 * Memory attribute 1
311 *
312 * Default is memory with non-gathering, non-reordering and early write
313 * acknowledegement property.
314 */
315 config UInt8 MAIR1 = 0x04;
316
317 /*!
318 * ======== MAIR2 ========
319 * Memory attribute 2
320 *
321 * Default is memory with non-gathering, reordering and early write
322 * acknowledegement property.
323 */
324 config UInt8 MAIR2 = 0x08;
325
326 /*!
327 * ======== MAIR3 ========
328 * Memory attribute 3
329 *
330 * Default is memory with gathering, reordering and early write
331 * acknowledegement property.
332 */
333 config UInt8 MAIR3 = 0x0C;
334
335 /*!
336 * ======== MAIR4 ========
337 * Memory attribute 4
338 *
339 * Default is normal inner & outer non-cacheable memory.
340 */
341 config UInt8 MAIR4 = 0x44;
342
343 /*!
344 * ======== MAIR5 ========
345 * Memory attribute 5
346 *
347 * Default is normal outer non-cacheable, inner write-back cacheable
348 * non-transient memory.
349 */
350 config UInt8 MAIR5 = 0x4F;
351
352 /*!
353 * ======== MAIR6 ========
354 * Memory attribute 6
355 *
356 * Default is normal outer & inner write-through cacheable non-transient
357 * memory.
358 */
359 config UInt8 MAIR6 = 0xBB;
360
361 /*!
362 * ======== MAIR7 ========
363 * Memory attribute 7
364 *
365 * Default is normal outer and inner write-back cacheable non-transient
366 * memory.
367 */
368 config UInt8 MAIR7 = 0x7D;
369
370 /*!
371 * ======== initFunc ========
372 * MMU init function pointer
373 *
374 * This config param is initialized to point to an init function that
375 * will perform MMU configuration using the {@link #map} runtime APIs
376 * provided by this module. The init function is called before
377 * C initialization i.e. before the data section is initialized.
378 * Therefore, care must be taken to not rely on any initialized
379 * data variables.
380 *
381 * By default, the {@link #initFuncDefault Mmu_initFuncDefault} function
382 * designed for use with AM65x devices is used if the application doesn't
383 * provide its own implementation.
384 */
385 config InitFuncPtr initFunc = initFuncDefault;
386
387 /*!
388 * ======== tableArraySection ========
389 * Contains a table array and some state variables.
390 * This section is uninitialized.
391 *
392 * Note: Memory containing the table array must be marked as inner &
393 * and outer shareable, and inner and outer write-back write-allocate
394 * cacheable.
395 */
396 metaonly config String tableArraySection =
397 ".data.ti_sysbios_family_c7x_Mmu_tableArray";
398
399 /*!
400 * ======== tableArrayLen ========
401 * Length of array of MMU tables
402 *
403 * MMU module allocates memory for MMU table from a table array.
404 * This config param controls number of MMU tables supported.
405 * Each table in the array is the size of the MMU table and aligned
406 * to the table's size.
407 *
408 * @a(Note)
409 * MMU table size is same as translation granule size (see
410 * {@link #granuleSize})
411 */
412 config UInt tableArrayLen = 16;
413
414 /*!
415 * ======== enable ========
416 * Enables the MMU.
417 *
418 * If the MMU is already enabled, then simply return.
419 * Otherwise this function does the following:
420 * @p(blist)
421 * If the L1 program cache is enabled, invalidate all of L1
422 * program cache.
423 * @p
424 *
425 * This function enables the MMU on the core it is called from.
426 *
427 * @a(Note)
428 * This function does not change the L1 data/program cache settings.
429 */
430 Void enable();
431
432 /*!
433 * ======== initMapAttrs() ========
434 * Initializes the map attribute structure
435 *
436 * @param(attrs) Pointer to map attribute struct
437 */
438 Void initMapAttrs(MapAttrs *descAttrs);
439
440 /*!
441 * ======== isEnabled ========
442 * Determines if the MMU is enabled
443 */
444 Bool isEnabled();
445
446 /*!
447 * ======== map ========
448 * Add a mapping to MMU table
449 *
450 * This API adds a mapping for the given virtual and physical
451 * address to the MMU table and sets the memory attributes
452 * as per the attributes passed to the function.
453 *
454 * This API internally disables interrupts before updating the
455 * MMU table. The interrupts may be disabled for a long period
456 * of time. It is therefore recommended to either call this
457 * API in the Mmu.initFunc or in main().
458 *
459 * The smallest mapping size (page size) supported is determined
460 * by the {@link #granuleSize}. The largess mapping size supported
461 * is 2^{@link #PA_MAX_WIDTH}-1.
462 *
463 * @param(vaddr) Virtual address (aligned to {@link #granuleSize})
464 * @param(paddr) Physical address (aligned to {@link #granuleSize})
465 * @param(size) Region size (aligned to {@link #granuleSize})
466 * @param(attrs) Memory region attributes
467 * @b(returns) Status (True-success, False-failed)
468 */
469 Bool map(UInt64 vaddr, UInt64 paddr, SizeT size, MapAttrs *attrs);
470
471 /*!
472 * ======== setMAIR ========
473 * Sets the memory attribute encoding in the MAIRn register.
474 *
475 * MAIR provides the memory attribute encodings to the possible
476 * {@link #DescriptorAttrs attrIndx} values in a long-descriptor format
477 * translation table entry for stage 1 translations.
478 *
479 * {@link #DescriptorAttrs attrIndx}[2:0] selects the ATTRn bit-field in
480 * the MAIR register.
481 *
482 * Memory Attribute Indirection Register (MAIR) bit assignments:
483 * @p(code)
484 * --------------------------------------------------------------
485 * |63 | 56|55 | 48|47 | 40|39 | 32|
486 * --------------------------------------------------------------
487 * MAIR | ATTR7 | ATTR6 | ATTR5 | ATTR4 |
488 * --------------------------------------------------------------
489 * |31 | 24|23 | 16|15 | 8|7 | 0|
490 * --------------------------------------------------------------
491 * MAIR | ATTR3 | ATTR2 | ATTR1 | ATTR0 |
492 * --------------------------------------------------------------
493 * @p
494 *
495 * SYS/BIOS has 8 MAIR config params (MAIR0, MAIR2, ...) that are
496 * initialized to default value. In order to have a custom memory
497 * attribute, a user can either change the MAIRn config param in
498 * the application's cfg script or call this runtime API.
499 *
500 * For more details on MAIR encodings please refer
501 * {@link https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile v8A ARM Architecture Reference Manual}
502 *
503 * @param(attrIndx) Memory attribute index
504 * @param(attr) Memory attribute encoding
505 *
506 * @a(Note)
507 * This function only invalidates the TLB and does not flush the cache.
508 * If the cacheability attribute of a region of memory is changed by
509 * modifying the MAIR entry for the region, the application needs to
510 * flush and invalidate the region of memory from the cache.
511 */
512 Void setMAIR(UInt8 attrIndx, UInt8 attr);
513
514 /*!
515 * @_nodoc
516 * ======== startup ========
517 * startup function to initialize MMU module
518 */
519 Void startup();
520
521 /*!
522 * ======== tlbInvAll ========
523 * Invalidate entire TLB (both data and instruction)
524 */
525 Void tlbInvAll(UInt64 type);
526
527 /*!
528 * ======== initFuncDefault ========
529 * default Mmu.initFunc implementation.
530 *
531 * provides Mmu regions for the AM65x's GIC, DMTimer, UART, SYSTIMER,
532 * and MSMC memory.
533 */
534 Void initFuncDefault();
535
536 internal:
537
538 539 540
541 struct ConfigInfo {
542 UInt64 indexMask;
543 UInt32 tableLength;
544 UInt8 tableOffset[4];
545 UInt8 granuleSizeBits;
546 UInt8 indexBits;
547 Bool noLevel0Table;
548 };
549
550 551 552
553 Void disable();
554
555 556 557
558 Void disableI();
559
560 561 562
563 Void enableI();
564
565 566 567 568 569 570
571 config ConfigInfo configInfo;
572
573 574 575
576 Void addBlockEntry(UInt8 level, UInt64 *tablePtr, UInt16 tableIdx,
577 UInt64 paddr, MapAttrs *attrs);
578
579 580 581
582 UInt64* addTableEntry(UInt64 *tablePtr, UInt16 tableIdx, MapAttrs *attrs);
583
584 585 586
587 UInt64* allocTable();
588
589 590 591
592 Void freeTable(UInt64 *table);
593
594 595 596
597 Void init(Ptr tableAddr);
598
599 600 601
602 Void readBlockEntry(UInt8 level, UInt64 *tablePtr, UInt16 tableIdx,
603 UInt64 *paddr, MapAttrs *attrs);
604
605 606 607
608 Void setMAIRAsm(UInt8 attrIndx, UInt8 attr);
609
610 611 612
613 Bool tableWalk(UInt8 level, UInt64 *tablePtr, UInt64 *vaddr, UInt64 *paddr,
614 SizeT *size, MapAttrs *attrs);
615
616 617 618
619 Void setTCR(UInt64 regVal);
620
621 /*! Module state */
622 struct Module_State {
623 }
624 }