11d504a4a34d03e9300549deacb29e8c3b77da24
[tpg/acess2.git] / validate_vmem.c
1 /*
2  */
3 #include <acess.h>
4 #include <mm_virt.h>
5 #include "include/vmem_layout.h"
6 #include <threads_int.h>
7 #include <stdbool.h>
8
9 extern Uint64   giPageCount;
10 extern tProcess *gAllProcesses;
11 extern char     gKernelEnd[];
12
13 // === PROTOTYPES ===
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);
19
20 // === CODE ===
21 void Validate_VirtualMemoryUsage(void)
22 {
23          int    *refcount = calloc(giPageCount, sizeof(int));
24         Uint32  *tmp_pd = malloc( PAGE_SIZE );
25         Uint32  *tmp_pt = malloc( PAGE_SIZE );
26         
27         // Pass #1 - Count PT references
28         for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
29         {
30                 Uint    cr3 = proc->MemState.CR3;
31                 _ref_mem(refcount, cr3/PAGE_SIZE, proc, 0);
32
33                 _load_page(tmp_pd, cr3);
34                 const Uint32    *pdir = tmp_pd;
35                 for(int i = 0; i < 1024; i ++)
36                 {
37                         if( _should_skip_pde(proc, i, pdir[i]) )
38                                 continue ;
39                         Uint32  ptaddr = pdir[i] & ~0xFFF;
40                         
41                         _ref_mem(refcount, ptaddr/PAGE_SIZE, proc, (void*)(i*1024*PAGE_SIZE));
42                 }
43         }
44         
45         
46         for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
47         {
48                 Uint    cr3 = proc->MemState.CR3;
49                 
50                 _load_page(tmp_pd, cr3);
51                 const Uint32    *pdir = tmp_pd;
52                 for(int i = 0; i < 1024; i ++)
53                 {
54                         Uint32  pde = pdir[i];
55                         if( _should_skip_pde(proc, i, pde) )
56                                 continue ;
57                         
58                         Uint32  ptaddr = pde & ~0xFFF;
59                         
60                         // 
61                         if( proc->PID == 0 || refcount[ ptaddr >> 12 ] == 1 )
62                         {
63                                 _load_page(tmp_pt, ptaddr);
64                                 Validate_VirtualMemoryUsage_PT(tmp_pt, proc, i, refcount);
65                         }
66                 }
67         }
68         
69         for( int i = 0; i < giPageCount; i ++ )
70         {
71                  int    recorded_refc = MM_GetRefCount(i*PAGE_SIZE);
72                 
73                 void    *node;
74                 if( MM_GetPageNode(i*PAGE_SIZE, &node) == 0 && node != NULL )
75                         _ref_mem(refcount, i, NULL, 0);
76                 
77                 // 0x9F000 - BIOS memory area
78                 // 0xA0000+ - ROM area
79                 if( 0x9F <= i && i < 0x100 ) {
80                         _ref_mem(refcount, i, NULL, 0);
81                 }
82                 
83                 if( recorded_refc != refcount[i] ) {
84                         Debug("Refcount mismatch %P - recorded %i != checked %i",
85                                 (tPAddr)i*PAGE_SIZE, recorded_refc, refcount[i]);
86                 }
87         }
88         
89         // Output.
90         for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
91         {
92                 Debug("%p(%i %s)", proc, proc->PID, proc->FirstThread->ThreadName);
93                 Uint    cr3 = proc->MemState.CR3;
94                 
95                 _load_page(tmp_pd, cr3);
96                 const Uint32    *pdir = tmp_pd;
97                 for(int i = 0; i < 1024; i ++)
98                 {
99                         Uint32  pde = pdir[i];
100                         if( _should_skip_pde(proc, i, pde) )
101                                 continue ;
102                         Uint32  paddr = pde & ~0xFFF;
103                         
104                         if( proc->PID != 0 && refcount[ paddr >> 12 ] > 1 )
105                                 continue ;
106                         
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]
112                                         );
113                         }
114         
115                         _load_page(tmp_pt, paddr);
116                         const Uint32 *ptab = tmp_pt;
117                         for( int j = 0; j < 1024; j ++ ) 
118                         {
119                                 if( !(ptab[j] & 1) )
120                                         continue ;
121                                 Uint32  pageaddr = ptab[j] & ~0xFFF;
122                                 
123                                 if( pageaddr/PAGE_SIZE >= giPageCount )
124                                 {
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
128                                         //      );
129                                 }
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]
135                                                 );
136                                 }
137                         }
138                 }
139         }
140 }
141
142 void Validate_VirtualMemoryUsage_PT(const Uint32 *PTable, const tProcess *Proc, int PDIndex, int *RefCounts)
143 {
144         for( int i = 0; i < 1024; i ++ )
145         {
146                 // Ignore the 3GB+1MB area
147                 if( PDIndex == 768 && i < 256 )
148                         continue ;
149                 // And ignore anything from the end of the kernel up to 3GB4MB
150                 if( PDIndex == 768 && i > ((tVAddr)gKernelEnd-KERNEL_BASE)/PAGE_SIZE )
151                         continue ;
152                 
153                 Uint32  pte = PTable[i];
154                 if( !(pte & 1) )
155                         continue ;
156                 
157                 Uint32  paddr = pte & ~0xFFF;
158                 Uint    page = paddr >> 12;
159                 
160                 _ref_mem(RefCounts, page, Proc, (void*)((PDIndex*1024+i)*PAGE_SIZE));
161         }
162 }
163
164 bool _should_skip_pde(const tProcess *Proc, int idx, Uint32 pde)
165 {
166         if( !(pde & 1) )
167                 return true;
168         
169         if( (pde & ~0xFFF) == Proc->MemState.CR3 ) {
170                 return true;
171         }
172
173         if( idx == PAGE_TABLE_ADDR>>22 ) {
174                 if( (pde & ~0xFFF) != Proc->MemState.CR3 ) {
175                         // Bad!
176                 }
177         }       
178         
179         return false;
180 }
181
182 void _ref_mem(int *RefCounts, Uint PageNum, const tProcess *Proc, void *addr)
183 {
184         if( PageNum == 0x1001000/PAGE_SIZE ) {
185                 Debug("frame #0x%x %i:%p", PageNum, Proc?Proc->PID:-1, addr);
186         }
187         if( PageNum >= giPageCount )
188                 ;
189         else
190                 RefCounts[ PageNum ] ++;
191 }
192
193 void _load_page(Uint32 *dst, tPAddr phys)
194 {
195         const void *src = MM_MapTemp(phys);
196         memcpy(dst, src, PAGE_SIZE);
197         MM_FreeTemp( (void*)src);
198 }
199

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