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

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