4 * ARM7 Virtual Memory Manager
5 * - arch/arm7/mm_virt.c
10 #define AP_KRW_ONLY 0x1
11 #define AP_KRO_ONLY 0x5
12 #define AP_RW_BOTH 0x3
13 #define AP_RO_BOTH 0x6
28 int MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi);
29 int MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi);
34 int MM_InitialiseVirtual(void)
39 int MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi)
41 Uint32 *table0, *table1;
44 if(VAddr & 0x80000000 ) {
45 table0 = (void*)MM_TABLE0KERN; // Level 0
46 table1 = (void*)MM_TABLE1KERN; // Level 1
49 table0 = (void*)MM_TABLE0USER;
50 table1 = (void*)MM_TABLE1USER;
54 desc = &table0[ VAddr >> 20 ];
58 case 12: // Small Page
59 case 16: // Large Page
60 if( (*desc & 3) == 0 ) {
61 if( pi->PhysAddr == 0 ) return 0;
63 *desc = MM_AllocPhys();
64 *desc |= pi->Domain << 5;
67 desc = &table1[ VAddr >> 12 ];
71 // - Error if overwriting a large page
72 if( (*desc & 3) == 1 ) return 1;
73 if( pi->PhysAddr == 0 ) {
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
91 case 20: // Section or unmapped
92 Log_Warning("MM", "TODO: Implement sections");
94 case 24: // Supersection
95 // Error if not aligned
96 if( VAddr & 0xFFFFFF ) {
99 if( (*desc & 3) == 0 || ((*desc & 3) == 2 && (*desc & (1 << 18))) )
101 if( pi->PhysAddr == 0 ) {
103 // TODO: Apply to all entries
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
120 int MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi)
122 Uint32 *table0, *table1;
125 if(VAddr & 0x80000000 ) {
126 table0 = (void*)MM_TABLE0KERN; // Level 0
127 table1 = (void*)MM_TABLE1KERN; // Level 1
130 table0 = (void*)MM_TABLE0USER;
131 table1 = (void*)MM_TABLE1USER;
135 desc = table0[ VAddr >> 20 ];
150 // 1: Coarse page table
152 // Domain from top level table
153 pi->Domain = (desc >> 5) & 7;
155 desc = table1[ VAddr >> 12 ];
162 // 1: Large Page (64KiB)
165 pi->PhysAddr = desc & 0xFFFF0000;
171 pi->PhysAddr = desc & 0xFFFFF000;
172 pi->bExecutable = desc & 1;
173 pi->bGlobal = !(desc >> 11);
174 pi->bShared = (desc >> 10) & 1;
179 // 2: Section (or Supersection)
181 if( desc & (1 << 18) ) {
183 pi->PhysAddr = desc & 0xFF000000;
184 pi->PhysAddr |= (Uint64)((desc >> 20) & 0xF) << 32;
185 pi->PhysAddr |= (Uint64)((desc >> 5) & 0x7) << 36;
187 pi->Domain = 0; // Superpages default to zero
192 pi->PhysAddr = desc & 0xFFF80000;
194 pi->Domain = (desc >> 5) & 7;
197 // 3: Reserved (invalid)
208 tPAddr MM_GetPhysAddr(tVAddr VAddr)
211 if( MM_int_GetPageInfo(VAddr, &pi) )
216 Uint MM_GetFlags(tVAddr VAddr)
221 if( MM_int_GetPageInfo(VAddr, &pi) )
229 ret |= MM_PFLAG_KERNEL;
232 ret |= MM_PFLAG_KERNEL|MM_PFLAG_RO;
241 if( pi.bExecutable ) ret |= MM_PFLAG_EXEC;
245 void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
248 if( MM_int_GetPageInfo(VAddr, &pi) )
255 int MM_Map(tVAddr VAddr, tPAddr PAddr)
257 tMM_PageInfo pi = {0};
260 pi.AP = AP_KRW_ONLY; // Kernel Read/Write
262 if( MM_int_SetPageInfo(VAddr, &pi) ) {
263 MM_DerefPhys(pi.PhysAddr);
269 tPAddr MM_Allocate(tVAddr VAddr)
271 tMM_PageInfo pi = {0};
273 pi.PhysAddr = MM_AllocPhys();
274 if( pi.PhysAddr == 0 ) return 0;
276 pi.AP = AP_KRW_ONLY; // Kernel Read/Write
278 if( MM_int_SetPageInfo(VAddr, &pi) ) {
279 MM_DerefPhys(pi.PhysAddr);
285 void MM_Deallocate(tVAddr VAddr)
289 if( MM_int_GetPageInfo(VAddr, &pi) ) return ;
291 if( pi.PhysAddr == 0 ) return;
292 MM_DerefPhys(pi.PhysAddr);
297 MM_int_SetPageInfo(VAddr, &pi);