]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Library/EblCmdLib/Arm/EblCmdMmu.c
ARM Packages: Removed trailing spaces
[mirror_edk2.git] / ArmPlatformPkg / Library / EblCmdLib / Arm / EblCmdMmu.c
CommitLineData
1d5d0ae9 1/** @file\r
2*\r
7fffeef9 3* Copyright (c) 2011-2012, ARM Limited. All rights reserved.\r
1d5d0ae9 4*\r
3402aac7
RC
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
1d5d0ae9 12*\r
13**/\r
14\r
15#include <PiDxe.h>\r
16#include <Library/UefiLib.h>\r
17#include <Library/ArmLib.h>\r
18#include <Chipset/ArmV7.h>\r
19#include <Library/CacheMaintenanceLib.h>\r
20#include <Library/EblCmdLib.h>\r
21#include <Library/BaseLib.h>\r
22#include <Library/DebugLib.h>\r
23\r
24#define GET_TT_ATTRIBUTES(TTEntry) ((TTEntry) & ~(TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK))\r
25#define GET_TT_PAGE_ATTRIBUTES(TTEntry) ((TTEntry) & 0xFFF)\r
26#define GET_TT_LARGEPAGE_ATTRIBUTES(TTEntry) ((TTEntry) & 0xFFFF)\r
27\r
28// Section\r
29#define TT_DESCRIPTOR_SECTION_STRONGLY_ORDER (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \\r
1d5d0ae9 30 TT_DESCRIPTOR_SECTION_NG_GLOBAL | \\r
31 TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \\r
32 TT_DESCRIPTOR_SECTION_DOMAIN(0) | \\r
33 TT_DESCRIPTOR_SECTION_AP_RW_RW | \\r
34 TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED)\r
35\r
36// Small Page\r
1d5d0ae9 37#define TT_DESCRIPTOR_PAGE_STRONGLY_ORDER (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \\r
38 TT_DESCRIPTOR_PAGE_NG_GLOBAL | \\r
39 TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \\r
40 TT_DESCRIPTOR_PAGE_AP_RW_RW | \\r
41 TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED)\r
42\r
43// Large Page\r
44#define TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \\r
45 TT_DESCRIPTOR_PAGE_NG_GLOBAL | \\r
46 TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \\r
47 TT_DESCRIPTOR_PAGE_AP_RW_RW | \\r
48 TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC)\r
49#define TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \\r
50 TT_DESCRIPTOR_PAGE_NG_GLOBAL | \\r
51 TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \\r
52 TT_DESCRIPTOR_PAGE_AP_RW_RW | \\r
53 TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC)\r
54#define TT_DESCRIPTOR_LARGEPAGE_DEVICE (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \\r
55 TT_DESCRIPTOR_PAGE_NG_GLOBAL | \\r
56 TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \\r
57 TT_DESCRIPTOR_PAGE_AP_RW_RW | \\r
58 TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE)\r
59#define TT_DESCRIPTOR_LARGEPAGE_UNCACHED (TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE | \\r
60 TT_DESCRIPTOR_PAGE_NG_GLOBAL | \\r
61 TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \\r
62 TT_DESCRIPTOR_PAGE_AP_RW_RW | \\r
63 TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE)\r
64\r
65\r
66typedef enum { Level0, Level1,Level2 } MMU_LEVEL;\r
67\r
68typedef struct {\r
9e2b420e 69 MMU_LEVEL Level;\r
70 UINT32 Value;\r
71 UINT32 Index;\r
72 UINT32* Table;\r
1d5d0ae9 73} MMU_ENTRY;\r
74\r
9e2b420e 75MMU_ENTRY\r
76MmuEntryCreate (\r
77 IN MMU_LEVEL Level,\r
78 IN UINT32* Table,\r
79 IN UINT32 Index\r
80 )\r
81{\r
82 MMU_ENTRY Entry;\r
83 Entry.Level = Level;\r
84 Entry.Value = Table[Index];\r
85 Entry.Table = Table;\r
86 Entry.Index = Index;\r
87 return Entry;\r
1d5d0ae9 88}\r
89\r
9e2b420e 90UINT32\r
91MmuEntryIsValidAddress (\r
92 IN MMU_LEVEL Level,\r
93 IN UINT32 Entry\r
94 )\r
95{\r
96 if (Level == Level0) {\r
97 return 0;\r
98 } else if (Level == Level1) {\r
99 if ((Entry & 0x3) == 0) { // Ignored\r
100 return 0;\r
101 } else if ((Entry & 0x3) == 2) { // Section Type\r
102 return 1;\r
103 } else { // Page Type\r
104 return 0;\r
105 }\r
106 } else if (Level == Level2){\r
107 if ((Entry & 0x3) == 0) { // Ignored\r
108 return 0;\r
109 } else { // Page Type\r
110 return 1;\r
1d5d0ae9 111 }\r
9e2b420e 112 } else {\r
113 DEBUG((EFI_D_ERROR,"MmuEntryIsValidAddress: Level:%d Entry:0x%X\n",(UINT32)Level,(UINT32)Entry));\r
114 ASSERT(0);\r
115 return 0;\r
116 }\r
1d5d0ae9 117}\r
118\r
9e2b420e 119UINT32\r
120MmuEntryGetAddress (\r
121 IN MMU_ENTRY Entry\r
122 )\r
123{\r
124 if (Entry.Level == Level1) {\r
125 if ((Entry.Value & 0x3) == 0) {\r
126 return 0;\r
127 } else if ((Entry.Value & 0x3) == 2) { // Section Type\r
128 return Entry.Value & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK;\r
129 } else if ((Entry.Value & 0x3) == 1) { // Level2 Table\r
fb42fffe 130 MMU_ENTRY Level2Entry = MmuEntryCreate (Level2,(UINT32*)(Entry.Value & 0xFFFFC000),0);\r
131 return MmuEntryGetAddress (Level2Entry);\r
9e2b420e 132 } else { // Page Type\r
133 return 0;\r
134 }\r
135 } else if (Entry.Level == Level2) {\r
136 if ((Entry.Value & 0x3) == 0) { // Ignored\r
137 return 0;\r
138 } else if ((Entry.Value & 0x3) == 1) { // Large Page\r
139 return Entry.Value & 0xFFFF0000;\r
140 } else if ((Entry.Value & 0x2) == 2) { // Small Page\r
141 return Entry.Value & 0xFFFFF000;\r
1d5d0ae9 142 } else {\r
9e2b420e 143 return 0;\r
1d5d0ae9 144 }\r
9e2b420e 145 } else {\r
146 ASSERT(0);\r
147 return 0;\r
148 }\r
1d5d0ae9 149}\r
150\r
9e2b420e 151UINT32\r
152MmuEntryGetSize (\r
153 IN MMU_ENTRY Entry\r
154 )\r
155{\r
156 if (Entry.Level == Level1) {\r
157 if ((Entry.Value & 0x3) == 0) {\r
158 return 0;\r
159 } else if ((Entry.Value & 0x3) == 2) {\r
160 if (Entry.Value & (1 << 18))\r
161 return 16*SIZE_1MB;\r
162 else\r
163 return SIZE_1MB;\r
164 } else if ((Entry.Value & 0x3) == 1) { // Level2 Table split 1MB section\r
165 return SIZE_1MB;\r
1d5d0ae9 166 } else {\r
9e2b420e 167 DEBUG((EFI_D_ERROR, "MmuEntryGetSize: Value:0x%X",Entry.Value));\r
168 ASSERT(0);\r
169 return 0;\r
1d5d0ae9 170 }\r
9e2b420e 171 } else if (Entry.Level == Level2) {\r
172 if ((Entry.Value & 0x3) == 0) { // Ignored\r
173 return 0;\r
174 } else if ((Entry.Value & 0x3) == 1) { // Large Page\r
175 return SIZE_64KB;\r
176 } else if ((Entry.Value & 0x2) == 2) { // Small Page\r
177 return SIZE_4KB;\r
178 } else {\r
179 ASSERT(0);\r
180 return 0;\r
181 }\r
182 } else {\r
183 ASSERT(0);\r
184 return 0;\r
185 }\r
1d5d0ae9 186}\r
187\r
9e2b420e 188CONST CHAR8*\r
189MmuEntryGetAttributesName (\r
190 IN MMU_ENTRY Entry\r
191 )\r
192{\r
193 UINT32 Value;\r
194\r
195 if (Entry.Level == Level1) {\r
196 Value = GET_TT_ATTRIBUTES(Entry.Value) | TT_DESCRIPTOR_SECTION_NS_MASK;\r
197 if (Value == TT_DESCRIPTOR_SECTION_WRITE_BACK(0))\r
198 return "TT_DESCRIPTOR_SECTION_WRITE_BACK";\r
199 else if (Value == TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0))\r
200 return "TT_DESCRIPTOR_SECTION_WRITE_THROUGH";\r
201 else if (Value == TT_DESCRIPTOR_SECTION_DEVICE(0))\r
202 return "TT_DESCRIPTOR_SECTION_DEVICE";\r
203 else if (Value == TT_DESCRIPTOR_SECTION_UNCACHED(0))\r
204 return "TT_DESCRIPTOR_SECTION_UNCACHED";\r
205 else if (Value == TT_DESCRIPTOR_SECTION_STRONGLY_ORDER)\r
206 return "TT_DESCRIPTOR_SECTION_STRONGLY_ORDERED";\r
207 else {\r
208 return "SectionUnknown";\r
209 }\r
210 } else if ((Entry.Level == Level2) && ((Entry.Value & 0x2) == 2)) { //Small Page\r
211 Value = GET_TT_PAGE_ATTRIBUTES(Entry.Value);\r
212 if (Value == TT_DESCRIPTOR_PAGE_WRITE_BACK)\r
213 return "TT_DESCRIPTOR_PAGE_WRITE_BACK";\r
214 else if (Value == TT_DESCRIPTOR_PAGE_WRITE_THROUGH)\r
215 return "TT_DESCRIPTOR_PAGE_WRITE_THROUGH";\r
216 else if (Value == TT_DESCRIPTOR_PAGE_DEVICE)\r
217 return "TT_DESCRIPTOR_PAGE_DEVICE";\r
218 else if (Value == TT_DESCRIPTOR_PAGE_UNCACHED)\r
219 return "TT_DESCRIPTOR_PAGE_UNCACHED";\r
220 else if (Value == TT_DESCRIPTOR_PAGE_STRONGLY_ORDER)\r
221 return "TT_DESCRIPTOR_PAGE_STRONGLY_ORDERED";\r
222 else {\r
223 return "PageUnknown";\r
224 }\r
225 } else if ((Entry.Level == Level2) && ((Entry.Value & 0x3) == 1)) { //Large Page\r
226 Value = GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value);\r
227 if (Value == TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK)\r
228 return "TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK";\r
229 else if (Value == TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH)\r
230 return "TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH";\r
231 else if (Value == TT_DESCRIPTOR_LARGEPAGE_DEVICE)\r
232 return "TT_DESCRIPTOR_LARGEPAGE_DEVICE";\r
233 else if (Value == TT_DESCRIPTOR_LARGEPAGE_UNCACHED)\r
234 return "TT_DESCRIPTOR_LARGEPAGE_UNCACHED";\r
235 else {\r
236 return "LargePageUnknown";\r
1d5d0ae9 237 }\r
9e2b420e 238 } else {\r
239 ASSERT(0);\r
240 return "";\r
241 }\r
1d5d0ae9 242}\r
243\r
9e2b420e 244UINT32\r
245MmuEntryGetAttributes (\r
246 IN MMU_ENTRY Entry\r
247 )\r
248{\r
249 if (Entry.Level == Level1) {\r
250 if ((Entry.Value & 0x3) == 0) {\r
251 return 0;\r
252 } else if ((Entry.Value & 0x3) == 2) {\r
253 return GET_TT_ATTRIBUTES(Entry.Value);\r
1d5d0ae9 254 } else {\r
9e2b420e 255 return 0;\r
256 }\r
257 } else if ((Entry.Level == Level2) && ((Entry.Value & 0x2) == 2)) { //Small Page\r
258 if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_WRITE_BACK)\r
259 return TT_DESCRIPTOR_SECTION_WRITE_BACK(0);\r
260 else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_WRITE_THROUGH)\r
261 return TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0);\r
262 else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_DEVICE)\r
263 return TT_DESCRIPTOR_SECTION_DEVICE(0);\r
264 else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_UNCACHED)\r
265 return TT_DESCRIPTOR_SECTION_UNCACHED(0);\r
266 else if (GET_TT_PAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_PAGE_STRONGLY_ORDER)\r
267 return TT_DESCRIPTOR_SECTION_STRONGLY_ORDER;\r
268 else {\r
269 return 0;\r
270 }\r
271 } else if ((Entry.Level == Level2) && ((Entry.Value & 0x3) == 1)) { //Large Page\r
272 if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_WRITE_BACK)\r
273 return TT_DESCRIPTOR_SECTION_WRITE_BACK(0);\r
274 else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_WRITE_THROUGH)\r
275 return TT_DESCRIPTOR_SECTION_WRITE_THROUGH(0);\r
276 else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_DEVICE)\r
277 return TT_DESCRIPTOR_SECTION_DEVICE(0);\r
278 else if (GET_TT_LARGEPAGE_ATTRIBUTES(Entry.Value) == TT_DESCRIPTOR_LARGEPAGE_UNCACHED)\r
279 return TT_DESCRIPTOR_SECTION_UNCACHED(0);\r
280 else {\r
281 return 0;\r
1d5d0ae9 282 }\r
9e2b420e 283 } else {\r
284 return 0;\r
285 }\r
1d5d0ae9 286}\r
287\r
288\r
9e2b420e 289MMU_ENTRY\r
290DumpMmuLevel (\r
291 IN MMU_LEVEL Level,\r
292 IN UINT32* Table,\r
293 IN MMU_ENTRY PreviousEntry\r
294 )\r
295{\r
296 UINT32 Index = 0, Count;\r
297 MMU_ENTRY LastEntry, Entry;\r
1d5d0ae9 298\r
299 ASSERT((Level == Level1) || (Level == Level2));\r
300\r
9e2b420e 301 if (Level == Level1) Count = 4096;\r
302 else Count = 256;\r
1d5d0ae9 303\r
9e2b420e 304 // At Level1, we will get into this function because PreviousEntry is not valid\r
305 if (!MmuEntryIsValidAddress((MMU_LEVEL)(Level-1),PreviousEntry.Value)) {\r
306 // Find the first valid address\r
307 for (; (Index < Count) && (!MmuEntryIsValidAddress(Level,Table[Index])); Index++);\r
1d5d0ae9 308\r
9e2b420e 309 LastEntry = MmuEntryCreate(Level,Table,Index);\r
310 Index++;\r
311 } else {\r
312 LastEntry = PreviousEntry;\r
313 }\r
1d5d0ae9 314\r
9e2b420e 315 for (; Index < Count; Index++) {\r
316 Entry = MmuEntryCreate(Level,Table,Index);\r
317 if ((Level == Level1) && ((Entry.Value & 0x3) == 1)) { // We have got a Level2 table redirection\r
318 LastEntry = DumpMmuLevel(Level2,(UINT32*)(Entry.Value & 0xFFFFFC00),LastEntry);\r
319 } else if (!MmuEntryIsValidAddress(Level,Table[Index])) {\r
320 if (MmuEntryIsValidAddress(LastEntry.Level,LastEntry.Value)) {\r
321 AsciiPrint("0x%08X-0x%08X\t%a\n",\r
322 MmuEntryGetAddress(LastEntry),MmuEntryGetAddress(PreviousEntry)+MmuEntryGetSize(PreviousEntry)-1,\r
323 MmuEntryGetAttributesName(LastEntry));\r
324 }\r
325 LastEntry = Entry;\r
326 } else {\r
327 if (MmuEntryGetAttributes(LastEntry) != MmuEntryGetAttributes(Entry)) {\r
328 if (MmuEntryIsValidAddress(Level,LastEntry.Value)) {\r
329 AsciiPrint("0x%08X-0x%08X\t%a\n",\r
330 MmuEntryGetAddress(LastEntry),MmuEntryGetAddress(PreviousEntry)+MmuEntryGetSize(PreviousEntry)-1,\r
331 MmuEntryGetAttributesName(LastEntry));\r
332 }\r
333 LastEntry = Entry;\r
334 } else {\r
335 ASSERT(LastEntry.Value != 0);\r
336 }\r
1d5d0ae9 337 }\r
9e2b420e 338 PreviousEntry = Entry;\r
339 }\r
1d5d0ae9 340\r
9e2b420e 341 if ((Level == Level1) && (LastEntry.Index != Index) && MmuEntryIsValidAddress(Level,LastEntry.Value)) {\r
342 AsciiPrint("0x%08X-0x%08X\t%a\n",\r
343 MmuEntryGetAddress(LastEntry),MmuEntryGetAddress(PreviousEntry)+MmuEntryGetSize(PreviousEntry)-1,\r
344 MmuEntryGetAttributesName(LastEntry));\r
345 }\r
1d5d0ae9 346\r
9e2b420e 347 return LastEntry;\r
1d5d0ae9 348}\r
349\r
350\r
351EFI_STATUS\r
352EblDumpMmu (\r
353 IN UINTN Argc,\r
354 IN CHAR8 **Argv\r
355 )\r
356{\r
9e2b420e 357 UINT32 *TTEntry;\r
358 MMU_ENTRY NoEntry;\r
359\r
360 TTEntry = ArmGetTTBR0BaseAddress();\r
1d5d0ae9 361\r
9e2b420e 362 AsciiPrint ("\nTranslation Table:0x%X\n",TTEntry);\r
363 AsciiPrint ("Address Range\t\tAttributes\n");\r
364 AsciiPrint ("____________________________________________________\n");\r
1d5d0ae9 365\r
9e2b420e 366 NoEntry.Level = (MMU_LEVEL)200;\r
367 DumpMmuLevel(Level1,TTEntry,NoEntry);\r
1d5d0ae9 368\r
9e2b420e 369 return EFI_SUCCESS;\r
1d5d0ae9 370}\r