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

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