SMP MTRRs
[akaros.git] / user / testpmap.c
1 //#ifdef LAB >= 4
2
3 #include <inc/lib.h>
4
5 int sequence_length = 16;
6 int sequence[] = { 0,  1,   1,   2,   3, 
7                    5,  8,  13,  21,  34, 
8                   55, 89, 144, 233, 377, 610};
9
10 void
11 mark_page(int* pg, int i) {
12   memset(pg, 0, PGSIZE);
13
14   // now dump a non-random sequence into the page
15   // offset by i
16   int j;
17   for (j = 0; j < sequence_length; j++)
18     pg[j] = i + sequence[j];
19 }
20
21 int
22 test_page(int* pg, int i) {
23   int j;
24   for (j = 0; j < sequence_length; j++)
25     if (pg[j] != i + sequence[j])
26       return 1;
27
28   return 0;
29 }
30
31 void
32 print_marked_page(int* pg) {
33   int j;
34   for (j = 0; j < (sequence_length-1); j++)
35     cprintf("%d, ", pg[j]);
36
37   cprintf("%d", pg[j]);
38 }
39
40 void
41 print_expected_mark(int i) {
42   int j;
43   for (j = 0; j < (sequence_length-1); j++)
44     cprintf("%d, ", sequence[j]+i);
45   
46   cprintf("%d", sequence[j]+i);
47 }
48
49 int n, va, r, initva, maxpa, maxva, maxnum, failures;
50 int *page_id;
51
52 int
53 alloc_range(int initaddr, int maxpa, int startn) {
54   n = startn;
55   maxnum = maxpa / PGSIZE;
56   initva = initaddr;
57   maxva = initva + maxpa;
58   
59   cprintf ("[%08x] trying to alloc pages in range [%08x, %08x]\n", env->env_id, initva, maxva);
60
61   // how many pages can I alloc? 
62   // - limit to 256 M worth of pages
63   for (va = initva; va < maxva; va += PGSIZE, n++) { 
64     // alloc a page 
65     if ((r = sys_mem_alloc(0, va, PTE_P | PTE_U | PTE_W | PTE_AVAIL)) < 0) { 
66       //cprintf("\nsys_mem_alloc failed: %e", r);
67       break;
68     }
69
70     //page_id = (int*)va;
71     //*page_id = n;              // mark this page...
72     //memset((int*)va, n, PGSIZE / sizeof(int));
73     mark_page((int*)va, n);
74
75     if ( (((va - initva) / PGSIZE) % 128) == 0) cprintf(".");
76   }
77   cprintf("\n");
78
79   cprintf("[%08x] able to allocate [%d] pages of requested [%d] pages\n", env->env_id, n, maxnum);
80
81   maxva = va;
82   return n;
83 }
84
85 int
86 test_range(int startva, int endva, int startn) {
87   int c;
88   cprintf("[%08x] testing pages in [%08x, %08x] to see if they look okay\n", env->env_id, startva, endva);
89   n = startn;
90   failures = 0;  
91   for (va = startva, c = 0; va < endva; va += PGSIZE, n++, c++) { 
92     page_id = (int*)va;
93
94     if (test_page((int*)va, n)) {
95       cprintf("\n[%08x] unexpected value at [%08x]:\n  {", env->env_id, va);
96       print_marked_page((int*)va);
97       cprintf("} should be\n  {");
98       print_expected_mark(n);
99       cprintf("}");
100       
101       failures++;
102     } else {
103       Pte pte = vpt[VPN(va)];
104       int perm = (PTE_U | PTE_P | PTE_W | PTE_AVAIL);
105
106       if ((pte & perm) != perm) {
107         cprintf("\n[%08x] unexpected PTE permissions [04x] for address [%08x]\n {", env->env_id, pte & perm, va);
108         failures++;
109       }
110
111       //      cprintf("\n value at [%08x]: {", va);
112       //print_marked_page((int*)va);
113       //cprintf("} should be {");
114       //print_expected_mark(n);
115       //cprintf("}");
116     }
117
118     if ( (((va - startva) / PGSIZE) % 128) == 0) cprintf(".");
119     //if ((va % PDMAP) == 0) cprintf(".");
120   }
121   cprintf("\n");
122
123   cprintf("[%08x] tested %d pages: %d failed assertions.\n", env->env_id, c, failures);
124
125   return failures;
126 }
127
128 void
129 unmap_range(int startva, int endva) {
130   cprintf("[%08x] unmapping range [%08x, %08x].\n", env->env_id, startva, endva);
131   int xva, z;
132   for (z=0, xva = startva; xva < endva; xva += PGSIZE, z++) { 
133     sys_mem_unmap(0, xva);
134   }
135   cprintf("[%08x] unmapped %d pages.\n", env->env_id, z);
136 }
137
138 int
139 duplicate_range(int startva, int dupeva, int nbytes) {
140   cprintf("[%08x] duplicating range [%08x, %08x] at [%08x, %08x]\n", 
141          env->env_id, startva, startva+nbytes, dupeva, dupeva+nbytes);
142   int xva, r, k;
143   for (xva = 0, k = 0; xva < nbytes; xva += PGSIZE, k+=PGSIZE) { 
144     if ((r = sys_mem_map(0, startva+xva, 0, dupeva+xva, PTE_P | PTE_U | PTE_W | PTE_USER)) < 0) {
145       cprintf ("[%08x] duplicate_range FAILURE: %e\n", env->env_id, r);
146       return r;
147     }
148   }
149
150   return k;
151 }
152
153 // This tries to stress test the pmap code...
154 // Not the most intelligent testing strategy, 
155 // just hammer at it and see if it breaks.
156 void
157 umain(int argc, char **argv)
158 {  
159   int max, max2, k, j, i, dupesize, dupen;
160
161   for (i = 0; i < 2; i++) { // might as well do this multiple times to stress the system...
162     cprintf("PMAPTEST[%08x] starting ROUND %d.\n", env->env_id, i);
163
164     // Try to allocate as many pages as possible...
165     k = alloc_range(UTEXT+PDMAP, (256 * 1024 * 1024), 0);       // alloc as many as possible
166     max = maxva;                                                // save maximum memory size
167     test_range(UTEXT+PDMAP, max, 0);                            // test if all are unique pages
168
169     // If we've corrupted kernel memory, a yield might expose a problem.
170     cprintf("PMAPTEST[%08x] yielding...\n", env->env_id);
171     sys_yield();
172     cprintf("PMAPTEST[%08x] back.\n", env->env_id);
173
174     // Free a couple of pages for use by page tables and other envs...
175     unmap_range(max-16 * PGSIZE, max);                           // free some pages so we have wiggle room, if extra
176     max -= 16 * PGSIZE;                                          // pages are needed for page tables...
177     
178     // Unmap last 1024 pages and then try to reallocate them in the same place
179     unmap_range(max - PDMAP, max);                              // unmap last 1024 pages
180     j = alloc_range(max - PDMAP, PDMAP, 0);                     // try to realloc them (<1024 if other envs alloc'd)
181     max2 = maxva; // max2 <= max && max2 >= (max - PDMAP)
182     test_range(max - PDMAP, max2, 0);                           // test if new pages are unique
183   
184     // Create duplicate mappings of the last 1024
185     dupesize = duplicate_range(max2-PDMAP, max+PDMAP, j*PGSIZE); // create duplicate mappings
186     test_range(max2-PDMAP, max2-PDMAP+dupesize, 0);             // test lower mapping
187     test_range(max+PDMAP, max + PDMAP + dupesize, 0);           // test upper mapping
188     dupen = *((int*)(max+PDMAP));
189   
190     // Remove one of the duplicate mappings and then unmap and realloc the last 1024 pages
191     unmap_range(max2-PDMAP, max2-PDMAP+dupesize);           // unmap lower mapping
192     j = alloc_range(max2-PDMAP, PDMAP, 0);                  // try to alloc something, should be below 1024 (really? other envs?)
193     unmap_range(max2-2*PDMAP, max2 - PDMAP);                // free 1024 pages
194     j = alloc_range(max2-2*PDMAP, PDMAP, 0);                // alloc new pages for free'd 1024
195     //max2 = maxva; // max2 <= old_max2 - PDMAP
196     
197     // Test ranges...
198     test_range(UTEXT+PDMAP, max2-2*PDMAP, 0);              // test entire lower range of pages
199     test_range(max2-2*PDMAP, maxva, 0);                    // test entire lower range of pages
200     test_range(max+PDMAP, max + PDMAP + dupesize, dupen);  // test upper range
201
202     // Free everything
203     unmap_range(UTEXT+PDMAP, maxva);                        
204     unmap_range(max+PDMAP, max+PDMAP+dupesize);    
205     
206     //unmap_range(UTEXT+PDMAP, max);
207   }
208
209 }
210
211 //#endif
212
213
214
215