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

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