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

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