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