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