Kernel/armv7 - Implemetned Hivecs, fixing bugs
[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 #define PADDR_MASK_LVL1 0xFFFFFC00
17
18 // === IMPORTS ===
19 extern Uint32   kernel_table0[];
20
21 // === TYPES ===
22 typedef struct
23 {
24         tPAddr  PhysAddr;
25         Uint8   Size;
26         Uint8   Domain;
27         BOOL    bExecutable;
28         BOOL    bGlobal;
29         BOOL    bShared;
30          int    AP;
31 } tMM_PageInfo;
32
33 //#define FRACTAL(table1, addr) ((table1)[ (0xFF8/4*1024) + ((addr)>>20)])
34 #define FRACTAL(table1, addr)   ((table1)[ (0xFF8/4*1024) + ((addr)>>22)])
35 #define USRFRACTAL(addr)        (*((Uint32*)(0x7FDFF000) + ((addr)>>22)))
36 #define TLBIALL()       __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 0" : : "r" (0))
37 #define TLBIMVA(addr)   __asm__ __volatile__ ("mcr p15, 0, %0, c8, c7, 1" : : "r" (addr))
38
39 // === PROTOTYPES ===
40 void    MM_int_GetTables(tVAddr VAddr, Uint32 **Table0, Uint32 **Table1);
41  int    MM_int_AllocateCoarse(tVAddr VAddr, int Domain);
42  int    MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi);
43  int    MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi);
44 tPAddr  MM_AllocateRootTable(void);
45 void    MM_int_CloneTable(Uint32 *DestEnt, int Table);
46 tPAddr  MM_Clone(void);
47 tVAddr  MM_NewKStack(int bGlobal);
48 void    MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info);
49 //void  MM_DumpTables(tVAddr Start, tVAddr End);
50
51 // === GLOBALS ===
52
53 // === CODE ===
54 int MM_InitialiseVirtual(void)
55 {
56         return 0;
57 }
58
59 void MM_int_GetTables(tVAddr VAddr, Uint32 **Table0, Uint32 **Table1)
60 {
61         if(VAddr & 0x80000000) {
62                 *Table0 = (void*)&kernel_table0;        // Level 0
63                 *Table1 = (void*)MM_TABLE1KERN; // Level 1
64         }
65         else {
66                 *Table0 = (void*)MM_TABLE0USER;
67                 *Table1 = (void*)MM_TABLE1USER;
68         }
69 }
70
71 int MM_int_AllocateCoarse(tVAddr VAddr, int Domain)
72 {
73         Uint32  *table0, *table1;
74         Uint32  *desc;
75         tPAddr  paddr;
76         
77         ENTER("xVAddr iDomain", VAddr, Domain);
78
79         MM_int_GetTables(VAddr, &table0, &table1);
80
81         VAddr &= ~(0x400000-1); // 4MiB per "block", 1 Page
82
83         desc = &table0[ VAddr>>20];
84         LOG("desc = %p", desc);
85         
86         // table0: 4 bytes = 1 MiB
87
88         LOG("desc[0] = %x", desc[0]);
89         LOG("desc[1] = %x", desc[1]);
90         LOG("desc[2] = %x", desc[2]);
91         LOG("desc[3] = %x", desc[3]);
92
93         if( (desc[0] & 3) != 0 || (desc[1] & 3) != 0
94          || (desc[2] & 3) != 0 || (desc[3] & 3) != 0 )
95         {
96                 // Error?
97                 LEAVE('i', 1);
98                 return 1;
99         }
100
101         paddr = MM_AllocPhys();
102         if( !paddr )
103         {
104                 // Error
105                 LEAVE('i', 2);
106                 return 2;
107         }
108         
109         *desc = paddr | (Domain << 5) | 1;
110         desc[1] = desc[0] + 0x400;
111         desc[2] = desc[0] + 0x800;
112         desc[3] = desc[0] + 0xC00;
113
114         if( VAddr < 0x80000000 ) {
115 //              Log("USRFRACTAL(%p) = %p", VAddr, &USRFRACTAL(VAddr));
116                 USRFRACTAL(VAddr) = paddr | 3;
117         }
118         else {
119 //              Log("FRACTAL(%p) = %p", VAddr, &FRACTAL(table1, VAddr));
120                 FRACTAL(table1, VAddr) = paddr | 3;
121         }
122
123         // TLBIALL 
124         TLBIALL();      
125
126         LEAVE('i', 0);
127         return 0;
128 }       
129
130 int MM_int_SetPageInfo(tVAddr VAddr, tMM_PageInfo *pi)
131 {
132         Uint32  *table0, *table1;
133         Uint32  *desc;
134
135         ENTER("pVAddr ppi", VAddr, pi);
136
137         MM_int_GetTables(VAddr, &table0, &table1);
138
139         desc = &table0[ VAddr >> 20 ];
140         LOG("desc = %p", desc);
141
142         switch(pi->Size)
143         {
144         case 12:        // Small Page
145         case 16:        // Large Page
146                 LOG("Page");
147                 if( (*desc & 3) == 0 ) {
148                         MM_int_AllocateCoarse( VAddr, pi->Domain );
149                 }
150                 desc = &table1[ VAddr >> 12 ];
151                 LOG("desc (2) = %p", desc);
152                 if( pi->Size == 12 )
153                 {
154                         // Small page
155                         // - Error if overwriting a large page
156                         if( (*desc & 3) == 1 )  LEAVE_RET('i', 1);
157                         if( pi->PhysAddr == 0 ) {
158                                 *desc = 0;
159                                 LEAVE('i', 0);
160                                 return 0;
161                         }
162
163                         *desc = (pi->PhysAddr & 0xFFFFF000) | 2;
164                         if(!pi->bExecutable)    *desc |= 1;     // XN
165                         if(!pi->bGlobal)        *desc |= 1 << 11;       // NG
166                         if( pi->bShared)        *desc |= 1 << 10;       // S
167                         *desc |= (pi->AP & 3) << 4;     // AP
168                         *desc |= ((pi->AP >> 2) & 1) << 9;      // APX
169                         TLBIMVA(VAddr & 0xFFFFF000);
170                         LEAVE('i', 0);
171                         return 0;
172                 }
173                 else
174                 {
175                         // Large page
176                         // TODO: 
177                         Log_Warning("MMVirt", "TODO: Implement large pages in MM_int_SetPageInfo");
178                 }
179                 break;
180         case 20:        // Section or unmapped
181                 Warning("TODO: Implement sections");
182                 break;
183         case 24:        // Supersection
184                 // Error if not aligned
185                 if( VAddr & 0xFFFFFF ) {
186                         LEAVE('i', 1);
187                         return 1;
188                 }
189                 if( (*desc & 3) == 0 || ((*desc & 3) == 2 && (*desc & (1 << 18)))  )
190                 {
191                         if( pi->PhysAddr == 0 ) {
192                                 *desc = 0;
193                                 // TODO: Apply to all entries
194                                 LEAVE('i', 0);
195                                 return 0;
196                         }
197                         // Apply
198                         *desc = pi->PhysAddr & 0xFF000000;
199 //                      *desc |= ((pi->PhysAddr >> 32) & 0xF) << 20;
200 //                      *desc |= ((pi->PhysAddr >> 36) & 0x7) << 5;
201                         *desc |= 2 | (1 << 18);
202                         // TODO: Apply to all entries
203                         LEAVE('i', 0);
204                         return 0;
205                 }
206                 // TODO: What here?
207                 LEAVE('i', 1);
208                 return 1;
209         }
210
211         LEAVE('i', 1);
212         return 1;
213 }
214
215 int MM_int_GetPageInfo(tVAddr VAddr, tMM_PageInfo *pi)
216 {
217         Uint32  *table0, *table1;
218         Uint32  desc;
219
220 //      LogF("MM_int_GetPageInfo: VAddr=%p, pi=%p\n", VAddr, pi);
221         
222         MM_int_GetTables(VAddr, &table0, &table1);
223
224         desc = table0[ VAddr >> 20 ];
225
226 //      if( VAddr > 0x90000000)
227 //              LOG("table0 desc(%p) = %x", &table0[ VAddr >> 20 ], desc);
228         
229         pi->bExecutable = 1;
230         pi->bGlobal = 0;
231         pi->bShared = 0;
232         pi->AP = 0;
233
234         switch( (desc & 3) )
235         {
236         // 0: Unmapped
237         case 0:
238                 pi->PhysAddr = 0;
239                 pi->Size = 20;
240                 pi->Domain = 0;
241                 return 1;
242
243         // 1: Coarse page table
244         case 1:
245                 // Domain from top level table
246                 pi->Domain = (desc >> 5) & 7;
247                 // Get next level
248                 desc = table1[ VAddr >> 12 ];
249 //              LOG("table1 desc(%p) = %x", &table1[ VAddr >> 12 ], desc);
250                 switch( desc & 3 )
251                 {
252                 // 0: Unmapped
253                 case 0: 
254                         pi->Size = 12;
255                         return 1;
256                 // 1: Large Page (64KiB)
257                 case 1:
258                         pi->Size = 16;
259                         pi->PhysAddr = desc & 0xFFFF0000;
260                         pi->AP = ((desc >> 4) & 3) | (((desc >> 9) & 1) << 2);
261                         pi->bExecutable = !(desc & 0x8000);
262                         pi->bShared = (desc >> 10) & 1;
263                         return 0;
264                 // 2/3: Small page
265                 case 2:
266                 case 3:
267                         pi->Size = 12;
268                         pi->PhysAddr = desc & 0xFFFFF000;
269                         pi->bExecutable = !(desc & 1);
270                         pi->bGlobal = !(desc >> 11);
271                         pi->bShared = (desc >> 10) & 1;
272                         pi->AP = ((desc >> 4) & 3) | (((desc >> 9) & 1) << 2);
273                         return 0;
274                 }
275                 return 1;
276         
277         // 2: Section (or Supersection)
278         case 2:
279                 if( desc & (1 << 18) ) {
280                         // Supersection
281                         pi->PhysAddr = desc & 0xFF000000;
282                         pi->PhysAddr |= (Uint64)((desc >> 20) & 0xF) << 32;
283                         pi->PhysAddr |= (Uint64)((desc >> 5) & 0x7) << 36;
284                         pi->Size = 24;
285                         pi->Domain = 0; // Supersections default to zero
286                         pi->AP = ((desc >> 10) & 3) | (((desc >> 15) & 1) << 2);
287                         return 0;
288                 }
289                 
290                 // Section
291                 pi->PhysAddr = desc & 0xFFF80000;
292                 pi->Size = 20;
293                 pi->Domain = (desc >> 5) & 7;
294                 pi->AP = ((desc >> 10) & 3) | (((desc >> 15) & 1) << 2);
295                 return 0;
296
297         // 3: Reserved (invalid)
298         case 3:
299                 pi->PhysAddr = 0;
300                 pi->Size = 20;
301                 pi->Domain = 0;
302                 return 2;
303         }
304         return 2;
305 }
306
307 // --- Exports ---
308 tPAddr MM_GetPhysAddr(tVAddr VAddr)
309 {
310         tMM_PageInfo    pi;
311         if( MM_int_GetPageInfo(VAddr, &pi) )
312                 return 0;
313         return pi.PhysAddr | (VAddr & ((1 << pi.Size)-1));
314 }
315
316 Uint MM_GetFlags(tVAddr VAddr)
317 {
318         tMM_PageInfo    pi;
319          int    ret;
320
321         if( MM_int_GetPageInfo(VAddr, &pi) )
322                 return 0;
323
324         ret = 0;
325         
326         switch(pi.AP)
327         {
328         case AP_KRW_ONLY:
329                 ret |= MM_PFLAG_KERNEL;
330                 break;
331         case AP_KRO_ONLY:
332                 ret |= MM_PFLAG_KERNEL|MM_PFLAG_RO;
333                 break;
334         case AP_RW_BOTH:
335                 break;
336         case AP_RO_BOTH:
337                 ret |= MM_PFLAG_RO;
338                 break;
339         }
340
341         if( pi.bExecutable )    ret |= MM_PFLAG_EXEC;
342         return ret;
343 }
344
345 void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask)
346 {
347         tMM_PageInfo    pi;
348         if( MM_int_GetPageInfo(VAddr, &pi) )
349                 return;
350 }
351
352 int MM_Map(tVAddr VAddr, tPAddr PAddr)
353 {
354         tMM_PageInfo    pi = {0};
355 //      Log("MM_Map %P=>%p", PAddr, VAddr);
356         
357         pi.PhysAddr = PAddr;
358         pi.Size = 12;
359         pi.AP = AP_KRW_ONLY;    // Kernel Read/Write
360         pi.bExecutable = 1;
361         if( MM_int_SetPageInfo(VAddr, &pi) ) {
362                 MM_DerefPhys(pi.PhysAddr);
363                 return 0;
364         }
365         return pi.PhysAddr;
366 }
367
368 tPAddr MM_Allocate(tVAddr VAddr)
369 {
370         tMM_PageInfo    pi = {0};
371         
372         ENTER("pVAddr", VAddr);
373
374         pi.PhysAddr = MM_AllocPhys();
375         if( pi.PhysAddr == 0 )  LEAVE_RET('i', 0);
376         pi.Size = 12;
377         pi.AP = AP_KRW_ONLY;    // Kernel Read/Write
378         pi.bExecutable = 1;
379         if( MM_int_SetPageInfo(VAddr, &pi) ) {
380                 MM_DerefPhys(pi.PhysAddr);
381                 LEAVE('i', 0);
382                 return 0;
383         }
384         LEAVE('x', pi.PhysAddr);
385         return pi.PhysAddr;
386 }
387
388 void MM_Deallocate(tVAddr VAddr)
389 {
390         tMM_PageInfo    pi;
391         
392         if( MM_int_GetPageInfo(VAddr, &pi) )    return ;
393
394         if( pi.PhysAddr == 0 )  return;
395         MM_DerefPhys(pi.PhysAddr);
396         
397         pi.PhysAddr = 0;
398         pi.AP = 0;
399         pi.bExecutable = 0;
400         MM_int_SetPageInfo(VAddr, &pi);
401 }
402
403 tPAddr MM_AllocateRootTable(void)
404 {
405         tPAddr  ret;
406         
407         ret = MM_AllocPhysRange(2, -1);
408         if( ret & 0x1000 ) {
409                 MM_DerefPhys(ret);
410                 MM_DerefPhys(ret+0x1000);
411                 ret = MM_AllocPhysRange(3, -1);
412                 if( ret & 0x1000 ) {
413                         MM_DerefPhys(ret);
414                         ret += 0x1000;
415 //                      Log("MM_AllocateRootTable: Second try not aligned, %P", ret);
416                 }
417                 else {
418                         MM_DerefPhys(ret + 0x2000);
419 //                      Log("MM_AllocateRootTable: Second try aligned, %P", ret);
420                 }
421         }
422 //      else
423 //              Log("MM_AllocateRootTable: Got it in one, %P", ret);
424         return ret;
425 }
426
427 void MM_int_CloneTable(Uint32 *DestEnt, int Table)
428 {
429         tPAddr  table;
430         Uint32  *tmp_map;
431         Uint32  *cur = (void*)MM_TABLE0USER;
432 //      Uint32  *cur = &FRACTAL(MM_TABLE1USER,0);
433          int    i;
434         
435         table = MM_AllocPhys();
436         if(!table)      return ;
437         
438         tmp_map = (void*)MM_MapTemp(table);
439         
440         for( i = 0; i < 1024; i ++ )
441         {
442                 switch(cur[i] & 3)
443                 {
444                 case 0: tmp_map[i] = 0; break;
445                 case 1:
446                         tmp_map[i] = 0;
447                         Log_Error("MMVirt", "TODO: Support large pages in MM_int_CloneTable");
448                         // Large page?
449                         break;
450                 case 2:
451                 case 3:
452                         // Small page
453                         // - If full RW
454                         if( (cur[Table*256] & 0x230) == 0x030 )
455                                 cur[Table*256+i] |= 0x200;      // Set to full RO (Full RO=COW, User RO = RO)
456                         tmp_map[i] = cur[Table*256+i];
457                         break;
458                 }
459         }
460
461         DestEnt[0] = table + 0*0x400 + 1;
462         DestEnt[1] = table + 1*0x400 + 1;
463         DestEnt[2] = table + 2*0x400 + 1;
464         DestEnt[3] = table + 3*0x400 + 1;
465 }
466
467 tPAddr MM_Clone(void)
468 {
469         tPAddr  ret;
470         Uint32  *new_lvl1_1, *new_lvl1_2, *cur;
471         Uint32  *tmp_map;
472          int    i;
473         
474         ret = MM_AllocateRootTable();
475
476         cur = (void*)MM_TABLE0USER;
477         new_lvl1_1 = (void*)MM_MapTemp(ret);
478         new_lvl1_2 = (void*)MM_MapTemp(ret+0x1000);
479         tmp_map = new_lvl1_1;
480         for( i = 0; i < 0x800-4; i ++ )
481         {
482 //              Log("i = %i", i);
483                 if( i == 0x400 )
484                         tmp_map = &new_lvl1_2[-0x400];
485                 switch( cur[i] & 3 )
486                 {
487                 case 0: tmp_map[i] = 0; break;
488                 case 1:
489                         MM_int_CloneTable(&tmp_map[i], i);
490                         i += 3; // Tables are alocated in blocks of 4
491                         break;
492                 case 2:
493                 case 3:
494                         Log_Error("MMVirt", "TODO: Support Sections/Supersections in MM_Clone (i=%i)", i);
495                         tmp_map[i] = 0;
496                         break;
497                 }
498         }
499
500         // Allocate Fractal table
501         {
502                  int    j, num;
503                 tPAddr  tmp = MM_AllocPhys();
504                 Uint32  *table = (void*)MM_MapTemp(tmp);
505                 Uint32  sp;
506                 register Uint32 __SP asm("sp");
507
508                 // Map table to last 4MiB of user space
509                 new_lvl1_2[0x3FC] = tmp + 0*0x400 + 1;
510                 new_lvl1_2[0x3FD] = tmp + 1*0x400 + 1;
511                 new_lvl1_2[0x3FE] = tmp + 2*0x400 + 1;
512                 new_lvl1_2[0x3FF] = tmp + 3*0x400 + 1;
513                 
514                 tmp_map = new_lvl1_1;
515                 for( j = 0; j < 512; j ++ )
516                 {
517                         if( j == 256 )
518                                 tmp_map = &new_lvl1_2[-0x400];
519                         if( (tmp_map[j*4] & 3) == 1 )
520                         {
521                                 table[j] = tmp_map[j*4] & PADDR_MASK_LVL1;// 0xFFFFFC00;
522                                 table[j] |= 0x813;      // nG, Kernel Only, Small page, XN
523                         }
524                         else
525                                 table[j] = 0;
526                 }
527                 // Fractal
528                 table[j++] = (ret + 0x0000) | 0x813;
529                 table[j++] = (ret + 0x1000) | 0x813;
530                 // Nuke the rest
531                 for(      ; j < 1024; j ++ )
532                         table[j] = 0;
533                 
534                 // Get kernel stack bottom
535                 sp = __SP & ~(MM_KSTACK_SIZE-1);
536                 j = (sp / 0x1000) % 1024;
537                 num = MM_KSTACK_SIZE/0x1000;
538                 
539                 // Copy stack pages
540                 for(; num--; j ++, sp += 0x1000)
541                 {
542                         tVAddr  page;
543                         void    *tmp_page;
544                         
545                         page = MM_AllocPhys();
546                         table[j] = page | 0x813;
547
548                         tmp_page = (void*)MM_MapTemp(page);
549                         memcpy(tmp_page, (void*)sp, 0x1000);
550                         MM_FreeTemp( (tVAddr) tmp_page );
551                 }
552         
553                 MM_FreeTemp( (tVAddr)table );
554         }
555
556         MM_FreeTemp( (tVAddr)new_lvl1_1 );
557         MM_FreeTemp( (tVAddr)new_lvl1_2 );
558
559         return ret;
560 }
561
562 tPAddr MM_ClearUser(void)
563 {
564         // TODO: Implement ClearUser
565         return 0;
566 }
567
568 tVAddr MM_MapTemp(tPAddr PAddr)
569 {
570         tVAddr  ret;
571         tMM_PageInfo    pi;
572
573         for( ret = MM_TMPMAP_BASE; ret < MM_TMPMAP_END - PAGE_SIZE; ret += PAGE_SIZE )
574         {
575                 if( MM_int_GetPageInfo(ret, &pi) == 0 )
576                         continue;
577
578 //              Log("MapTemp %P at %p", PAddr, ret);    
579                 MM_RefPhys(PAddr);      // Counter the MM_Deallocate in FreeTemp
580                 MM_Map(ret, PAddr);
581                 
582                 return ret;
583         }
584         Log_Warning("MMVirt", "MM_MapTemp: All slots taken");
585         return 0;
586 }
587
588 void MM_FreeTemp(tVAddr VAddr)
589 {
590         // TODO: Implement FreeTemp
591         if( VAddr < MM_TMPMAP_BASE || VAddr >= MM_TMPMAP_END ) {
592                 Log_Warning("MMVirt", "MM_FreeTemp: Passed an addr not from MM_MapTemp (%p)", VAddr);
593                 return ;
594         }
595         
596         MM_Deallocate(VAddr);
597 }
598
599 tVAddr MM_MapHWPages(tPAddr PAddr, Uint NPages)
600 {
601         tVAddr  ret;
602          int    i;
603         tMM_PageInfo    pi;
604
605         ENTER("xPAddr iNPages", PAddr, NPages);
606
607         // Scan for a location
608         for( ret = MM_HWMAP_BASE; ret < MM_HWMAP_END - NPages * PAGE_SIZE; ret += PAGE_SIZE )
609         {
610 //              LOG("checking %p", ret);
611                 // Check if there is `NPages` free pages
612                 for( i = 0; i < NPages; i ++ )
613                 {
614                         if( MM_int_GetPageInfo(ret + i*PAGE_SIZE, &pi) == 0 )
615                                 break;
616                 }
617                 // Nope, jump to after the used page found and try again
618 //              LOG("i = %i, ==? %i", i, NPages);
619                 if( i != NPages ) {
620                         ret += i * PAGE_SIZE;
621                         continue ;
622                 }
623         
624                 // Map the pages        
625                 for( i = 0; i < NPages; i ++ )
626                         MM_Map(ret+i*PAGE_SIZE, PAddr+i*PAddr);
627                 // and return
628                 LEAVE('p', ret);
629                 return ret;
630         }
631         Log_Warning("MMVirt", "MM_MapHWPages: No space for a %i page block", NPages);
632         LEAVE('p', 0);
633         return 0;
634 }
635
636 tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PAddr)
637 {
638         Log_Error("MMVirt", "TODO: Implement MM_AllocDMA");
639         return 0;
640 }
641
642 void MM_UnmapHWPages(tVAddr Vaddr, Uint Number)
643 {
644         Log_Error("MMVirt", "TODO: Implement MM_UnmapHWPages");
645 }
646
647 tVAddr MM_NewKStack(int bShared)
648 {
649         tVAddr  min_addr, max_addr;
650         tVAddr  addr, ofs;
651
652         if( bShared ) {
653                 min_addr = MM_GLOBALSTACKS;
654                 max_addr = MM_GLOBALSTACKS_END;
655         }
656         else {
657                 min_addr = MM_KSTACK_BASE;
658                 max_addr = MM_KSTACK_END;
659         }
660
661         // Locate a free slot
662         for( addr = min_addr; addr < max_addr; addr += MM_KSTACK_SIZE )
663         {
664                 tMM_PageInfo    pi;
665                 if( MM_int_GetPageInfo(addr+MM_KSTACK_SIZE-PAGE_SIZE, &pi) )    break;
666         }
667
668         // Check for an error   
669         if(addr >= max_addr) {
670                 return 0;
671         }
672
673         // 1 guard page
674         for( ofs = PAGE_SIZE; ofs < MM_KSTACK_SIZE; ofs += PAGE_SIZE )
675         {
676                 if( MM_Allocate(addr + ofs) == 0 )
677                 {
678                         while(ofs)
679                         {
680                                 ofs -= PAGE_SIZE;
681                                 MM_Deallocate(addr + ofs);
682                         }
683                         Log_Warning("MMVirt", "MM_NewKStack: Unable to allocate");
684                         return 0;
685                 }
686         }
687         return addr + ofs;
688 }
689
690 void MM_int_DumpTableEnt(tVAddr Start, size_t Len, tMM_PageInfo *Info)
691 {
692         Log("%p => %8x - 0x%7x %i %x",
693                 Start, Info->PhysAddr-Len, Len,
694                 Info->Domain,
695                 Info->AP
696                 );
697 }
698
699 void MM_DumpTables(tVAddr Start, tVAddr End)
700 {
701         tVAddr  range_start = 0, addr;
702         tMM_PageInfo    pi, pi_old;
703          int    i = 0, inRange=0;
704         
705         pi_old.Size = 0;
706
707         Log("Page Table Dump:");
708         range_start = Start;
709         for( addr = Start; i == 0 || (addr && addr < End); i = 1 )
710         {
711 //              Log("addr = %p", addr);
712                 int rv = MM_int_GetPageInfo(addr, &pi);
713                 if( rv
714                  || pi.Size != pi_old.Size
715                  || pi.Domain != pi_old.Domain
716                  || pi.AP != pi_old.AP
717                  || pi_old.PhysAddr != pi.PhysAddr )
718                 {
719                         if(inRange) {
720                                 MM_int_DumpTableEnt(range_start, addr - range_start, &pi_old);
721                         }
722                         addr &= ~((1 << pi.Size)-1);
723                         range_start = addr;
724                 }
725                 
726                 pi_old = pi;
727                 pi_old.PhysAddr += 1 << pi_old.Size;
728                 addr += 1 << pi_old.Size;
729                 inRange = (rv == 0);
730         }
731         if(inRange)
732                 MM_int_DumpTableEnt(range_start, addr - range_start, &pi);
733         Log("Done");
734 }
735

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