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
37
38 package ti.sysbios.family.arm.a8;
39
40 import xdc.rov.ViewInfo;
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,
63 * specified to not be initialized via the "NOLOAD" type on GNU compilers
64 * and "NOINIT" on TI compilers.
65 *
66 * This module does not manage the second level descriptor tables.
67 * A 'SECTION' mapped access requires only a first level fetch. In
68 * this case, there is no need for a second level descriptor table.
69 * A 'PAGE_TABLE' mapped access requires a second level
70 * descriptor table which can be supplied by the user.
71 *
72 * The following is an example of how to place the MMU table
73 * and how to enable L1 data caching for the address range
74 * 0x80000000-0x90000000 in the *.cfg file:
75 *
76 * @p(code)
77 *
78 * var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
79 * var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
80 *
81 * // Enable the cache
82 * Cache.enableCache = true;
83 *
84 * // Enable the MMU (Required for L1/L2 data caching)
85 * Mmu.enableMMU = true;
86 *
87 * // descriptor attribute structure
88 * var attrs = {
89 * type: Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
90 * bufferable: true, // bufferable
91 * cacheable: true, // cacheable
92 * };
93 *
94 * // Set the descriptor for each entry in the address range
95 * for (var i=0x80000000; i < 0x90000000; i = i + 0x00100000) {
96 * // Each 'SECTION' descriptor entry spans a 1MB address range
97 * Mmu.setFirstLevelDescMeta(i, i, attrs);
98 * }
99 *
100 * var memmap = Program.cpu.memoryMap;
101 * var DDR = null;
102 *
103 * // Find DDR in memory map
104 * for (var i=0; i < memmap.length; i++) {
105 * if (memmap[i].name == "DDR") {
106 * DDR = memmap[i];
107 * }
108 * }
109 *
110 * // Place the MMU table in the DDR memory segment if it exists
111 * if (DDR != null) {
112 * var sectionName = "ti.sysbios.family.arm.a8.mmuTableSection";
113 * Program.sectMap[sectionName] = new Program.SectionSpec();
114 * Program.sectMap[sectionName].type = "NOINIT";
115 * Program.sectMap[sectionName].loadSegment = "DDR";
116 * }
117 * else {
118 * print("No DDR memory segment was found");
119 * }
120 *
121 * @p
122 *
123 * The following example demonstrates how to add a peripheral's address
124 * to the MMU table so that it can be accessed by code at runtime:
125 *
126 * @p(code)
127 * var Cache = xdc.useModule('ti.sysbios.family.arm.a8.Cache');
128 * var Mmu = xdc.useModule('ti.sysbios.family.arm.a8.Mmu');
129 *
130 * // Enable the cache
131 * Cache.enableCache = true;
132 *
133 * // Enable the MMU (Required for L1/L2 data caching)
134 * Mmu.enableMMU = true;
135 *
136 * // Force peripheral section to be NON cacheable
137 * var peripheralAttrs = {
138 * type : Mmu.FirstLevelDesc_SECTION, // SECTION descriptor
139 * bufferable : false, // bufferable
140 * cacheable : false, // cacheable
141 * shareable : false, // shareable
142 * noexecute : true, // not executable
143 * };
144 *
145 * // Define the base address of the 1 Meg page
146 * // the peripheral resides in.
147 * var peripheralBaseAddr = 0xa0400000;
148 *
149 * // Configure the corresponding MMU page descriptor accordingly
150 * Mmu.setFirstLevelDescMeta(peripheralBaseAddr,
151 * peripheralBaseAddr,
152 * peripheralAttrs);
153 * @p
154 *
155 * Notes:
156 * @p(blist)
157 * -The 'Supersection' table descriptor is NOT supported.
158 * -The 'not global' page descriptor setting is NOT supported.
159 * -The 'non-secure' page descriptor setting is NOT supported.
160 * -There are size and alignment requirements on the second
161 * level descriptor tables depending on the page size.
162 * -See the ARM Architecture Reference Manual for more info.
163 * @p
164 *
165 */
166
167 @Template ("./Mmu.xdt")
168 @ModuleStartup
169
170 module Mmu
171 {
172
173
174 /*! @_nodoc */
175 metaonly struct PageView {
176 String Type;
177 Ptr AddrVirtual;
178 Ptr AddrPhysical;
179 Ptr Level2TablePtr;
180 Bool Bufferable;
181 Bool Cacheable;
182 Bool Shareable;
183 Bool Noexecute;
184 String L1DWritePolicy;
185 UInt IMP;
186 UInt Domain;
187 String Access;
188 };
189
190 @Facet
191 metaonly config ViewInfo.Instance rovViewInfo =
192 ViewInfo.create({
193 viewMap: [
194 ['PageView', {
195 type: ViewInfo.MODULE_DATA,
196 viewInitFxn: 'viewPages',
197 structName: 'PageView'
198 }]
199 ]
200 });
201
202 /*! First Level descriptors */
203 enum FirstLevelDesc {
204 FirstLevelDesc_FAULT = 0, /*! Virtual address is unmapped */
205 FirstLevelDesc_PAGE_TABLE = 1, /*! Page table addr descriptor */
206 FirstLevelDesc_SECTION = 2 /*! Section descriptor */
207 };
208
209 /*!
210 * Structure for setting first level descriptor entries
211 *
212 * If the 'cacheable' attribute is true and 'bufferable' is true,
213 * L1 data cache operates as a write-back cache.
214 * If 'cacheable' is true but 'bufferable' is false,
215 * L1 data cache operates as a write-through cache.
216 *
217 * See the 'Translation Tables' section of the ARM v7 Architecture
218 * Reference Manual for more details.
219 */
220 struct FirstLevelDescAttrs {
221 FirstLevelDesc type; /*! first level descriptor type */
222 Bool bufferable; /*! is memory section bufferable */
223 Bool cacheable; /*! is memory section cacheable */
224 Bool shareable; /*! is memory section shareable */
225 Bool noexecute; /*! is memory section not executable */
226 UInt8 imp; /*! implementation defined */
227 UInt8 domain; /*! domain access control value 0-15 */
228 UInt8 accPerm; /*! access permission bits value 0-3 */
229 };
230
231 /*!
232 * ======== A_nullPointer ========
233 * Assert raised when a pointer is null
234 */
235 config xdc.runtime.Assert.Id A_nullPointer = {
236 msg: "A_nullPointer: Pointer is null"
237 };
238
239 /*!
240 * ======== A_unknownDescType ========
241 * Assert raised when the descriptor type is not recognized.
242 */
243 config xdc.runtime.Assert.Id A_unknownDescType =
244 {msg: "A_unknownDescType: Descriptor type is not recognized"};
245
246 /*! default descriptor attributes structure */
247 config FirstLevelDescAttrs defaultAttrs = {
248 type: FirstLevelDesc_SECTION,
249 bufferable: false,
250 cacheable: false,
251 shareable: false,
252 noexecute: false,
253 imp: 1,
254 domain: 0,
255 accPerm: 3,
256 };
257
258 /*!
259 * ======== enableMMU ========
260 * Configuration parameter to enable MMU.
261 */
262 config Bool enableMMU = true;
263
264 /*!
265 * ======== cachePlatformMemory ========
266 * Flag to automatically mark platform's code/data/stack memory as
267 * cacheable in MMU descriptor table
268 *
269 * By default, all memory regions defined in the platform an
270 * application is built with are marked as cacheable.
271 *
272 * @see xdc.bld.Program#platform
273 *
274 * If manual configuration of memory regions is required, set
275 * this config parameter to 'false'.
276 */
277 metaonly config Bool cachePlatformMemory = true;
278
279 /*!
280 * ======== setFirstLevelDescMeta ========
281 * Statically sets the descriptor for the virtual address.
282 *
283 * The first level table entry for the virtual address is mapped
284 * to the physical address with the attributes specified. The
285 * descriptor table is effective when the MMU is enabled.
286 *
287 * @param(virtualAddr) The modified virtual address
288 * @param(phyAddr) The physical address
289 * @param(attrs) Pointer to first level descriptor attribute struct
290 */
291 metaonly Void setFirstLevelDescMeta(Ptr virtualAddr, Ptr phyAddr,
292 FirstLevelDescAttrs attrs);
293
294 /*!
295 * ======== disable ========
296 * Disables the MMU.
297 *
298 * If the MMU is already disabled, then simply return.
299 * Otherwise this function does the following:
300 * If the L1 data cache is enabled, write back invalidate all
301 * of L1 data cache. If the L1 program cache is enabled,
302 * invalidate all of L1 program cache. This function does not
303 * change the cache L1 data/program settings.
304 */
305 @DirectCall
306 Void disable();
307
308 /*!
309 * ======== enable ========
310 * Enables the MMU.
311 *
312 * If the MMU is already enabled, then simply return.
313 * Otherwise this function does the following:
314 * If the L1 program cache is enabled, invalidate all of L1
315 * program cache. This function does not change the L1
316 * data/program cache settings.
317 */
318 @DirectCall
319 Void enable();
320
321 /*!
322 * ======== initDescAttrs() ========
323 * Initializes the first level descriptor attribute structure
324 *
325 * @param(attrs) Pointer to first level descriptor attribute struct
326 */
327 @DirectCall
328 Void initDescAttrs(FirstLevelDescAttrs *attrs);
329
330 /*!
331 * ======== isEnabled ========
332 * Determines if the MMU is enabled
333 */
334 @DirectCall
335 Bool isEnabled();
336
337 /*!
338 * ======== setFirstLevelDesc ========
339 * Sets the descriptor for the virtual address.
340 *
341 * The first level table entry for the virtual address is mapped
342 * to the physical address with the attributes specified. The
343 * descriptor table is effective when the MMU is enabled.
344 *
345 * @param(virtualAddr) The modified virtual address
346 * @param(phyAddr) The physical address
347 * @param(attrs) Pointer to first level descriptor attribute struct
348 */
349 @DirectCall
350 Void setFirstLevelDesc(Ptr virtualAddr, Ptr phyAddr,
351 FirstLevelDescAttrs *attrs);
352
353
354 internal:
355
356 /*! static array to hold first level dscriptor table */
357 metaonly config UInt32 tableBuf[];
358
359 /*!
360 * ======== enableAsm ========
361 * Assembly function to enable the MMU.
362 */
363 Void enableAsm();
364
365 /*!
366 * ======== disableAsm ========
367 * Assembly function to disable the MMU.
368 */
369 Void disableAsm();
370
371 /*! function generated to initialize first level descriptor table */
372 Void initTableBuf(Module_State *mod);
373
374 /*! Module state */
375 struct Module_State {
376 UInt32 tableBuf[]; /*! 16KB array for first-level descriptors */
377 }
378 }