TODO
[tpg/acess2.git] / KernelLand / Kernel / arch / x86_64 / mm_phys.c
1 /*
2  * Acess2 x86_64 Port
3  * 
4  * Physical Memory Manager
5  */
6 #define DEBUG   0
7 #include <acess.h>
8 #include <mboot.h>
9 #include <mm_virt.h>
10
11 #define TRACE_REF       0
12
13 enum eMMPhys_Ranges
14 {
15         MM_PHYS_16BIT,  // Does anything need this?
16         MM_PHYS_20BIT,  // Real-Mode
17         MM_PHYS_24BIT,  // ISA DMA
18         MM_PHYS_32BIT,  // x86 Hardware
19         MM_PHYS_MAX,    // Doesn't care
20         NUM_MM_PHYS_RANGES
21 };
22
23 // === IMPORTS ===
24 extern char     gKernelBase[];
25 extern char     gKernelEnd[];
26
27 // === PROTOTYPES ===
28 void    MM_InitPhys_Multiboot(tMBoot_Info *MBoot);
29 //tPAddr        MM_AllocPhysRange(int Num, int Bits);
30 //tPAddr        MM_AllocPhys(void);
31 //void  MM_RefPhys(tPAddr PAddr);
32 //void  MM_DerefPhys(tPAddr PAddr);
33  int    MM_int_GetRangeID( tPAddr Addr );
34
35 // === MACROS ===
36 #define PAGE_ALLOC_TEST(__page)         (gaMainBitmap[(__page)>>6] & (1ULL << ((__page)&63)))
37 #define PAGE_ALLOC_SET(__page)          do{gaMainBitmap[(__page)>>6] |= (1ULL << ((__page)&63));}while(0)
38 #define PAGE_ALLOC_CLEAR(__page)        do{gaMainBitmap[(__page)>>6] &= ~(1ULL << ((__page)&63));}while(0)
39 //#define PAGE_MULTIREF_TEST(__page)    (gaMultiBitmap[(__page)>>6] & (1ULL << ((__page)&63)))
40 //#define PAGE_MULTIREF_SET(__page)     do{gaMultiBitmap[(__page)>>6] |= 1ULL << ((__page)&63);}while(0)
41 //#define PAGE_MULTIREF_CLEAR(__page)   do{gaMultiBitmap[(__page)>>6] &= ~(1ULL << ((__page)&63));}while(0)
42
43 // === GLOBALS ===
44 tMutex  glPhysicalPages;
45 Uint64  *gaSuperBitmap = (void*)MM_PAGE_SUPBMP; // 1 bit = 64 Pages, 16 MiB per Word
46 Uint64  *gaMainBitmap = (void*)MM_PAGE_BITMAP;  // 1 bit = 1 Page, 256 KiB per Word
47 Uint64  *gaMultiBitmap = (void*)MM_PAGE_DBLBMP; // Each bit means that the page is being used multiple times
48 Uint32  *gaiPageReferences = (void*)MM_PAGE_COUNTS;     // Reference Counts
49 void    **gapPageNodes = (void*)MM_PAGE_NODES;  // Reference Counts
50 tPAddr  giFirstFreePage;        // First possibly free page
51 Uint64  giPhysRangeFree[NUM_MM_PHYS_RANGES];    // Number of free pages in each range
52 Uint64  giPhysRangeFirst[NUM_MM_PHYS_RANGES];   // First free page in each range
53 Uint64  giPhysRangeLast[NUM_MM_PHYS_RANGES];    // Last free page in each range
54 Uint64  giMaxPhysPage = 0;      // Maximum Physical page
55 // Only used in init, allows the init code to provide pages for use by
56 // the allocator before the bitmaps exist.
57 // 3 entries because the are three calls to MM_AllocPhys in MM_Map
58 #define NUM_STATIC_ALLOC        3
59 tPAddr  gaiStaticAllocPages[NUM_STATIC_ALLOC] = {0};
60
61 // === CODE ===
62 /**
63  * \brief Initialise the physical memory map using a Multiboot 1 map
64  */
65 void MM_InitPhys_Multiboot(tMBoot_Info *MBoot)
66 {
67         tMBoot_MMapEnt  *mmapStart;
68         tMBoot_MMapEnt  *ent;
69         Uint64  maxAddr = 0;
70          int    numPages, superPages;
71          int    i;
72         Uint64  base, size;
73         tVAddr  vaddr;
74         tPAddr  paddr, firstFreePage;
75         
76         ENTER("pMBoot=%p", MBoot);
77         
78         // Scan the physical memory map
79         // Looking for the top of physical memory
80         mmapStart = (void *)( KERNEL_BASE | MBoot->MMapAddr );
81         LOG("mmapStart = %p", mmapStart);
82         ent = mmapStart;
83         while( (Uint)ent < (Uint)mmapStart + MBoot->MMapLength )
84         {
85                 // Adjust for the size of the entry
86                 ent->Size += 4;
87                 LOG("ent={Type:%i,Base:0x%x,Length:%x",
88                         ent->Type, ent->Base, ent->Length);
89                 
90                 // If entry is RAM and is above `maxAddr`, change `maxAddr`
91                 if(ent->Type == 1 && ent->Base + ent->Length > maxAddr)
92                         maxAddr = ent->Base + ent->Length;
93                 
94                 // Go to next entry
95                 ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size );
96         }
97         
98         // Did we find a valid end?
99         if(maxAddr == 0) {
100                 // No, darn, let's just use the HighMem hack
101                 giMaxPhysPage = (MBoot->HighMem >> 2) + 256;    // HighMem is a kByte value
102         }
103         else {
104                 // Goodie, goodie gumdrops
105                 giMaxPhysPage = maxAddr >> 12;
106         }
107         LOG("giMaxPhysPage = 0x%x", giMaxPhysPage);
108         
109         // Find a contigous section of memory to hold it in
110         // - Starting from the end of the kernel
111         // - We also need a region for the super bitmap
112         superPages = ((giMaxPhysPage+64*8-1)/(64*8) + 0xFFF) >> 12;
113         numPages = (giMaxPhysPage + 7) / 8;
114         numPages = (numPages + 0xFFF) >> 12;
115         LOG("numPages = %i, superPages = %i", numPages, superPages);
116         if(maxAddr == 0)
117         {
118                  int    todo = numPages*2 + superPages;
119                 // Ok, naieve allocation, just put it after the kernel
120                 // - Allocated Bitmap
121                 vaddr = MM_PAGE_BITMAP;
122                 paddr = (tPAddr)&gKernelEnd - KERNEL_BASE;
123                 while(todo )
124                 {
125                         // Allocate statics
126                         for( i = 0; i < NUM_STATIC_ALLOC; i++) {
127                                 if(gaiStaticAllocPages[i] != 0) continue;
128                                 gaiStaticAllocPages[i] = paddr;
129                                 paddr += 0x1000;
130                         }
131                         
132                         MM_Map(vaddr, paddr);
133                         vaddr += 0x1000;
134                         paddr += 0x1000;
135                         
136                         todo --;
137                         
138                         if( todo == numPages + superPages )
139                                 vaddr = MM_PAGE_DBLBMP;
140                         if( todo == superPages )
141                                 vaddr = MM_PAGE_SUPBMP;
142                 }
143         }
144         // Scan for a nice range
145         else
146         {
147                  int    todo = numPages*2 + superPages;
148                 paddr = 0;
149                 vaddr = MM_PAGE_BITMAP;
150                 // Scan!
151                 for(
152                         ent = mmapStart;
153                         (Uint)ent < (Uint)mmapStart + MBoot->MMapLength;
154                         ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size )
155                         )
156                 {
157                          int    avail;
158                         
159                         // RAM only please
160                         if( ent->Type != 1 )
161                                 continue;
162                         
163                         // Let's not put it below the kernel, shall we?
164                         if( ent->Base + ent->Size < (tPAddr)&gKernelBase )
165                                 continue;
166                         
167                         LOG("%x <= %x && %x > %x",
168                                 ent->Base, (tPAddr)&gKernelBase,
169                                 ent->Base + ent->Size, (tPAddr)&gKernelEnd - KERNEL_BASE
170                                 );
171                         // Check if the kernel is in this range
172                         if( ent->Base <= (tPAddr)&gKernelBase
173                         && ent->Base + ent->Length > (tPAddr)&gKernelEnd - KERNEL_BASE )
174                         {
175                                 avail = ent->Length >> 12;
176                                 avail -= ((tPAddr)&gKernelEnd - KERNEL_BASE - ent->Base) >> 12;
177                                 paddr = (tPAddr)&gKernelEnd - KERNEL_BASE;
178                         }
179                         // No? then we can use all of the block
180                         else
181                         {
182                                 avail = ent->Length >> 12;
183                                 paddr = ent->Base;
184                         }
185                         
186                         Log("MM_InitPhys_Multiboot: paddr=0x%x, avail=0x%x pg", paddr, avail);
187                         
188                         // Map
189                         while( todo && avail --)
190                         {
191                                 // Static Allocations
192                                 for( i = 0; i < NUM_STATIC_ALLOC && avail; i++) {
193                                         if(gaiStaticAllocPages[i] != 0) continue;
194                                         gaiStaticAllocPages[i] = paddr;
195                                         paddr += 0x1000;
196                                         avail --;
197                                 }
198                                 if(!avail)      break;
199                                 
200                                 // Map
201                                 MM_Map(vaddr, paddr);
202                                 todo --;
203                                 vaddr += 0x1000;
204                                 paddr += 0x1000;
205                                 
206                                 // Alter the destination address when needed
207                                 if(todo == superPages+numPages)
208                                         vaddr = MM_PAGE_DBLBMP;
209                                 if(todo == superPages)
210                                         vaddr = MM_PAGE_SUPBMP;
211                         }
212                         
213                         // Fast quit if there's nothing left to allocate
214                         if( !todo )             break;
215                 }
216         }
217         // Save the current value of paddr to simplify the allocation later
218         firstFreePage = paddr;
219         
220         LOG("Clearing multi bitmap");
221         // Fill the bitmaps
222         memset(gaMultiBitmap, 0, (numPages<<12)/8);
223         // - initialise to one, then clear the avaliable areas
224         memset(gaMainBitmap, -1, (numPages<<12)/8);
225         memset(gaSuperBitmap, -1, (numPages<<12)/(8*64));
226         LOG("Setting main bitmap");
227         // - Clear all Type=1 areas
228         LOG("Clearing valid regions");
229         for(
230                 ent = mmapStart;
231                 (Uint)ent < (Uint)mmapStart + MBoot->MMapLength;
232                 ent = (tMBoot_MMapEnt *)( (Uint)ent + ent->Size )
233                 )
234         {
235                 // Check if the type is RAM
236                 if(ent->Type != 1)      continue;
237                 
238                 // Main bitmap
239                 base = ent->Base >> 12;
240                 size = ent->Size >> 12;
241                 
242                 if(base & 63) {
243                         Uint64  val = -1LL << (base & 63);
244                         gaMainBitmap[base / 64] &= ~val;
245                         size -= (base & 63);
246                         base += 64 - (base & 63);
247                 }
248                 memset( &gaMainBitmap[base / 64], 0, size/8 );
249                 if( size & 7 ) {
250                         Uint64  val = -1LL << (size & 7);
251                         val <<= (size/8)&7;
252                         gaMainBitmap[base / 64] &= ~val;
253                 }
254                 
255                 // Super Bitmap
256                 base = ent->Base >> 12;
257                 size = ent->Size >> 12;
258                 size = (size + (base & 63) + 63) >> 6;
259                 base = base >> 6;
260                 if(base & 63) {
261                         Uint64  val = -1LL << (base & 63);
262                         gaSuperBitmap[base / 64] &= ~val;
263 //                      size -= (base & 63);
264 //                      base += 64 - (base & 63);
265                 }
266         }
267         
268         // Reference the used pages
269         base = (tPAddr)&gKernelBase >> 12;
270         size = firstFreePage >> 12;
271         memset( &gaMainBitmap[base / 64], -1, size/8 );
272         if( size & 7 ) {
273                 Uint64  val = -1LL << (size & 7);
274                 val <<= (size/8)&7;
275                 gaMainBitmap[base / 64] |= val;
276         }
277         
278         // Free the unused static allocs
279         for( i = 0; i < NUM_STATIC_ALLOC; i++) {
280                 if(gaiStaticAllocPages[i] != 0)
281                         continue;
282                 gaMainBitmap[ gaiStaticAllocPages[i] >> (12+6) ]
283                         &= ~(1LL << ((gaiStaticAllocPages[i]>>12)&63));
284         }
285         
286         // Fill the super bitmap
287         LOG("Filling super bitmap");
288         memset(gaSuperBitmap, 0, superPages<<12);
289         for( base = 0; base < (size+63)/64; base ++)
290         {
291                 if( gaMainBitmap[ base ] + 1 == 0 )
292                         gaSuperBitmap[ base/64 ] |= 1LL << (base&63);
293         }
294         
295         // Set free page counts
296         for( base = 1; base < giMaxPhysPage; base ++ )
297         {
298                  int    rangeID;
299                 // Skip allocated
300                 if( gaMainBitmap[ base >> 6 ] & (1LL << (base&63))  )   continue;
301                 
302                 // Get range ID
303                 rangeID = MM_int_GetRangeID( base << 12 );
304                 
305                 // Increment free page count
306                 giPhysRangeFree[ rangeID ] ++;
307                 
308                 // Check for first free page in range
309                 if(giPhysRangeFirst[ rangeID ] == 0)
310                         giPhysRangeFirst[ rangeID ] = base;
311                 // Set last (when the last free page is reached, this won't be
312                 // updated anymore, hence will be correct)
313                 giPhysRangeLast[ rangeID ] = base;
314         }
315         
316         LEAVE('-');
317 }
318
319 void MM_DumpStatistics(void)
320 {
321         // TODO: Statistics for x86_64 PMM
322 }
323
324 /**
325  * \brief Allocate a contiguous range of physical pages with a maximum
326  *        bit size of \a MaxBits
327  * \param Pages Number of pages to allocate
328  * \param MaxBits       Maximum size of the physical address
329  * \note If \a MaxBits is <= 0, any sized address is used (with preference
330  *       to higher addresses)
331  */
332 tPAddr MM_AllocPhysRange(int Pages, int MaxBits)
333 {
334         tPAddr  addr, ret;
335          int    rangeID;
336          int    nFree = 0, i;
337         
338         ENTER("iPages iBits", Pages, MaxBits);
339         
340         if( MaxBits <= 0 || MaxBits >= 64 )     // Speedup for the common case
341                 rangeID = MM_PHYS_MAX;
342         else
343                 rangeID = MM_int_GetRangeID( (1LL << MaxBits) - 1 );
344         
345         LOG("rangeID = %i", rangeID);
346         
347         Mutex_Acquire(&glPhysicalPages);
348         
349         // Check if the range actually has any free pages
350         while(giPhysRangeFree[rangeID] == 0 && rangeID)
351                 rangeID --;
352         
353         LOG("rangeID = %i", rangeID);
354         
355         // What the? Oh, man. No free pages
356         if(giPhysRangeFree[rangeID] == 0) {
357                 Mutex_Release(&glPhysicalPages);
358                 // TODO: Page out
359                 // ATM. Just Warning
360                 Warning(" MM_AllocPhysRange: Out of free pages");
361                 Log_Warning("Arch",
362                         "Out of memory (unable to fulfil request for %i pages), zero remaining",
363                         Pages
364                         );
365                 LEAVE('i', 0);
366                 return 0;
367         }
368         
369         // Check if there is enough in the range
370         if(giPhysRangeFree[rangeID] >= Pages)
371         {
372                 LOG("{%i,0x%x -> 0x%x}",
373                         giPhysRangeFree[rangeID],
374                         giPhysRangeFirst[rangeID], giPhysRangeLast[rangeID]
375                         );
376                 // Do a cheap scan, scanning upwards from the first free page in
377                 // the range
378                 nFree = 0;
379                 addr = giPhysRangeFirst[ rangeID ];
380                 while( addr <= giPhysRangeLast[ rangeID ] )
381                 {
382                         //Log(" MM_AllocPhysRange: addr = 0x%x", addr);
383                         // Check the super bitmap
384                         if( gaSuperBitmap[addr >> (6+6)] + 1 == 0 ) {
385                                 LOG("nFree = %i = 0 (super) (0x%x)", nFree, addr);
386                                 nFree = 0;
387                                 addr += 1LL << (6+6);
388                                 addr &= ~0xFFF; // (1LL << 6+6) - 1
389                                 continue;
390                         }
391                         // Check page block (64 pages)
392                         if( gaMainBitmap[addr >> 6] + 1 == 0) {
393                                 LOG("nFree = %i = 0 (main) (0x%x)", nFree, addr);
394                                 nFree = 0;
395                                 addr += 1LL << (6);
396                                 addr &= ~0x3F;
397                                 continue;
398                         }
399                         // Check individual page
400                         if( gaMainBitmap[addr >> 6] & (1LL << (addr & 63)) ) {
401                                 LOG("nFree = %i = 0 (page) (0x%x)", nFree, addr);
402                                 nFree = 0;
403                                 addr ++;
404                                 continue;
405                         }
406                         nFree ++;
407                         addr ++;
408                         LOG("nFree(%i) == %i (0x%x)", nFree, Pages, addr);
409                         if(nFree == Pages)
410                                 break;
411                 }
412                 LOG("nFree = %i", nFree);
413                 // If we don't find a contiguous block, nFree will not be equal
414                 // to Num, so we set it to zero and do the expensive lookup.
415                 if(nFree != Pages)      nFree = 0;
416         }
417         
418         if( !nFree )
419         {
420                 // Oops. ok, let's do an expensive check (scan down the list
421                 // until a free range is found)
422 //              nFree = 1;
423 //              addr = giPhysRangeLast[ rangeID ];
424                 // TODO: Expensive Check
425                 Mutex_Release(&glPhysicalPages);
426                 // TODO: Page out
427                 // ATM. Just Warning
428                 Warning(" MM_AllocPhysRange: Out of memory (unable to fulfil request for %i pages)", Pages);
429                 Log_Warning("Arch",
430                         "Out of memory (unable to fulfil request for %i pages)",
431                         Pages   
432                         );
433                 LEAVE('i', 0);
434                 return 0;
435         }
436         LOG("nFree = %i, addr = 0x%08x", nFree, addr);
437         
438         // Mark pages as allocated
439         addr -= Pages;
440         for( i = 0; i < Pages; i++, addr++ )
441         {
442                 gaMainBitmap[addr >> 6] |= 1LL << (addr & 63);
443                 if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[addr] ) )
444                         gaiPageReferences[addr] = 1;
445 //              Log("page %P refcount = %i", MM_GetRefCount(addr<<12)); 
446                 rangeID = MM_int_GetRangeID(addr << 12);
447                 giPhysRangeFree[ rangeID ] --;
448                 LOG("%x == %x", addr, giPhysRangeFirst[ rangeID ]);
449                 if(addr == giPhysRangeFirst[ rangeID ])
450                         giPhysRangeFirst[ rangeID ] += 1;
451         }
452         addr -= Pages;
453         ret = addr;     // Save the return address
454         
455         // Update super bitmap
456         Pages += addr & (64-1);
457         addr &= ~(64-1);
458         Pages = (Pages + (64-1)) & ~(64-1);
459         for( i = 0; i < Pages/64; i++ )
460         {
461                 if( gaMainBitmap[ addr >> 6 ] + 1 == 0 )
462                         gaSuperBitmap[addr>>12] |= 1LL << ((addr >> 6) & 63);
463         }
464         
465         Mutex_Release(&glPhysicalPages);
466         #if TRACE_REF
467         Log("MM_AllocPhysRange: ret = %P (Ref %i)", ret << 12, MM_GetRefCount(ret<<12));
468         #endif
469         LEAVE('x', ret << 12);
470         return ret << 12;
471 }
472
473 /**
474  * \brief Allocate a single physical page, with no preference as to address
475  *        size.
476  */
477 tPAddr MM_AllocPhys(void)
478 {
479          int    i;
480         
481         // Hack to allow allocation during setup
482         for(i = 0; i < NUM_STATIC_ALLOC; i++) {
483                 if( gaiStaticAllocPages[i] ) {
484                         tPAddr  ret = gaiStaticAllocPages[i];
485                         gaiStaticAllocPages[i] = 0;
486                         Log("MM_AllocPhys: Return %P, static alloc %i", ret, i);
487                         return ret;
488                 }
489         }
490         
491         return MM_AllocPhysRange(1, -1);
492 }
493
494 /**
495  * \brief Reference a physical page
496  */
497 void MM_RefPhys(tPAddr PAddr)
498 {
499         Uint64  page = PAddr >> 12;
500         
501         if( page > giMaxPhysPage )      return ;
502         
503         if( PAGE_ALLOC_TEST(page) )
504         {
505                 tVAddr  ref_base = ((tVAddr)&gaiPageReferences[ page ]) & ~0xFFF;
506                 // Allocate reference page
507                 if( !MM_GetPhysAddr(ref_base) )
508                 {
509                         const int       pages_per_refpage = PAGE_SIZE/sizeof(gaiPageReferences[0]);
510                          int    i;
511                          int    page_base = page / pages_per_refpage * pages_per_refpage;
512                         if( !MM_Allocate( ref_base ) ) {
513                                 Log_Error("Arch", "Out of memory when allocating reference count page");
514                                 return ;
515                         }
516                         // Fill block
517                         Log("Allocated references for %P-%P", page_base << 12, (page_base+pages_per_refpage)<<12);
518                         for( i = 0; i < pages_per_refpage; i ++ ) {
519                                  int    pg = page_base + i;
520                                 gaiPageReferences[pg] = !!PAGE_ALLOC_TEST(pg);
521                         }
522                 }
523                 gaiPageReferences[page] ++;
524         }
525         else
526         {
527                 // Allocate
528                 PAGE_ALLOC_SET(page);
529                 if( gaMainBitmap[page >> 6] + 1 == 0 )
530                         gaSuperBitmap[page>> 12] |= 1LL << ((page >> 6) & 63);
531                 if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[page] ) )
532                         gaiPageReferences[page] = 1;
533         }
534
535         #if TRACE_REF
536         Log("MM_RefPhys: %P referenced (%i)", page << 12, MM_GetRefCount(page << 12));
537         #endif
538 }
539
540 /**
541  * \brief Dereference a physical page
542  */
543 void MM_DerefPhys(tPAddr PAddr)
544 {
545         Uint64  page = PAddr >> 12;
546         
547         if( PAddr >> 12 > giMaxPhysPage )       return ;
548         
549         if( MM_GetPhysAddr( (tVAddr) &gaiPageReferences[page] ) )
550         {
551                 gaiPageReferences[ page ] --;
552                 if( gaiPageReferences[ page ] == 0 )
553                         PAGE_ALLOC_CLEAR(page);
554         }
555         else
556                 PAGE_ALLOC_CLEAR(page);
557         
558         // Update the free counts if the page was freed
559         if( !PAGE_ALLOC_TEST(page) )
560         {
561                  int    rangeID;
562                 rangeID = MM_int_GetRangeID( PAddr );
563                 giPhysRangeFree[ rangeID ] ++;
564                 if( giPhysRangeFirst[rangeID] > page )
565                         giPhysRangeFirst[rangeID] = page;
566                 if( giPhysRangeLast[rangeID] < page )
567                         giPhysRangeLast[rangeID] = page;
568         }
569         
570         // If the bitmap entry is not -1, unset the bit in the super bitmap
571         if(gaMainBitmap[ page >> 6 ] + 1 != 0 ) {
572                 gaSuperBitmap[page >> 12] &= ~(1LL << ((page >> 6) & 63));
573         }
574         
575         #if TRACE_REF
576         Log("Page %P dereferenced (%i)", page << 12, MM_GetRefCount(page << 12));
577         #endif
578 }
579
580 int MM_GetRefCount( tPAddr PAddr )
581 {
582         PAddr >>= 12;
583         
584         if( PAddr > giMaxPhysPage )     return 0;
585
586         if( MM_GetPhysAddr( (tVAddr)&gaiPageReferences[PAddr] ) ) {
587                 return gaiPageReferences[PAddr];
588         }
589
590         if( PAGE_ALLOC_TEST(PAddr) )
591         {
592                 return 1;
593         }
594         return 0;
595 }
596
597 /**
598  * \brief Takes a physical address and returns the ID of its range
599  * \param Addr  Physical address of page
600  * \return Range ID from eMMPhys_Ranges
601  */
602 int MM_int_GetRangeID( tPAddr Addr )
603 {
604         if(Addr >> 32)
605                 return MM_PHYS_MAX;
606         else if(Addr >> 24)
607                 return MM_PHYS_32BIT;
608         else if(Addr >> 20)
609                 return MM_PHYS_24BIT;
610         else if(Addr >> 16)
611                 return MM_PHYS_20BIT;
612         else
613                 return MM_PHYS_16BIT;
614 }
615
616 int MM_SetPageNode(tPAddr PAddr, void *Node)
617 {
618         tPAddr  page = PAddr >> 12;
619         tVAddr  node_page = ((tVAddr)&gapPageNodes[page]) & ~(PAGE_SIZE-1);
620
621 //      if( !MM_GetRefCount(PAddr) )    return 1;
622         
623         if( !MM_GetPhysAddr(node_page) ) {
624                 if( !MM_Allocate(node_page) )
625                         return -1;
626                 memset( (void*)node_page, 0, PAGE_SIZE );
627         }
628
629         gapPageNodes[page] = Node;
630         return 0;
631 }
632
633 int MM_GetPageNode(tPAddr PAddr, void **Node)
634 {
635 //      if( !MM_GetRefCount(PAddr) )    return 1;
636         PAddr >>= 12;
637         
638         if( !MM_GetPhysAddr( (tVAddr)&gapPageNodes[PAddr] ) ) {
639                 *Node = NULL;
640                 return 0;
641         }
642
643         *Node = gapPageNodes[PAddr];
644         return 0;
645 }
646

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