5 #include "include/vmem_layout.h"
6 #include <threads_int.h>
9 extern Uint64 giPageCount;
10 extern tProcess *gAllProcesses;
11 extern char gKernelEnd[];
14 void Validate_VirtualMemoryUsage(void);
15 void Validate_VirtualMemoryUsage_PT(const Uint32 *PTable, const tProcess *Proc, int PDIndex, int *RefCounts);
16 static bool _should_skip_pde(const tProcess *Proc, int idx, Uint32 pde);
17 static void _ref_mem(int *RefCounts, Uint PageNum, const tProcess *Proc, void *addr);
18 static void _load_page(Uint32 *dst, tPAddr phys);
21 void Validate_VirtualMemoryUsage(void)
23 int *refcount = calloc(giPageCount, sizeof(int));
24 Uint32 *tmp_pd = malloc( PAGE_SIZE );
25 Uint32 *tmp_pt = malloc( PAGE_SIZE );
27 // Pass #1 - Count PT references
28 for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
30 Uint cr3 = proc->MemState.CR3;
31 _ref_mem(refcount, cr3/PAGE_SIZE, proc, 0);
33 _load_page(tmp_pd, cr3);
34 const Uint32 *pdir = tmp_pd;
35 for(int i = 0; i < 1024; i ++)
37 if( _should_skip_pde(proc, i, pdir[i]) )
39 Uint32 ptaddr = pdir[i] & ~0xFFF;
41 _ref_mem(refcount, ptaddr/PAGE_SIZE, proc, (void*)(i*1024*PAGE_SIZE));
46 for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
48 Uint cr3 = proc->MemState.CR3;
50 _load_page(tmp_pd, cr3);
51 const Uint32 *pdir = tmp_pd;
52 for(int i = 0; i < 1024; i ++)
55 if( _should_skip_pde(proc, i, pde) )
58 Uint32 ptaddr = pde & ~0xFFF;
61 if( proc->PID == 0 || refcount[ ptaddr >> 12 ] == 1 )
63 _load_page(tmp_pt, ptaddr);
64 Validate_VirtualMemoryUsage_PT(tmp_pt, proc, i, refcount);
69 for( int i = 0; i < giPageCount; i ++ )
71 int recorded_refc = MM_GetRefCount(i*PAGE_SIZE);
74 if( MM_GetPageNode(i*PAGE_SIZE, &node) == 0 && node != NULL )
75 _ref_mem(refcount, i, NULL, 0);
77 // 0x9F000 - BIOS memory area
78 // 0xA0000+ - ROM area
79 if( 0x9F <= i && i < 0x100 ) {
80 _ref_mem(refcount, i, NULL, 0);
83 if( recorded_refc != refcount[i] ) {
84 Debug("Refcount mismatch %P - recorded %i != checked %i",
85 (tPAddr)i*PAGE_SIZE, recorded_refc, refcount[i]);
90 for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
92 Debug("%p(%i %s)", proc, proc->PID, proc->FirstThread->ThreadName);
93 Uint cr3 = proc->MemState.CR3;
95 _load_page(tmp_pd, cr3);
96 const Uint32 *pdir = tmp_pd;
97 for(int i = 0; i < 1024; i ++)
100 if( _should_skip_pde(proc, i, pde) )
102 Uint32 paddr = pde & ~0xFFF;
104 if( proc->PID != 0 && refcount[ paddr >> 12 ] > 1 )
107 if( MM_GetRefCount(paddr) != refcount[paddr>>12] ) {
108 Debug("Table %p(%i %s) @%p %P %i!=%i",
109 proc, proc->PID, proc->FirstThread->ThreadName,
110 i*1024*PAGE_SIZE, paddr,
111 MM_GetRefCount(paddr), refcount[paddr>>12]
115 _load_page(tmp_pt, paddr);
116 const Uint32 *ptab = tmp_pt;
117 for( int j = 0; j < 1024; j ++ )
121 Uint32 pageaddr = ptab[j] & ~0xFFF;
123 if( pageaddr/PAGE_SIZE >= giPageCount )
125 //Debug("PG %p(%i %s) @%p %P not in RAM",
126 // proc, proc->PID, proc->FirstThread->ThreadName,
127 // (i*1024+j)*PAGE_SIZE, pageaddr
130 else if( MM_GetRefCount(pageaddr) != refcount[pageaddr>>12] ) {
131 Debug("PG %p(%i %s) @%p %P %i!=%i",
132 proc, proc->PID, proc->FirstThread->ThreadName,
133 (i*1024+j)*PAGE_SIZE, pageaddr,
134 MM_GetRefCount(pageaddr), refcount[pageaddr>>12]
142 void Validate_VirtualMemoryUsage_PT(const Uint32 *PTable, const tProcess *Proc, int PDIndex, int *RefCounts)
144 for( int i = 0; i < 1024; i ++ )
146 // Ignore the 3GB+1MB area
147 if( PDIndex == 768 && i < 256 )
149 // And ignore anything from the end of the kernel up to 3GB4MB
150 if( PDIndex == 768 && i > ((tVAddr)gKernelEnd-KERNEL_BASE)/PAGE_SIZE )
153 Uint32 pte = PTable[i];
157 Uint32 paddr = pte & ~0xFFF;
158 Uint page = paddr >> 12;
160 _ref_mem(RefCounts, page, Proc, (void*)((PDIndex*1024+i)*PAGE_SIZE));
164 bool _should_skip_pde(const tProcess *Proc, int idx, Uint32 pde)
169 if( (pde & ~0xFFF) == Proc->MemState.CR3 ) {
173 if( idx == PAGE_TABLE_ADDR>>22 ) {
174 if( (pde & ~0xFFF) != Proc->MemState.CR3 ) {
182 void _ref_mem(int *RefCounts, Uint PageNum, const tProcess *Proc, void *addr)
184 if( PageNum == 0x1001000/PAGE_SIZE ) {
185 Debug("frame #0x%x %i:%p", PageNum, Proc?Proc->PID:-1, addr);
187 if( PageNum >= giPageCount )
190 RefCounts[ PageNum ] ++;
193 void _load_page(Uint32 *dst, tPAddr phys)
195 const void *src = MM_MapTemp(phys);
196 memcpy(dst, src, PAGE_SIZE);
197 MM_FreeTemp( (void*)src);