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.a8;
37
38 import xdc.rov.ViewInfo;
39
40 import xdc.runtime.Assert;
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 is initialized with
55 * cache-enabled entries for every memory segment defined in the platform.
56 * Cache-disabled entries are also added for the peripheral
57 * addresses used by SYS/BIOS (i.e. Timers, Interrupt controller).
58 *
59 * The translation table is placed in
60 * an output section called "ti.sysbios.family.arm.a8.mmuTableSection".
61 * This section is placed into the platform's default dataMemory and
62 * in order to minimize object file size, specified to not be initialized
63 * via the "NOLOAD" type on GNU compilers and "NOINIT" on TI compilers.
64 *
65 * This module does not manage the second level descriptor tables.
66 * A 'SECTION' mapped access requires only a first level fetch. In
67 * this case, there is no need for a second level descriptor table.
68 * A 'PAGE_TABLE' mapped access requires a second level
69 * descriptor table which can be supplied by the user.
70 *
71 * The following is an example of how to place the MMU table
72 * and how to enable L1 data + L2 caching for the address range
73 * 0x80000000-0x90000000 in the *.cfg file:
74 *
75 * @p(code)
76 *
77 * // For Cortex-A8
78 * var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
79 * // For Cortex-A9
80 * var Cache = xdc.useModule('ti.sysbios.family.arm.a9.Cache');
81 *
82 * var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
83 *
84 * // Enable the cache
85 * Cache.enableCache = true;
86 *
87 * // Enable the MMU (Required for L1/L2 data caching)
88 * Mmu.enableMMU = true;
89 *
90 * // descriptor attribute structure for marking the memory region
91 * // as normal cacheable memory (write-back and write-allocate)
92 * var attrs = {
93 * type: Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
94 * tex: 0x1,
95 * bufferable: true, // bufferable
96 * cacheable: true, // cacheable
97 * };
98 *
99 * // Set the descriptor for each entry in the address range
100 * for (var i=0x80000000; i < 0x90000000; i = i + 0x00100000) {
101 * // Each 'SECTION' descriptor entry spans a 1MB address range
102 * Mmu.setFirstLevelDescMeta(i, i, attrs);
103 * }
104 *
105 * var memmap = Program.cpu.memoryMap;
106 * var DDR = null;
107 *
108 * // Find DDR in memory map
109 * for (var i=0; i < memmap.length; i++) {
110 * if (memmap[i].name == "DDR") {
111 * DDR = memmap[i];
112 * }
113 * }
114 *
115 * // Place the MMU table in the DDR memory segment if it exists
116 * if (DDR != null) {
117 * var sectionName = "ti.sysbios.family.arm.a8.mmuTableSection";
118 * Program.sectMap[sectionName] = new Program.SectionSpec();
119 * Program.sectMap[sectionName].type = "NOLOAD"; // NOINIT for TI Tools
120 * Program.sectMap[sectionName].loadSegment = "DDR";
121 * }
122 * else {
123 * print("No DDR memory segment was found");
124 * }
125 *
126 * @p
127 *
128 * The following example demonstrates how to add a peripheral's address
129 * to the MMU table so that it can be accessed by code at runtime:
130 *
131 * @p(code)
132 * // For Cortex-A8
133 * var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
134 * // For Cortex-A9
135 * var Cache = xdc.useModule('ti.sysbios.family.arm.a9.Cache');
136 *
137 * var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
138 *
139 * // Enable the cache
140 * Cache.enableCache = true;
141 *
142 * // Enable the MMU (Required for L1/L2 data caching)
143 * Mmu.enableMMU = true;
144 *
145 * // Force peripheral section to be NON cacheable strongly-ordered memory
146 * var peripheralAttrs = {
147 * type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
148 * tex: 0,
149 * bufferable : false, // bufferable
150 * cacheable : false, // cacheable
151 * shareable : false, // shareable
152 * noexecute : true, // not executable
153 * };
154 *
155 * // Define the base address of the 1 Meg page
156 * // the peripheral resides in.
157 * var peripheralBaseAddr = 0xa0400000;
158 *
159 * // Configure the corresponding MMU page descriptor accordingly
160 * Mmu.setFirstLevelDescMeta(peripheralBaseAddr,
161 * peripheralBaseAddr,
162 * peripheralAttrs);
163 * @p
164 *
165 * @a(Memory region attributes)
166 * Memory regions can be configured as different memory types by setting
167 * the {@link #FirstLevelDescAttrs bufferable},
168 * {@link #FirstLevelDescAttrs cacheable} and {@link #FirstLevelDescAttrs tex}
169 * (type extension) fields of the {@link #FirstLevelDescAttrs} structure
170 * which is passed as an argument to {@link #setFirstLevelDesc}. The three
171 * memory types supported by the hardware are "Normal" (cacheable), "Device"
172 * and "Strongly-ordered" memory. "Device" and "Strongly-ordered" memory
173 * types are recommended for mapping peripheral address space like
174 * memory-mapped registers. These two types ensure that the memory accesses
175 * to the peripheral memory are not performed speculatively, are not repeated
176 * and are performed in order. The "Normal" memory type is recommended for
177 * mapping memory regions storing application code and data.
178 *
179 * Here are some common settings for the
180 * {@link #FirstLevelDescAttrs bufferable},
181 * {@link #FirstLevelDescAttrs cacheable} and {@link #FirstLevelDescAttrs tex}
182 * fields to define different memory region types:
183 *
184 * @p(code)
185 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
186 * + Memory Type | bufferable | cacheable | tex +
187 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
188 * + Shareable Strongly-ordered memory | false | false | 0 +
189 * +-----------------------------------------+------------+-----------+-----+
190 * + Shareable Device memory | true | false | 0 +
191 * +-----------------------------------------+------------+-----------+-----+
192 * + Outer & Inner Non-cacheable | false | false | 1 +
193 * +-----------------------------------------+------------+-----------+-----+
194 * + Outer & Inner Write-back Write-allocate | true | true | 1 +
195 * + cacheable | | | +
196 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
197 * @p
198 *
199 * For an exhaustive list of all different memory type settings and a
200 * detailed explanation of the memory region attributes, please read the
201 * 'Short-descriptor translation table format' section of the ARM v7-AR
202 * Architecture Reference Manual issue C.
203 *
204 * Notes:
205 * @p(blist)
206 * -The 'Supersection' table descriptor is NOT supported.
207 * -The 'not global' page descriptor setting is NOT supported.
208 * -The 'non-secure' page descriptor setting is NOT supported.
209 * -There are size and alignment requirements on the second
210 * level descriptor tables depending on the page size.
211 * -See the ARM Architecture Reference Manual for more info.
212 * @p
213 *
214 */
215
216 @Template ("./Mmu.xdt")
217 @ModuleStartup
218 @DirectCall
219
220 module Mmu
221 {
222
223
224 /*! @_nodoc */
225 metaonly struct PageView {
226 String Type;
227 String Tex;
228 Ptr AddrVirtual;
229 Ptr AddrPhysical;
230 Ptr Level2TablePtr;
231 Bool Bufferable;
232 Bool Cacheable;
233 Bool Shareable;
234 Bool Noexecute;
235 Bool NotGlobal;
236 String L1DWritePolicy;
237 UInt IMP;
238 UInt Domain;
239 String Access;
240 };
241
242 @Facet
243 metaonly config ViewInfo.Instance rovViewInfo =
244 ViewInfo.create({
245 viewMap: [
246 ['0x0-0x7FFFFFFF', {
247 type: ViewInfo.MODULE_DATA,
248 viewInitFxn: 'viewPages1',
249 structName: 'PageView'
250 }],
251 ['0x80000000-0x9FFFFFFF', {
252 type: ViewInfo.MODULE_DATA,
253 viewInitFxn: 'viewPages2',
254 structName: 'PageView'
255 }],
256 ['0xA0000000-0xBFFFFFFF', {
257 type: ViewInfo.MODULE_DATA,
258 viewInitFxn: 'viewPages3',
259 structName: 'PageView'
260 }],
261 ['0xC0000000-0xDFFFFFFF', {
262 type: ViewInfo.MODULE_DATA,
263 viewInitFxn: 'viewPages4',
264 structName: 'PageView'
265 }],
266 ['0xE0000000-0xFFFFFFFF', {
267 type: ViewInfo.MODULE_DATA,
268 viewInitFxn: 'viewPages5',
269 structName: 'PageView'
270 }]
271 ]
272 });
273
274 /*!
275 * First Level descriptors
276 *
277 * Different descriptor type encodings:
278 * 0b00 -> Invalid or Fault entry
279 * 0b01 -> Page table entry
280 * 0b10 -> Section descriptor
281 * 0b11 -> Reserved
282 */
283 enum FirstLevelDesc {
284 FirstLevelDesc_FAULT = 0, /*! Virtual address is unmapped */
285 FirstLevelDesc_PAGE_TABLE = 1, /*! Page table addr descriptor */
286 FirstLevelDesc_SECTION = 2, /*! Section descriptor */
287 FirstLevelDesc_RESERVED = 3 /*! Reserved */
288 };
289
290 /*!
291 * Structure for setting first level descriptor entries
292 *
293 * The B (Bufferable), C (Cacheable), and TEX (Type extension) bits
294 * in the translation table descriptor define the memory region
295 * attributes.
296 *
297 * See the 'Short-descriptor translation table format' section of the
298 * ARM v7-AR Architecture Reference Manual issue C for more details.
299 */
300 struct FirstLevelDescAttrs {
301 FirstLevelDesc type; /*! first level descriptor type */
302 Bool bufferable; /*! is memory section bufferable */
303 Bool cacheable; /*! is memory section cacheable */
304 Bool shareable; /*! is memory section shareable */
305 Bool noexecute; /*! is memory section not executable */
306 UInt8 imp; /*! implementation defined */
307 UInt8 domain; /*! domain access control value 0-15 */
308 UInt8 accPerm; /*! access permission bits value 0-7 */
309 UInt8 tex; /*! memory region attr type extension field */
310 Bool notGlobal; /*! not global bit */
311 };
312
313
314
315 /*!
316 * ======== A_nullPointer ========
317 * Assert raised when a pointer is null
318 */
319 config Assert.Id A_nullPointer = {
320 msg: "A_nullPointer: Pointer is null"
321 };
322
323 /*!
324 * ======== A_unknownDescType ========
325 * Assert raised when the descriptor type is not recognized.
326 */
327 config Assert.Id A_unknownDescType = {
328 msg: "A_unknownDescType: Descriptor type is not recognized"
329 };
330
331 /*! default descriptor attributes structure */
332 config FirstLevelDescAttrs defaultAttrs = {
333 type: FirstLevelDesc_SECTION,
334 bufferable: false,
335 cacheable: false,
336 shareable: false,
337 noexecute: false,
338 imp: 1,
339 domain: 0,
340 accPerm: 3,
341 tex: 1,
342 notGlobal: false
343 };
344
345 /*!
346 * ======== enableMMU ========
347 * Configuration parameter to enable MMU.
348 */
349 config Bool enableMMU = true;
350
351 /*!
352 * ======== cachePlatformMemory ========
353 * Flag to automatically mark platform's code/data/stack memory as
354 * cacheable in MMU descriptor table
355 *
356 * By default, all memory regions defined in the platform an
357 * application is built with are marked as cacheable.
358 *
359 * @see xdc.bld.Program#platform
360 *
361 * If manual configuration of memory regions is required, set
362 * this config parameter to 'false'.
363 */
364 metaonly config Bool cachePlatformMemory = true;
365
366 /*!
367 * ======== setFirstLevelDescMeta ========
368 * Statically sets the descriptor for the virtual address.
369 *
370 * The first level table entry for the virtual address is mapped
371 * to the physical address with the attributes specified. The
372 * descriptor table is effective when the MMU is enabled.
373 *
374 * @param(virtualAddr) The modified virtual address
375 * @param(phyAddr) The physical address
376 * @param(attrs) Pointer to first level descriptor attribute struct
377 */
378 metaonly Void setFirstLevelDescMeta(Ptr virtualAddr, Ptr phyAddr,
379 FirstLevelDescAttrs attrs);
380
381 /*!
382 * ======== disable ========
383 * Disables the MMU.
384 *
385 * If the MMU is already disabled, then simply return.
386 * Otherwise this function does the following:
387 * If the L1 data cache is enabled, write back invalidate all
388 * of L1 data cache. If the L1 program cache is enabled,
389 * invalidate all of L1 program cache. This function does not
390 * change the cache L1 data/program settings.
391 */
392 Void disable();
393
394 /*!
395 * ======== enable ========
396 * Enables the MMU.
397 *
398 * If the MMU is already enabled, then simply return.
399 * Otherwise this function does the following:
400 * If the L1 program cache is enabled, invalidate all of L1
401 * program cache. This function does not change the L1
402 * data/program cache settings.
403 */
404 Void enable();
405
406 /*!
407 * ======== initDescAttrs() ========
408 * Initializes the first level descriptor attribute structure
409 *
410 * @param(attrs) Pointer to first level descriptor attribute struct
411 */
412 Void initDescAttrs(FirstLevelDescAttrs *attrs);
413
414 /*!
415 * ======== isEnabled ========
416 * Determines if the MMU is enabled
417 */
418 Bool isEnabled();
419
420 /*!
421 * ======== setFirstLevelDesc ========
422 * Sets the descriptor for the virtual address.
423 *
424 * The first level table entry for the virtual address is mapped
425 * to the physical address with the attributes specified. The
426 * descriptor table is effective when the MMU is enabled.
427 *
428 * @param(virtualAddr) The modified virtual address
429 * @param(phyAddr) The physical address
430 * @param(attrs) Pointer to first level descriptor attribute struct
431 */
432 Void setFirstLevelDesc(Ptr virtualAddr, Ptr phyAddr,
433 FirstLevelDescAttrs *attrs);
434
435 /*!
436 * ======== getPhysicalAddr ========
437 * Returns the translated physical address for the given virtual address.
438 * If the virtual address cannot be translated i.e. the virtual address
439 * would generate a fault if translated, ~(0) is returned.
440 *
441 * @param(virtualAddr) virtual address
442 * @b(returns) translated physical address
443 */
444 Ptr getPhysicalAddr(Ptr virtualAddr);
445
446 /*!
447 * @_nodoc
448 * ======== getMmuTableAddr ========
449 * Returns the MMU table base address
450 *
451 * @b(returns) MMU table base address
452 */
453 Ptr getMmuTableAddr();
454
455 /*!
456 * ======== getDomainAccessCtrlReg ========
457 * Returns the domain access control register value (DACR)
458 *
459 * @b(returns) Domain Access Ctrl Register value
460 */
461 UInt32 getDomainAccessCtrlReg();
462
463 /*!
464 * ======== setDomainAccessCtrlReg ========
465 * Write the passed argument to domain access control register (DACR)
466 *
467 * The domain access control register has 16 2-bit fields to control
468 * the access permissions of each domain.
469 *
470 * @p(code)
471 * |31 30|29 28|27 26|25 24|23 22| ... |7 6|5 4|3 2|1 0|
472 * -----------------------------------------------------------
473 * Domain | D15 | D14 | D13 | D12 | D11 | ... | D3 | D2 | D1 | D0 |
474 * -----------------------------------------------------------
475 *
476 * Possible domain access permission value for each field:
477 * 0b00 No access. Any domain access will generate a fault.
478 * 0b01 Accesses are checked against translation table permission bits.
479 * 0b11 No access permission checking is performed for this domain.
480 * @p
481 *
482 * @param(regVal) Contents to be written to DACR register
483 */
484 Void setDomainAccessCtrlReg(UInt32 regVal);
485
486 /*!
487 * @_nodoc
488 * ======== switchContext ========
489 * Switches the ASID and changes the MMU table base address
490 *
491 * Note: This function does not validate the mmuTable pointer
492 *
493 * @param(asid) ASID to switch to
494 * @param(mmuTable) MMU table base address to switch to
495 */
496 Void switchContext(UInt8 asid, Ptr mmuTable);
497
498 /*!
499 * @_nodoc
500 * ======== getAsid ========
501 * Returns the current ASID
502 *
503 * @b(returns) Current ASID
504 */
505 UInt8 getAsid();
506
507 /*!
508 * ======== tlbInvAll ========
509 * Invalidate entire TLB (both data and instruction)
510 */
511 Void tlbInvAll();
512
513 internal:
514
515 /*! static array to hold first level dscriptor table */
516 metaonly config UInt32 tableBuf[];
517
518 /*!
519 * ======== init ========
520 * initialize mmu registers
521 */
522 Void init();
523
524 /*!
525 * ======== enableAsm ========
526 * Assembly function to enable the MMU.
527 */
528 Void enableAsm();
529
530 /*!
531 * ======== disableAsm ========
532 * Assembly function to disable the MMU.
533 */
534 Void disableAsm();
535
536 /*! function generated to initialize first level descriptor table */
537 Void initTableBuf(UInt32 *mmuTableBuf);
538
539 /*!
540 * ======== getPhysicalAddrI ========
541 * Returns the translated physical address for the given virtual address.
542 * If the virtual address cannot be translated i.e. the virtual address
543 * would generate a fault if translated, ~(0) is returned.
544 */
545 Ptr getPhysicalAddrI(Ptr virtualAddr);
546
547 /*! Module state */
548 struct Module_State {
549 UInt32 tableBuf[]; /*! 16KB array for first-level descriptors */
550 }
551 }