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