Kernel/arm7 - Removed debug statement from VMM
[tpg/acess2.git] / Kernel / arch / arm7 / mm_virt.c
1 /*
2  * Acess2
3  * 
4  * ARM7 Virtual Memory Manager
5  * - arch/arm7/mm_virt.c
6  */
7 #define DEBUG   0
8 #include <acess.h>
9 #include <mm_virt.h>
10 #include <hal_proc.h>
11
12 #define AP_KRW_ONLY     0x1
13 #define AP_KRO_ONLY     0x5
14 #define AP_RW_BOTH      0x3
15 #define AP_RO_BOTH      0x6
16
17 // === IMPORTS ===
18 extern Uint32   kernel_table0[];
19
20 // === TYPES ===
21 typedef struct
22 {
23         tPAddr  PhysAddr;
24         Uint8   Size;
25         Uint8   Domain;
26         BOOL    bExecutable;
27         BOOL    bGlobal;
28         BOOL    bShared;
29          int    AP;
30 } tMM_PageInfo;
31
32 //#define FRACTAL(table1, addr) ((table1)[ (0xFF8/4*1024) + ((addr)>>20)])
33 #define FRACTAL(table1, addr)   ((table1)[ (0xFF8/4*1024) + ((addr)>>22)])
34 #define TLBIALL()       __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0))
35
36 // === PROTOTYPES ===
37 void    MM_int_GetTables(tVAddr VAddr, Uint32 **Table0, Uint32 **Table1);
38  int    MM_int_AllocateCoarse(tVAddr VAddr, int Domain);
39  int    MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi);
40  int    MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi);
41
42 // === GLOBALS ===
43
44 // === CODE ===
45 int MM_InitialiseVirtual(void)
46 {
47         return 0;
48 }
49
50 void MM_int_GetTables(tVAddr VAddr, Uint32 **Table0, Uint32 **Table1)
51 {
52         if(VAddr & 0x80000000) {
53                 *Table0 = (void*)&kernel_table0;        // Level 0
54                 *Table1 = (void*)MM_TABLE1KERN; // Level 1
55         }
56         else {
57                 *Table0 = (void*)MM_TABLE0USER;
58                 *Table1 = (void*)MM_TABLE1USER;
59         }
60 }
61
62 int MM_int_AllocateCoarse(tVAddr VAddr, int Domain)
63 {
64         Uint32  *table0, *table1;
65         Uint32  *desc;
66         tPAddr  paddr;
67         
68         ENTER("xVAddr iDomain", VAddr, Domain);
69
70         MM_int_GetTables(VAddr, &table0, &table1);
71
72         VAddr &= ~(0x400000-1); // 4MiB per "block", 1 Page
73
74         desc = &table0[ VAddr>>20];
75         LOG("desc = %p", desc);
76         
77         // table0: 4 bytes = 1 MiB
78
79         LOG("desc[0] = %x", desc[0]);
80         LOG("desc[1] = %x", desc[1]);
81         LOG("desc[2] = %x", desc[2]);
82         LOG("desc[3] = %x", desc[3]);
83
84         if( (desc[0] & 3) != 0 || (desc[1] & 3) != 0
85          || (desc[2] & 3) != 0 || (desc[3] & 3) != 0 )
86         {
87                 // Error?
88                 LEAVE('i', 1);
89                 return 1;
90         }
91
92         paddr = MM_AllocPhys();
93         if( !paddr )
94         {
95                 // Error
96                 LEAVE('i', 2);
97                 return 2;
98         }
99         
100         *desc = paddr | (Domain << 5) | 1;
101         desc[1] = desc[0] + 0x400;
102         desc[2] = desc[0] + 0x800;
103         desc[3] = desc[0] + 0xC00;
104
105         FRACTAL(table1, VAddr) = paddr | 3;
106
107         // TLBIALL 
108         TLBIALL();      
109
110         LEAVE('i', 0);
111         return 0;
112 }       
113
114 int MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi)
115 {
116         Uint32  *table0, *table1;
117         Uint32  *desc;
118
119         ENTER("pVADdr ppi", VAddr, pi);
120
121         MM_int_GetTables(VAddr, &table0, &table1);
122
123         desc = &table0[ VAddr >> 20 ];
124         LOG("desc = %p", desc);
125
126         switch(pi->Size)
127         {
128         case 12:        // Small Page
129         case 16:        // Large Page
130                 LOG("Page");
131                 if( (*desc & 3) == 0 ) {
132                         MM_int_AllocateCoarse( VAddr, pi->Domain );
133                 }
134                 desc = &table1[ VAddr >> 12 ];
135                 LOG("desc (2) = %p", desc);
136                 if( pi->Size == 12 )
137                 {
138                         // Small page
139                         // - Error if overwriting a large page
140                         if( (*desc & 3) == 1 )  LEAVE_RET('i', 1);
141                         if( pi->PhysAddr == 0 ) {
142                                 *desc = 0;
143                                 LEAVE('i', 0);
144                                 return 0;
145                         }
146
147                         *desc = (pi->PhysAddr & 0xFFFFF000) | 2;
148                         if(!pi->bExecutable)    *desc |= 1;     // XN
149                         if(!pi->bGlobal)        *desc |= 1 << 11;       // NG
150                         if( pi->bShared)        *desc |= 1 << 10;       // S
151                         *desc |= (pi->AP & 3) << 4;     // AP
152                         *desc |= ((pi->AP >> 2) & 1) << 9;      // APX
153                         LEAVE('i', 0);
154                         return 0;
155                 }
156                 else
157                 {
158                         // Large page
159                         // TODO: 
160                 }
161                 break;
162         case 20:        // Section or unmapped
163                 Warning("TODO: Implement sections");
164                 break;
165         case 24:        // Supersection
166                 // Error if not aligned
167                 if( VAddr & 0xFFFFFF ) {
168                         LEAVE('i', 1);
169                         return 1;
170                 }
171                 if( (*desc & 3) == 0 || ((*desc & 3) == 2 && (*desc & (1 << 18)))  )
172                 {
173                         if( pi->PhysAddr == 0 ) {
174                                 *desc = 0;
175                                 // TODO: Apply to all entries
176                                 LEAVE('i', 0);
177                                 return 0;
178                         }
179                         // Apply
180                         *desc = pi->PhysAddr & 0xFF000000;
181 //                      *desc |= ((pi->PhysAddr >> 32) & 0xF) << 20;
182 //                      *desc |= ((pi->PhysAddr >> 36) & 0x7) << 5;
183                         *desc |= 2 | (1 << 18);
184                         // TODO: Apply to all entries
185                         LEAVE('i', 0);
186                         return 0;
187                 }
188                 // TODO: What here?
189                 LEAVE('i', 1);
190                 return 1;
191         }
192
193         LEAVE('i', 1);
194         return 1;
195 }
196
197 extern tShortSpinlock   glDebug_Lock;
198
199 int MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi)
200 {
201         Uint32  *table0, *table1;
202         Uint32  desc;
203         
204         MM_int_GetTables(VAddr, &table0, &table1);
205
206         desc = table0[ VAddr >> 20 ];
207
208 //      if( VAddr > 0x90000000)
209 //              LOG("table0 desc(%p) = %x", &table0[ VAddr >> 20 ], desc);
210         
211         pi->bExecutable = 1;
212         pi->bGlobal = 0;
213         pi->bShared = 0;
214
215
216         switch( (desc & 3) )
217         {
218         // 0: Unmapped
219         case 0:
220                 pi->PhysAddr = 0;
221                 pi->Size = 20;
222                 pi->Domain = 0;
223                 return 1;
224
225         // 1: Coarse page table
226         case 1:
227                 // Domain from top level table
228                 pi->Domain = (desc >> 5) & 7;
229                 // Get next level
230                 desc = table1[ VAddr >> 12 ];
231 //              LOG("table1 desc(%p) = %x", &table1[ VAddr >> 12 ], desc);
232                 switch( desc & 3 )
233                 {
234                 // 0: Unmapped
235                 case 0: 
236                         pi->Size = 12;
237                         return 1;
238                 // 1: Large Page (64KiB)
239                 case 1:
240                         pi->Size = 16;
241                         pi->PhysAddr = desc & 0xFFFF0000;
242                         return 0;
243                 // 2/3: Small page
244                 case 2:
245                 case 3:
246                         pi->Size = 12;
247                         pi->PhysAddr = desc & 0xFFFFF000;
248                         pi->bExecutable = desc & 1;
249                         pi->bGlobal = !(desc >> 11);
250                         pi->bShared = (desc >> 10) & 1;
251                         return 0;
252                 }
253                 return 1;
254         
255         // 2: Section (or Supersection)
256         case 2:
257                 if( desc & (1 << 18) ) {
258                         // Supersection
259                         pi->PhysAddr = desc & 0xFF000000;
260                         pi->PhysAddr |= (Uint64)((desc >> 20) & 0xF) << 32;
261                         pi->PhysAddr |= (Uint64)((desc >> 5) & 0x7) << 36;
262                         pi->Size = 24;
263                         pi->Domain = 0; // Superpages default to zero
264                         return 0;
265                 }
266                 
267                 // Section
268                 pi->PhysAddr = desc & 0xFFF80000;
269                 pi->Size = 20;
270                 pi->Domain = (desc >> 5) & 7;
271                 return 0;
272
273         // 3: Reserved (invalid)
274         case 3:
275                 pi->PhysAddr = 0;
276                 pi->Size = 20;
277                 pi->Domain = 0;
278                 return 2;
279         }
280         return 2;
281 }
282
283 // --- Exports ---
284 tPAddr MM_GetPhysAddr(tVAddr VAddr)
285 {
286         tMM_PageInfo    pi;
287         if( MM_int_GetPageInfo(VAddr, &pi) )
288                 return 0;
289         return pi.PhysAddr | (VAddr & ((1 << pi.Size)-1));
290 }
291
292 Uint MM_GetFlags(tVAddr VAddr)
293 {
294         tMM_PageInfo    pi;
295          int    ret;
296
297         if( MM_int_GetPageInfo(VAddr, &pi) )
298                 return 0;
299
300         ret = 0;
301         
302         switch(pi.AP)
303         {
304         case AP_KRW_ONLY:
305                 ret |= MM_PFLAG_KERNEL;
306                 break;
307         case AP_KRO_ONLY:
308                 ret |= MM_PFLAG_KERNEL|MM_PFLAG_RO;
309                 break;
310         case AP_RW_BOTH:
311                 break;
312         case AP_RO_BOTH:
313                 ret |= MM_PFLAG_RO;
314                 break;
315         }
316
317         if( pi.bExecutable )    ret |= MM_PFLAG_EXEC;
318         return ret;
319 }
320
321 void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
322 {
323         tMM_PageInfo    pi;
324         if( MM_int_GetPageInfo(VAddr, &pi) )
325                 return;
326         
327                 
328
329 }
330
331 int MM_Map(tVAddr VAddr, tPAddr PAddr)
332 {
333         tMM_PageInfo    pi = {0};
334         pi.PhysAddr = PAddr;
335         pi.Size = 12;
336         pi.AP = AP_KRW_ONLY;    // Kernel Read/Write
337         pi.bExecutable = 1;
338         if( MM_int_SetPageInfo(VAddr, &pi) ) {
339                 MM_DerefPhys(pi.PhysAddr);
340                 return 0;
341         }
342         return pi.PhysAddr;
343 }
344
345 tPAddr MM_Allocate(tVAddr VAddr)
346 {
347         tMM_PageInfo    pi = {0};
348         
349         ENTER("pVAddr", VAddr);
350
351         pi.PhysAddr = MM_AllocPhys();
352         if( pi.PhysAddr == 0 )  LEAVE_RET('i', 0);
353         pi.Size = 12;
354         pi.AP = AP_KRW_ONLY;    // Kernel Read/Write
355         pi.bExecutable = 1;
356         if( MM_int_SetPageInfo(VAddr, &pi) ) {
357                 MM_DerefPhys(pi.PhysAddr);
358                 LEAVE('i', 0);
359                 return 0;
360         }
361         LEAVE('x', pi.PhysAddr);
362         return pi.PhysAddr;
363 }
364
365 void MM_Deallocate(tVAddr VAddr)
366 {
367         tMM_PageInfo    pi;
368         
369         if( MM_int_GetPageInfo(VAddr, &pi) )    return ;
370
371         if( pi.PhysAddr == 0 )  return;
372         MM_DerefPhys(pi.PhysAddr);
373         
374         pi.PhysAddr = 0;
375         pi.AP = 0;
376         pi.bExecutable = 0;
377         MM_int_SetPageInfo(VAddr, &pi);
378 }
379
380 tPAddr MM_ClearUser(void)
381 {
382         // TODO: Implement ClearUser
383         return 0;
384 }
385
386 tVAddr MM_MapTemp(tPAddr PAddr)
387 {
388         // TODO: Implement MapTemp
389         return 0;
390 }
391
392 void MM_FreeTemp(tVAddr VAddr)
393 {
394         // TODO: Implement FreeTemp
395 }
396
397 void MM_DumpTables(tVAddr Start, tVAddr End)
398 {
399         
400 }
401

UCC git Repository :: git.ucc.asn.au