initial commit
[mit-jos.git] / user / testpmap.c
blobf38cff5936e438d44f93de74e38ffd137304c5bd
1 //#ifdef LAB >= 4
3 #include <inc/lib.h>
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};
10 void
11 mark_page(int* pg, int i) {
12 memset(pg, 0, PGSIZE);
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];
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;
28 return 0;
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]);
37 cprintf("%d", pg[j]);
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);
46 cprintf("%d", sequence[j]+i);
49 int n, va, r, initva, maxpa, maxva, maxnum, failures;
50 int *page_id;
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;
59 cprintf ("[%08x] trying to alloc pages in range [%08x, %08x]\n", env->env_id, initva, maxva);
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;
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);
75 if ( (((va - initva) / PGSIZE) % 128) == 0) cprintf(".");
77 cprintf("\n");
79 cprintf("[%08x] able to allocate [%d] pages of requested [%d] pages\n", env->env_id, n, maxnum);
81 maxva = va;
82 return n;
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;
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("}");
101 failures++;
102 } else {
103 Pte pte = vpt[VPN(va)];
104 int perm = (PTE_U | PTE_P | PTE_W | PTE_AVAIL);
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++;
111 // cprintf("\n value at [%08x]: {", va);
112 //print_marked_page((int*)va);
113 //cprintf("} should be {");
114 //print_expected_mark(n);
115 //cprintf("}");
118 if ( (((va - startva) / PGSIZE) % 128) == 0) cprintf(".");
119 //if ((va % PDMAP) == 0) cprintf(".");
121 cprintf("\n");
123 cprintf("[%08x] tested %d pages: %d failed assertions.\n", env->env_id, c, failures);
125 return failures;
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);
135 cprintf("[%08x] unmapped %d pages.\n", env->env_id, z);
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;
150 return k;
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)
159 int max, max2, k, j, i, dupesize, dupen;
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);
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
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);
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...
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
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));
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
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
202 // Free everything
203 unmap_range(UTEXT+PDMAP, maxva);
204 unmap_range(max+PDMAP, max+PDMAP+dupesize);
206 //unmap_range(UTEXT+PDMAP, max);
211 //#endif