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

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