Added setjmp/longjmp support to the kernel
[akaros.git] / kern / src / testing.c
1
2 #ifdef __SHARC__
3 #pragma nosharc
4 #endif
5
6 #include <arch/mmu.h>
7 #include <arch/arch.h>
8 #include <bitmask.h>
9 #include <smp.h>
10
11 #include <ros/memlayout.h>
12 #include <ros/common.h>
13 #include <ros/bcq.h>
14 #include <ros/ucq.h>
15
16 #include <atomic.h>
17 #include <stdio.h>
18 #include <assert.h>
19 #include <string.h>
20 #include <testing.h>
21 #include <trap.h>
22 #include <trap.h>
23 #include <process.h>
24 #include <syscall.h>
25 #include <time.h>
26 #include <kfs.h>
27 #include <multiboot.h>
28 #include <pmap.h>
29 #include <page_alloc.h>
30 #include <pmap.h>
31 #include <slab.h>
32 #include <kmalloc.h>
33 #include <hashtable.h>
34 #include <radix.h>
35 #include <monitor.h>
36 #include <kthread.h>
37 #include <schedule.h>
38 #include <umem.h>
39 #include <ucq.h>
40 #include <setjmp.h>
41
42 #define l1 (available_caches.l1)
43 #define l2 (available_caches.l2)
44 #define l3 (available_caches.l3)
45
46 #ifdef CONFIG_X86
47
48 void test_ipi_sending(void)
49 {
50         extern handler_t (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
51         int8_t state = 0;
52
53         register_interrupt_handler(interrupt_handlers, I_TESTING,
54                                    test_hello_world_handler, NULL);
55         enable_irqsave(&state);
56         cprintf("\nCORE 0 sending broadcast\n");
57         send_broadcast_ipi(I_TESTING);
58         udelay(3000000);
59         cprintf("\nCORE 0 sending all others\n");
60         send_all_others_ipi(I_TESTING);
61         udelay(3000000);
62         cprintf("\nCORE 0 sending self\n");
63         send_self_ipi(I_TESTING);
64         udelay(3000000);
65         cprintf("\nCORE 0 sending ipi to physical 1\n");
66         send_ipi(0x01, I_TESTING);
67         udelay(3000000);
68         cprintf("\nCORE 0 sending ipi to physical 2\n");
69         send_ipi(0x02, I_TESTING);
70         udelay(3000000);
71         cprintf("\nCORE 0 sending ipi to physical 3\n");
72         send_ipi(0x03, I_TESTING);
73         udelay(3000000);
74         cprintf("\nCORE 0 sending ipi to physical 15\n");
75         send_ipi(0x0f, I_TESTING);
76         udelay(3000000);
77         cprintf("\nCORE 0 sending ipi to logical 2\n");
78         send_group_ipi(0x02, I_TESTING);
79         udelay(3000000);
80         cprintf("\nCORE 0 sending ipi to logical 1\n");
81         send_group_ipi(0x01, I_TESTING);
82         udelay(3000000);
83         cprintf("\nDone!\n");
84         disable_irqsave(&state);
85 }
86
87 // Note this never returns and will muck with any other timer work
88 void test_pic_reception(void)
89 {
90         register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
91         pit_set_timer(100,TIMER_RATEGEN); // totally arbitrary time
92         pic_unmask_irq(0);
93         cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
94         cprintf("PIC2 Mask = 0x%04x\n", inb(PIC2_DATA));
95         unmask_lapic_lvt(LAPIC_LVT_LINT0);
96         cprintf("Core %d's LINT0: 0x%08x\n", core_id(), read_mmreg32(LAPIC_LVT_LINT0));
97         enable_irq();
98         while(1);
99 }
100
101 void test_ioapic_pit_reroute(void) 
102 {
103         register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
104         ioapic_route_irq(0, 3); 
105
106         cprintf("Starting pit on core 3....\n");
107         udelay(3000000);
108         pit_set_timer(0xFFFE,TIMER_RATEGEN); // totally arbitrary time
109         
110         udelay(3000000);
111         ioapic_unroute_irq(0);
112         udelay(300000);
113         cprintf("Masked pit. Waiting before return...\n");
114         udelay(3000000);
115 }
116
117 #endif // CONFIG_X86
118
119
120 void test_print_info(void)
121 {
122         cprintf("\nCORE 0 asking all cores to print info:\n");
123         smp_call_function_all(test_print_info_handler, NULL, 0);
124         cprintf("\nDone!\n");
125 }
126
127 void test_page_coloring(void) 
128 {
129 /*
130         //Print the different cache properties of our machine
131         print_cache_properties("L1", l1);
132         cprintf("\n");
133         print_cache_properties("L2", l2);
134         cprintf("\n");
135         print_cache_properties("L3", l3);
136         cprintf("\n");
137
138         //Print some stats about our memory
139         cprintf("Max Address: %llu\n", MAX_VADDR);
140         cprintf("Num Pages: %u\n", npages);
141
142         //Declare a local variable for allocating pages 
143         page_t* page;
144
145         cprintf("Contents of the page free list:\n");
146         for(int i=0; i<llc_cache->num_colors; i++) {
147                 cprintf("  COLOR %d:\n", i);
148                 LIST_FOREACH(page, &colored_page_free_list[i], pg_link) {
149                         cprintf("    Page: %d\n", page2ppn(page));
150                 }
151         }
152
153         //Run through and allocate all pages through l1_page_alloc
154         cprintf("Allocating from L1 page colors:\n");
155         for(int i=0; i<get_cache_num_page_colors(l1); i++) {
156                 cprintf("  COLOR %d:\n", i);
157                 while(colored_page_alloc(l1, &page, i) != -ENOMEM)
158                         cprintf("    Page: %d\n", page2ppn(page));
159         }
160
161         //Put all the pages back by reinitializing
162         page_init();
163         
164         //Run through and allocate all pages through l2_page_alloc
165         cprintf("Allocating from L2 page colors:\n");
166         for(int i=0; i<get_cache_num_page_colors(l2); i++) {
167                 cprintf("  COLOR %d:\n", i);
168                 while(colored_page_alloc(l2, &page, i) != -ENOMEM)
169                         cprintf("    Page: %d\n", page2ppn(page));
170         }
171
172         //Put all the pages back by reinitializing
173         page_init();
174         
175         //Run through and allocate all pages through l3_page_alloc
176         cprintf("Allocating from L3 page colors:\n");
177         for(int i=0; i<get_cache_num_page_colors(l3); i++) {
178                 cprintf("  COLOR %d:\n", i);
179                 while(colored_page_alloc(l3, &page, i) != -ENOMEM)
180                         cprintf("    Page: %d\n", page2ppn(page));
181         }
182         
183         //Put all the pages back by reinitializing
184         page_init();
185         
186         //Run through and allocate all pages through page_alloc
187         cprintf("Allocating from global allocator:\n");
188         while(upage_alloc(&page) != -ENOMEM)
189                 cprintf("    Page: %d\n", page2ppn(page));
190         
191         if(colored_page_alloc(l2, &page, 0) != -ENOMEM)
192                 cprintf("Should not get here, all pages should already be gone!\n");
193         cprintf("All pages gone for sure...\n");
194         
195         //Now lets put a few pages back using page_free..
196         cprintf("Reinserting pages via page_free and reallocating them...\n");
197         page_free(&pages[0]);
198         page_free(&pages[15]);
199         page_free(&pages[7]);
200         page_free(&pages[6]);
201         page_free(&pages[4]);
202
203         while(upage_alloc(&page) != -ENOMEM)
204                 cprintf("Page: %d\n", page2ppn(page));  
205         
206         page_init();
207 */
208 }
209
210 void test_color_alloc() {
211         size_t checkpoint = 0;
212         uint8_t* colors_map = kmalloc(BYTES_FOR_BITMASK(llc_cache->num_colors), 0);
213         cache_color_alloc(l2, colors_map);
214         cache_color_alloc(l3, colors_map);
215         cache_color_alloc(l3, colors_map);
216         cache_color_alloc(l2, colors_map);
217         cache_color_free(llc_cache, colors_map);
218         cache_color_free(llc_cache, colors_map);
219         cache_color_free(llc_cache, colors_map);
220         cache_color_free(llc_cache, colors_map);
221         cache_color_free(llc_cache, colors_map);
222         cache_color_free(llc_cache, colors_map);
223         cache_color_free(llc_cache, colors_map);
224         cache_color_free(llc_cache, colors_map);
225         cache_color_free(llc_cache, colors_map);
226         cache_color_free(llc_cache, colors_map);
227         cache_color_free(llc_cache, colors_map);
228         cache_color_free(llc_cache, colors_map);
229         cache_color_free(llc_cache, colors_map);
230         cache_color_free(llc_cache, colors_map);
231         cache_color_free(llc_cache, colors_map);
232         cache_color_free(llc_cache, colors_map);
233         cache_color_free(l2, colors_map);
234         cache_color_free(llc_cache, colors_map);
235         cache_color_free(llc_cache, colors_map);
236
237 print_cache_colors:
238         printk("L1 free colors, tot colors: %d\n", l1->num_colors);
239         PRINT_BITMASK(l1->free_colors_map, l1->num_colors);
240         printk("L2 free colors, tot colors: %d\n", l2->num_colors);
241         PRINT_BITMASK(l2->free_colors_map, l2->num_colors);
242         printk("L3 free colors, tot colors: %d\n", l3->num_colors);
243         PRINT_BITMASK(l3->free_colors_map, l3->num_colors);
244         printk("Process allocated colors\n");
245         PRINT_BITMASK(colors_map, llc_cache->num_colors);
246         printk("test_color_alloc() complete!\n");
247 }
248
249 barrier_t test_cpu_array;
250
251 void test_barrier(void)
252 {
253         cprintf("Core 0 initializing barrier\n");
254         init_barrier(&test_cpu_array, num_cpus);
255         cprintf("Core 0 asking all cores to print ids, barrier, rinse, repeat\n");
256         smp_call_function_all(test_barrier_handler, NULL, 0);
257 }
258
259 void test_interrupts_irqsave(void)
260 {
261         int8_t state = 0;
262         printd("Testing Nesting Enabling first, turning ints off:\n");
263         disable_irq();
264         printd("Interrupts are: %x\n", irq_is_enabled());
265         assert(!irq_is_enabled());
266         printd("Enabling IRQSave\n");
267         enable_irqsave(&state);
268         printd("Interrupts are: %x\n", irq_is_enabled());
269         assert(irq_is_enabled());
270         printd("Enabling IRQSave Again\n");
271         enable_irqsave(&state);
272         printd("Interrupts are: %x\n", irq_is_enabled());
273         assert(irq_is_enabled());
274         printd("Disabling IRQSave Once\n");
275         disable_irqsave(&state);
276         printd("Interrupts are: %x\n", irq_is_enabled());
277         assert(irq_is_enabled());
278         printd("Disabling IRQSave Again\n");
279         disable_irqsave(&state);
280         printd("Interrupts are: %x\n", irq_is_enabled());
281         assert(!irq_is_enabled());
282         printd("Done.  Should have been 0, 200, 200, 200, 0\n");
283
284         printd("Testing Nesting Disabling first, turning ints on:\n");
285         state = 0;
286         enable_irq();
287         printd("Interrupts are: %x\n", irq_is_enabled());
288         assert(irq_is_enabled());
289         printd("Disabling IRQSave Once\n");
290         disable_irqsave(&state);
291         printd("Interrupts are: %x\n", irq_is_enabled());
292         assert(!irq_is_enabled());
293         printd("Disabling IRQSave Again\n");
294         disable_irqsave(&state);
295         printd("Interrupts are: %x\n", irq_is_enabled());
296         assert(!irq_is_enabled());
297         printd("Enabling IRQSave Once\n");
298         enable_irqsave(&state);
299         printd("Interrupts are: %x\n", irq_is_enabled());
300         assert(!irq_is_enabled());
301         printd("Enabling IRQSave Again\n");
302         enable_irqsave(&state);
303         printd("Interrupts are: %x\n", irq_is_enabled());
304         assert(irq_is_enabled());
305         printd("Done.  Should have been 200, 0, 0, 0, 200 \n");
306
307         state = 0;
308         disable_irq();
309         printd("Ints are off, enabling then disabling.\n");
310         enable_irqsave(&state);
311         printd("Interrupts are: %x\n", irq_is_enabled());
312         assert(irq_is_enabled());
313         disable_irqsave(&state);
314         printd("Interrupts are: %x\n", irq_is_enabled());
315         assert(!irq_is_enabled());
316         printd("Done.  Should have been 200, 0\n");
317
318         state = 0;
319         enable_irq();
320         printd("Ints are on, enabling then disabling.\n");
321         enable_irqsave(&state);
322         printd("Interrupts are: %x\n", irq_is_enabled());
323         assert(irq_is_enabled());
324         disable_irqsave(&state);
325         printd("Interrupts are: %x\n", irq_is_enabled());
326         assert(irq_is_enabled());
327         printd("Done.  Should have been 200, 200\n");
328
329         state = 0;
330         disable_irq();
331         printd("Ints are off, disabling then enabling.\n");
332         disable_irqsave(&state);
333         printd("Interrupts are: %x\n", irq_is_enabled());
334         assert(!irq_is_enabled());
335         enable_irqsave(&state);
336         printd("Interrupts are: %x\n", irq_is_enabled());
337         assert(!irq_is_enabled());
338         printd("Done.  Should have been 0, 0\n");
339
340         state = 0;
341         enable_irq();
342         printd("Ints are on, disabling then enabling.\n");
343         disable_irqsave(&state);
344         printd("Interrupts are: %x\n", irq_is_enabled());
345         assert(!irq_is_enabled());
346         enable_irqsave(&state);
347         printd("Interrupts are: %x\n", irq_is_enabled());
348         assert(irq_is_enabled());
349         printd("Done.  Should have been 0, 200\n");
350
351         disable_irq();
352         cprintf("Passed enable_irqsave tests\n");
353 }
354
355 void test_bitmasks(void)
356 {
357 #define masksize 67
358         DECL_BITMASK(mask, masksize);
359         printk("size of mask %d\n", sizeof(mask));
360         CLR_BITMASK(mask, masksize);
361         PRINT_BITMASK(mask, masksize);
362         printk("cleared\n");
363         SET_BITMASK_BIT(mask, 0);
364         SET_BITMASK_BIT(mask, 11);
365         SET_BITMASK_BIT(mask, 17);
366         SET_BITMASK_BIT(mask, masksize-1);
367         printk("bits set\n");
368         PRINT_BITMASK(mask, masksize);
369         DECL_BITMASK(mask2, masksize);
370         COPY_BITMASK(mask2, mask, masksize);
371         printk("copy of original mask, should be the same as the prev\n");
372         PRINT_BITMASK(mask2, masksize);
373         CLR_BITMASK_BIT(mask, 11);
374         printk("11 cleared\n");
375         PRINT_BITMASK(mask, masksize);
376         printk("bit 17 is %d (should be 1)\n", GET_BITMASK_BIT(mask, 17));
377         printk("bit 11 is %d (should be 0)\n", GET_BITMASK_BIT(mask, 11));
378         FILL_BITMASK(mask, masksize);
379         PRINT_BITMASK(mask, masksize);
380         printk("should be all 1's, except for a few at the end\n");
381         printk("Is Clear?: %d (should be 0)\n", BITMASK_IS_CLEAR(mask,masksize));
382         CLR_BITMASK(mask, masksize);
383         PRINT_BITMASK(mask, masksize);
384         printk("Is Clear?: %d (should be 1)\n", BITMASK_IS_CLEAR(mask,masksize));
385         printk("should be cleared\n");
386 }
387
388 checklist_t *RO the_global_list;
389
390 static void test_checklist_handler(struct hw_trapframe *hw_tf, void *data)
391 {
392         udelay(1000000);
393         cprintf("down_checklist(%x,%d)\n", the_global_list, core_id());
394         down_checklist(the_global_list);
395 }
396
397 void test_checklists(void)
398 {
399         INIT_CHECKLIST(a_list, MAX_NUM_CPUS);
400         the_global_list = &a_list;
401         printk("Checklist Build, mask size: %d\n", sizeof(a_list.mask.bits));
402         printk("mask\n");
403         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
404         SET_BITMASK_BIT(a_list.mask.bits, 11);
405         printk("Set bit 11\n");
406         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
407
408         CLR_BITMASK(a_list.mask.bits, a_list.mask.size);
409         INIT_CHECKLIST_MASK(a_mask, MAX_NUM_CPUS);
410         FILL_BITMASK(a_mask.bits, num_cpus);
411         //CLR_BITMASK_BIT(a_mask.bits, core_id());
412         //SET_BITMASK_BIT(a_mask.bits, 1);
413         //printk("New mask (1, 17, 25):\n");
414         printk("Created new mask, filled up to num_cpus\n");
415         PRINT_BITMASK(a_mask.bits, a_mask.size);
416         printk("committing new mask\n");
417         commit_checklist_wait(&a_list, &a_mask);
418         printk("Old mask (copied onto):\n");
419         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
420         //smp_call_function_single(1, test_checklist_handler, 0, 0);
421
422         smp_call_function_all(test_checklist_handler, NULL, 0);
423
424         printk("Waiting on checklist\n");
425         waiton_checklist(&a_list);
426         printk("Done Waiting!\n");
427
428 }
429
430 atomic_t a, b, c;
431
432 static void test_incrementer_handler(struct hw_trapframe *tf, void *data)
433 {
434         assert(data);
435         atomic_inc(data);
436 }
437
438 static void test_null_handler(struct hw_trapframe *tf, void *data)
439 {
440         asm volatile("nop");
441 }
442
443 void test_smp_call_functions(void)
444 {
445         int i;
446         atomic_init(&a, 0);
447         atomic_init(&b, 0);
448         atomic_init(&c, 0);
449         handler_wrapper_t *waiter0 = 0, *waiter1 = 0, *waiter2 = 0, *waiter3 = 0,
450                           *waiter4 = 0, *waiter5 = 0;
451         uint8_t me = core_id();
452         printk("\nCore %d: SMP Call Self (nowait):\n", me);
453         printk("---------------------\n");
454         smp_call_function_self(test_hello_world_handler, NULL, 0);
455         printk("\nCore %d: SMP Call Self (wait):\n", me);
456         printk("---------------------\n");
457         smp_call_function_self(test_hello_world_handler, NULL, &waiter0);
458         smp_call_wait(waiter0);
459         printk("\nCore %d: SMP Call All (nowait):\n", me);
460         printk("---------------------\n");
461         smp_call_function_all(test_hello_world_handler, NULL, 0);
462         printk("\nCore %d: SMP Call All (wait):\n", me);
463         printk("---------------------\n");
464         smp_call_function_all(test_hello_world_handler, NULL, &waiter0);
465         smp_call_wait(waiter0);
466         printk("\nCore %d: SMP Call All-Else Individually, in order (nowait):\n", me);
467         printk("---------------------\n");
468         for(i = 1; i < num_cpus; i++)
469                 smp_call_function_single(i, test_hello_world_handler, NULL, 0);
470         printk("\nCore %d: SMP Call Self (wait):\n", me);
471         printk("---------------------\n");
472         smp_call_function_self(test_hello_world_handler, NULL, &waiter0);
473         smp_call_wait(waiter0);
474         printk("\nCore %d: SMP Call All-Else Individually, in order (wait):\n", me);
475         printk("---------------------\n");
476         for(i = 1; i < num_cpus; i++)
477         {
478                 smp_call_function_single(i, test_hello_world_handler, NULL, &waiter0);
479                 smp_call_wait(waiter0);
480         }
481         printk("\nTesting to see if any IPI-functions are dropped when not waiting:\n");
482         printk("A: %d, B: %d, C: %d (should be 0,0,0)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
483         smp_call_function_all(test_incrementer_handler, &a, 0);
484         smp_call_function_all(test_incrementer_handler, &b, 0);
485         smp_call_function_all(test_incrementer_handler, &c, 0);
486         // if i can clobber a previous IPI, the interleaving might do it
487         smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
488         smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
489         smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
490         smp_call_function_single(4 % num_cpus, test_incrementer_handler, &a, 0);
491         smp_call_function_single(5 % num_cpus, test_incrementer_handler, &b, 0);
492         smp_call_function_single(6 % num_cpus, test_incrementer_handler, &c, 0);
493         smp_call_function_all(test_incrementer_handler, &a, 0);
494         smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
495         smp_call_function_all(test_incrementer_handler, &b, 0);
496         smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
497         smp_call_function_all(test_incrementer_handler, &c, 0);
498         smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
499         // wait, so we're sure the others finish before printing.
500         // without this, we could (and did) get 19,18,19, since the B_inc
501         // handler didn't finish yet
502         smp_call_function_self(test_null_handler, NULL, &waiter0);
503         // need to grab all 5 handlers (max), since the code moves to the next free.
504         smp_call_function_self(test_null_handler, NULL, &waiter1);
505         smp_call_function_self(test_null_handler, NULL, &waiter2);
506         smp_call_function_self(test_null_handler, NULL, &waiter3);
507         smp_call_function_self(test_null_handler, NULL, &waiter4);
508         smp_call_wait(waiter0);
509         smp_call_wait(waiter1);
510         smp_call_wait(waiter2);
511         smp_call_wait(waiter3);
512         smp_call_wait(waiter4);
513         printk("A: %d, B: %d, C: %d (should be 19,19,19)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
514         printk("Attempting to deadlock by smp_calling with an outstanding wait:\n");
515         smp_call_function_self(test_null_handler, NULL, &waiter0);
516         printk("Sent one\n");
517         smp_call_function_self(test_null_handler, NULL, &waiter1);
518         printk("Sent two\n");
519         smp_call_wait(waiter0);
520         printk("Wait one\n");
521         smp_call_wait(waiter1);
522         printk("Wait two\n");
523         printk("\tMade it through!\n");
524         printk("Attempting to deadlock by smp_calling more than are available:\n");
525         printk("\tShould see an Insufficient message and a kernel warning.\n");
526         if (smp_call_function_self(test_null_handler, NULL, &waiter0))
527                 printk("\tInsufficient handlers to call function (0)\n");
528         if (smp_call_function_self(test_null_handler, NULL, &waiter1))
529                 printk("\tInsufficient handlers to call function (1)\n");
530         if (smp_call_function_self(test_null_handler, NULL, &waiter2))
531                 printk("\tInsufficient handlers to call function (2)\n");
532         if (smp_call_function_self(test_null_handler, NULL, &waiter3))
533                 printk("\tInsufficient handlers to call function (3)\n");
534         if (smp_call_function_self(test_null_handler, NULL, &waiter4))
535                 printk("\tInsufficient handlers to call function (4)\n");
536         if (smp_call_function_self(test_null_handler, NULL, &waiter5))
537                 printk("\tInsufficient handlers to call function (5)\n");
538         smp_call_wait(waiter0);
539         smp_call_wait(waiter1);
540         smp_call_wait(waiter2);
541         smp_call_wait(waiter3);
542         smp_call_wait(waiter4);
543         smp_call_wait(waiter5);
544         printk("\tMade it through!\n");
545
546         printk("Done\n");
547 }
548
549 #ifdef CONFIG_X86
550 void test_lapic_status_bit(void)
551 {
552         register_interrupt_handler(interrupt_handlers, I_TESTING,
553                                    test_incrementer_handler, &a);
554         #define NUM_IPI 100000
555         atomic_set(&a,0);
556         printk("IPIs received (should be 0): %d\n", a);
557         for(int i = 0; i < NUM_IPI; i++) {
558                 send_ipi(7, I_TESTING);
559                 lapic_wait_to_send();
560         }
561         // need to wait a bit to let those IPIs get there
562         udelay(5000000);
563         printk("IPIs received (should be %d): %d\n", a, NUM_IPI);
564         // hopefully that handler never fires again.  leaving it registered for now.
565 }
566 #endif // CONFIG_X86
567
568 /************************************************************/
569 /* ISR Handler Functions */
570
571 void test_hello_world_handler(struct hw_trapframe *hw_tf, void *data)
572 {
573         int trapno;
574         #if defined(CONFIG_X86)
575         trapno = hw_tf->tf_trapno;
576         #else
577         trapno = 0;
578         #endif
579
580         cprintf("Incoming IRQ, ISR: %d on core %d with tf at %p\n",
581                 trapno, core_id(), hw_tf);
582 }
583
584 spinlock_t print_info_lock = SPINLOCK_INITIALIZER_IRQSAVE;
585
586 void test_print_info_handler(struct hw_trapframe *hw_tf, void *data)
587 {
588         uint64_t tsc = read_tsc();
589
590         spin_lock_irqsave(&print_info_lock);
591         cprintf("----------------------------\n");
592         cprintf("This is Core %d\n", core_id());
593         cprintf("Timestamp = %lld\n", tsc);
594 #ifdef CONFIG_X86
595         cprintf("Hardware core %d\n", hw_core_id());
596         cprintf("MTRR_DEF_TYPE = 0x%08x\n", read_msr(IA32_MTRR_DEF_TYPE));
597         cprintf("MTRR Phys0 Base = 0x%016llx, Mask = 0x%016llx\n",
598                 read_msr(0x200), read_msr(0x201));
599         cprintf("MTRR Phys1 Base = 0x%016llx, Mask = 0x%016llx\n",
600                 read_msr(0x202), read_msr(0x203));
601         cprintf("MTRR Phys2 Base = 0x%016llx, Mask = 0x%016llx\n",
602                 read_msr(0x204), read_msr(0x205));
603         cprintf("MTRR Phys3 Base = 0x%016llx, Mask = 0x%016llx\n",
604                 read_msr(0x206), read_msr(0x207));
605         cprintf("MTRR Phys4 Base = 0x%016llx, Mask = 0x%016llx\n",
606                 read_msr(0x208), read_msr(0x209));
607         cprintf("MTRR Phys5 Base = 0x%016llx, Mask = 0x%016llx\n",
608                 read_msr(0x20a), read_msr(0x20b));
609         cprintf("MTRR Phys6 Base = 0x%016llx, Mask = 0x%016llx\n",
610                 read_msr(0x20c), read_msr(0x20d));
611         cprintf("MTRR Phys7 Base = 0x%016llx, Mask = 0x%016llx\n",
612                 read_msr(0x20e), read_msr(0x20f));
613 #endif // CONFIG_X86
614         cprintf("----------------------------\n");
615         spin_unlock_irqsave(&print_info_lock);
616 }
617
618 void test_barrier_handler(struct hw_trapframe *hw_tf, void *data)
619 {
620         cprintf("Round 1: Core %d\n", core_id());
621         waiton_barrier(&test_cpu_array);
622         waiton_barrier(&test_cpu_array);
623         waiton_barrier(&test_cpu_array);
624         waiton_barrier(&test_cpu_array);
625         waiton_barrier(&test_cpu_array);
626         waiton_barrier(&test_cpu_array);
627         cprintf("Round 2: Core %d\n", core_id());
628         waiton_barrier(&test_cpu_array);
629         cprintf("Round 3: Core %d\n", core_id());
630         // uncomment to see it fucked up
631         //cprintf("Round 4: Core %d\n", core_id());
632 }
633
634 static void test_waiting_handler(struct hw_trapframe *hw_tf, void *data)
635 {
636         atomic_dec(data);
637 }
638
639 #ifdef CONFIG_X86
640 void test_pit(void)
641 {
642         cprintf("Starting test for PIT now (10s)\n");
643         udelay_pit(10000000);
644         cprintf("End now\n");
645         cprintf("Starting test for TSC (if stable) now (10s)\n");
646         udelay(10000000);
647         cprintf("End now\n");
648
649         cprintf("Starting test for LAPIC (if stable) now (10s)\n");
650         enable_irq();
651         lapic_set_timer(10000000, FALSE);
652
653         atomic_t waiting;
654         atomic_init(&waiting, 1);
655         register_interrupt_handler(interrupt_handlers, I_TESTING,
656                                    test_waiting_handler, &waiting);
657         while(atomic_read(&waiting))
658                 cpu_relax();
659         cprintf("End now\n");
660 }
661
662 void test_circ_buffer(void)
663 {
664         int arr[5] = {0, 1, 2, 3, 4};
665
666         for (int i = 0; i < 5; i++) {
667                 FOR_CIRC_BUFFER(i, 5, j)
668                         printk("Starting with current = %d, each value = %d\n", i, j);
669         }
670         return;
671 }
672
673 static void test_km_handler(uint32_t srcid, long a0, long a1, long a2)
674 {
675         printk("Received KM on core %d from core %d: arg0= %p, arg1 = %p, "
676                "arg2 = %p\n", core_id(), srcid, a0, a1, a2);
677         return;
678 }
679
680 void test_kernel_messages(void)
681 {
682         printk("Testing Kernel Messages\n");
683         /* Testing sending multiples, sending different types, alternating, and
684          * precendence (the immediates should trump the others) */
685         printk("sending 5 IMMED to core 1, sending (#,deadbeef,0)\n");
686         for (int i = 0; i < 5; i++)
687                 send_kernel_message(1, test_km_handler, (long)i, 0xdeadbeef, 0,
688                                     KMSG_IMMEDIATE);
689         udelay(5000000);
690         printk("sending 5 routine to core 1, sending (#,cafebabe,0)\n");
691         for (int i = 0; i < 5; i++)
692                 send_kernel_message(1, test_km_handler, (long)i, 0xcafebabe, 0,
693                                     KMSG_ROUTINE);
694         udelay(5000000);
695         printk("sending 10 routine and 3 immediate to core 2\n");
696         for (int i = 0; i < 10; i++)
697                 send_kernel_message(2, test_km_handler, (long)i, 0xcafebabe, 0,
698                                     KMSG_ROUTINE);
699         for (int i = 0; i < 3; i++)
700                 send_kernel_message(2, test_km_handler, (long)i, 0xdeadbeef, 0,
701                                     KMSG_IMMEDIATE);
702         udelay(5000000);
703         printk("sending 5 ea alternating to core 2\n");
704         for (int i = 0; i < 5; i++) {
705                 send_kernel_message(2, test_km_handler, (long)i, 0xdeadbeef, 0,
706                                     KMSG_IMMEDIATE);
707                 send_kernel_message(2, test_km_handler, (long)i, 0xcafebabe, 0,
708                                     KMSG_ROUTINE);
709         }
710         udelay(5000000);
711         return;
712 }
713 #endif // CONFIG_X86
714 static void test_single_cache(int iters, size_t size, int align, int flags,
715                               void (*ctor)(void *, size_t),
716                               void (*dtor)(void *, size_t))
717 {
718         struct kmem_cache *test_cache;
719         void *objects[iters];
720         test_cache = kmem_cache_create("test_cache", size, align, flags, ctor, dtor);
721         printk("Testing Kmem Cache:\n");
722         print_kmem_cache(test_cache);
723         for (int i = 0; i < iters; i++) {
724                 objects[i] = kmem_cache_alloc(test_cache, 0);
725                 printk("Buffer %d addr = %p\n", i, objects[i]);
726         }
727         for (int i = 0; i < iters; i++) {
728                 kmem_cache_free(test_cache, objects[i]);
729         }
730         kmem_cache_destroy(test_cache);
731         printk("\n\n\n\n");
732 }
733
734 void a_ctor(void *buf, size_t size)
735 {
736         printk("constructin tests\n");
737 }
738 void a_dtor(void *buf, size_t size)
739 {
740         printk("destructin tests\n");
741 }
742
743 void test_slab(void)
744 {
745         test_single_cache(10, 128, 512, 0, 0, 0);
746         test_single_cache(10, 128, 4, 0, a_ctor, a_dtor);
747         test_single_cache(10, 1024, 16, 0, 0, 0);
748 }
749
750 void test_kmalloc(void)
751 {
752         printk("Testing Kmalloc\n");
753         void *bufs[NUM_KMALLOC_CACHES + 1];     
754         size_t size;
755         for (int i = 0; i < NUM_KMALLOC_CACHES + 1; i++){
756                 size = (KMALLOC_SMALLEST << i) - KMALLOC_OFFSET;
757                 bufs[i] = kmalloc(size, 0);
758                 printk("Size %d, Addr = %p\n", size, bufs[i]);
759         }
760         for (int i = 0; i < NUM_KMALLOC_CACHES; i++) {
761                 printk("Freeing buffer %d\n", i);
762                 kfree(bufs[i]);
763         }
764         printk("Testing a large kmalloc\n");
765         size = (KMALLOC_LARGEST << 2);
766         bufs[0] = kmalloc(size, 0);
767         printk("Size %d, Addr = %p\n", size, bufs[0]);
768         kfree(bufs[0]);
769 }
770
771 static size_t test_hash_fn_col(void *k)
772 {
773         return (size_t)k % 2; // collisions in slots 0 and 1
774 }
775
776 void test_hashtable(void)
777 {
778         struct test {int x; int y;};
779         struct test tstruct[10];
780
781         struct hashtable *h;
782         uintptr_t k = 5;
783         struct test *v = &tstruct[0];
784
785         h = create_hashtable(32, __generic_hash, __generic_eq);
786         
787         // test inserting one item, then finding it again
788         printk("Tesing one item, insert, search, and removal\n");
789         if(!hashtable_insert(h, (void*)k, v))
790                 printk("Failed to insert to hashtable!\n");
791         v = NULL;
792         if (!(v = hashtable_search(h, (void*)k)))
793                 printk("Failed to find in hashtable!\n");
794         if (v != &tstruct[0])
795                 printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[0]);
796         v = NULL;
797         if (!(v = hashtable_remove(h, (void*)k)))
798                 printk("Failed to remove from hashtable!\n");
799         // shouldn't be able to find it again
800         if ((v = hashtable_search(h, (void*)k)))
801                 printk("Should not have been able to find in hashtable!\n");
802         
803         printk("Tesing a bunch of items, insert, search, and removal\n");
804         for (int i = 0; i < 10; i++) {
805                 k = i; // vary the key, we don't do KEY collisions
806                 if(!hashtable_insert(h, (void*)k, &tstruct[i]))
807                         printk("Failed to insert iter %d to hashtable!\n", i);
808         }
809         // read out the 10 items
810         for (int i = 0; i < 10; i++) {
811                 k = i;
812                 if (!(v = hashtable_search(h, (void*)k)))
813                         printk("Failed to find in hashtable!\n");
814                 if (v != &tstruct[i])
815                         printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[i]);
816         }
817         if (hashtable_count(h) != 10)
818                 printk("Wrong accounting of number of elements!\n");
819         // remove the 10 items
820         for (int i = 0; i < 10; i++) {
821                 k = i;
822                 if (!(v = hashtable_remove(h, (void*)k)))
823                         printk("Failed to remove from hashtable!\n");
824         }
825         // make sure they are all gone
826         for (int i = 0; i < 10; i++) {
827                 k = i;
828                 if ((v = hashtable_search(h, (void*)k)))
829                         printk("Should not have been able to find in hashtable!\n");
830         }
831         if (hashtable_count(h))
832                 printk("Wrong accounting of number of elements!\n");
833         hashtable_destroy(h);
834
835         // same test of a bunch of items, but with collisions.
836         printk("Tesing a bunch of items with collisions, etc.\n");
837         h = create_hashtable(32, test_hash_fn_col, __generic_eq);
838         // insert 10 items
839         for (int i = 0; i < 10; i++) {
840                 k = i; // vary the key, we don't do KEY collisions
841                 if(!hashtable_insert(h, (void*)k, &tstruct[i]))
842                         printk("Failed to insert iter %d to hashtable!\n", i);
843         }
844         // read out the 10 items
845         for (int i = 0; i < 10; i++) {
846                 k = i;
847                 if (!(v = hashtable_search(h, (void*)k)))
848                         printk("Failed to find in hashtable!\n");
849                 if (v != &tstruct[i])
850                         printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[i]);
851         }
852         if (hashtable_count(h) != 10)
853                 printk("Wrong accounting of number of elements!\n");
854         // remove the 10 items
855         for (int i = 0; i < 10; i++) {
856                 k = i;
857                 if (!(v = hashtable_remove(h, (void*)k)))
858                         printk("Failed to remove from hashtable!\n");
859         }
860         // make sure they are all gone
861         for (int i = 0; i < 10; i++) {
862                 k = i;
863                 if ((v = hashtable_search(h, (void*)k)))
864                         printk("Should not have been able to find in hashtable!\n");
865         }
866         if (hashtable_count(h))
867                 printk("Wrong accounting of number of elements!\n");
868         hashtable_destroy(h);
869 }
870
871 /* Ghetto test, only tests one prod or consumer at a time */
872 void test_bcq(void)
873 {
874         /* Tests a basic struct */
875         struct my_struct {
876                 int x;
877                 int y;
878         };
879         struct my_struct in_struct, out_struct;
880         
881         DEFINE_BCQ_TYPES(test, struct my_struct, 16);
882         struct test_bcq t_bcq;
883         bcq_init(&t_bcq, struct my_struct, 16);
884         
885         in_struct.x = 4;
886         in_struct.y = 5;
887         out_struct.x = 1;
888         out_struct.y = 2;
889         
890         bcq_enqueue(&t_bcq, &in_struct, 16, 5);
891         bcq_dequeue(&t_bcq, &out_struct, 16);
892         printk("out x %d. out y %d\n", out_struct.x, out_struct.y);
893         
894         /* Tests the BCQ a bit more, esp with overflow */
895         #define NR_ELEM_A_BCQ 8 /* NOTE: this must be a power of 2! */
896         DEFINE_BCQ_TYPES(my, int, NR_ELEM_A_BCQ);
897         struct my_bcq a_bcq;
898         bcq_init(&a_bcq, int, NR_ELEM_A_BCQ);
899         
900         int y = 2;
901         int output[100];
902         int retval[100];
903
904         /* Helpful debugger */
905         void print_a_bcq(struct my_bcq *bcq)
906         {
907                 printk("A BCQ (made of ints): %p\n", bcq);
908                 printk("\tprod_idx: %p\n", bcq->hdr.prod_idx);
909                 printk("\tcons_pub_idx: %p\n", bcq->hdr.cons_pub_idx);
910                 printk("\tcons_pvt_idx: %p\n", bcq->hdr.cons_pvt_idx);
911                 for (int i = 0; i < NR_ELEM_A_BCQ; i++) {
912                         printk("Element %d, rdy_for_cons: %02p\n", i,
913                                bcq->wraps[i].rdy_for_cons);
914                 }
915         }
916
917         /* Put in more than it can take */
918         for (int i = 0; i < 15; i++) {
919                 y = i;
920                 retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
921                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
922         }
923         //print_a_bcq(&a_bcq);
924         
925         /* Try to dequeue more than we put in */
926         for (int i = 0; i < 15; i++) {
927                 retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
928                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
929         }
930         //print_a_bcq(&a_bcq);
931         
932         /* Put in some it should be able to take */
933         for (int i = 0; i < 3; i++) {
934                 y = i;
935                 retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
936                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
937         }
938         
939         /* Take those, and then a couple extra */
940         for (int i = 0; i < 5; i++) {
941                 retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
942                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
943         }
944         
945         /* Try some one-for-one */
946         for (int i = 0; i < 5; i++) {
947                 y = i;
948                 retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
949                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
950                 retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
951                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
952         }
953 }
954
955 /* Test a simple concurrent send and receive (one prod, one cons).  We spawn a
956  * process that will go into _M mode on another core, and we'll do the test from
957  * an alarm handler run on our core.  When we start up the process, we won't
958  * return so we need to defer the work with an alarm. */
959 void test_ucq(void)
960 {
961         struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
962         struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0);
963
964         /* Alarm handler: what we want to do after the process is up */
965         void send_msgs(struct alarm_waiter *waiter)
966         {
967                 struct timer_chain *tchain;
968                 struct proc *old_proc, *p = waiter->data;
969                 struct ucq *ucq = (struct ucq*)USTACKTOP;
970                 struct event_msg msg;
971
972                 printk("Running the alarm handler!\n");
973                 printk("NR msg per page: %d\n", NR_MSG_PER_PAGE);
974                 /* might not be mmaped yet, if not, abort */
975                 if (!user_mem_check(p, ucq, PGSIZE, 1, PTE_USER_RW)) {
976                         printk("Not mmaped yet\n");
977                         goto abort;
978                 }
979                 /* load their address space */
980                 old_proc = switch_to(p);
981                 /* So it's mmaped, see if it is ready (note that this is dangerous) */
982                 if (!ucq->ucq_ready) {
983                         printk("Not ready yet\n");
984                         switch_back(p, old_proc);
985                         goto abort;
986                 }
987                 /* So it's ready, time to finally do the tests... */
988                 printk("[kernel] Finally starting the tests... \n");
989                 /* 1: Send a simple message */
990                 printk("[kernel] #1 Sending simple message (7, deadbeef)\n");
991                 msg.ev_type = 7;
992                 msg.ev_arg2 = 0xdeadbeef;
993                 send_ucq_msg(ucq, p, &msg);
994                 printk("nr_pages: %d\n", atomic_read(&ucq->nr_extra_pgs));
995                 /* 2: Send a bunch.  In a VM, this causes one swap, and then a bunch of
996                  * mmaps. */
997                 printk("[kernel] #2 \n");
998                 for (int i = 0; i < 5000; i++) {
999                         msg.ev_type = i;
1000                         send_ucq_msg(ucq, p, &msg);
1001                 }
1002                 printk("nr_pages: %d\n", atomic_read(&ucq->nr_extra_pgs));
1003                 printk("[kernel] #3 \n");
1004                 /* 3: make sure we chained pages (assuming 1k is enough) */
1005                 for (int i = 0; i < 1000; i++) {
1006                         msg.ev_type = i;
1007                         send_ucq_msg(ucq, p, &msg);
1008                 }
1009                 printk("nr_pages: %d\n", atomic_read(&ucq->nr_extra_pgs));
1010                 /* other things we could do:
1011                  *  - concurrent producers / consumers...  ugh.
1012                  *  - would require a kmsg to another core, instead of a local alarm
1013                  */
1014                 /* done, switch back and free things */
1015                 switch_back(p, old_proc);
1016                 proc_decref(p);
1017                 kfree(waiter); /* since it was kmalloc()d */
1018                 return;
1019         abort:
1020                 tchain = &per_cpu_info[core_id()].tchain;
1021                 /* Set to run again */
1022                 set_awaiter_rel(waiter, 1000000);
1023                 set_alarm(tchain, waiter);
1024         }
1025         /* Set up a handler to run the real part of the test */
1026         init_awaiter(waiter, send_msgs);
1027         set_awaiter_rel(waiter, 1000000);       /* 1s should be long enough */
1028         set_alarm(tchain, waiter);
1029         /* Just spawn the program */
1030         struct file *program;
1031         program = do_file_open("/bin/ucq", 0, 0);
1032         if (!program) {
1033                 printk("Unable to find /bin/ucq!\n");
1034                 return;
1035         }
1036         char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
1037         struct proc *p = proc_create(program, 0, p_envp);
1038         proc_wakeup(p);
1039         /* instead of getting rid of the reference created in proc_create, we'll put
1040          * it in the awaiter */
1041         waiter->data = p;
1042         kref_put(&program->f_kref);
1043         /* Should never return from schedule (env_pop in there) also note you may
1044          * not get the process you created, in the event there are others floating
1045          * around that are runnable */
1046         schedule();
1047         smp_idle();
1048         assert(0);
1049 }
1050
1051 /* rudimentary tests.  does the basics, create, merge, split, etc.  Feel free to
1052  * add more, esp for the error conditions and finding free slots.  This is also
1053  * a bit lazy with setting the caller's fields (perm, flags, etc). */
1054 void test_vm_regions(void)
1055 {
1056         #define MAX_VMR_TESTS 10
1057         struct proc pr, *p = &pr;       /* too lazy to even create one */
1058         int n = 0;
1059         TAILQ_INIT(&p->vm_regions);
1060
1061         struct vmr_summary {
1062                 uintptr_t base; 
1063                 uintptr_t end; 
1064         };
1065         int check_vmrs(struct proc *p, struct vmr_summary *results, int len, int n)
1066         {
1067                 int count = 0;
1068                 struct vm_region *vmr;
1069                 TAILQ_FOREACH(vmr, &p->vm_regions, vm_link) {
1070                         if (count >= len) {
1071                                 printk("More vm_regions than expected\n");
1072                                 break;
1073                         }
1074                         if ((vmr->vm_base != results[count].base) ||
1075                             (vmr->vm_end != results[count].end)) {
1076                                 printk("VM test case %d failed!\n", n);
1077                                 print_vmrs(p);
1078                                 return -1;
1079                         }
1080                         count++;
1081                 }
1082                 return count;
1083         }
1084         struct vm_region *vmrs[MAX_VMR_TESTS];
1085         struct vmr_summary results[MAX_VMR_TESTS];
1086
1087         memset(results, 0, sizeof(results));
1088         /* Make one */
1089         vmrs[0] = create_vmr(p, 0x2000, 0x1000);
1090         results[0].base = 0x2000;
1091         results[0].end = 0x3000;
1092         check_vmrs(p, results, 1, n++);
1093         /* Grow it */
1094         grow_vmr(vmrs[0], 0x4000);
1095         results[0].base = 0x2000;
1096         results[0].end = 0x4000;
1097         check_vmrs(p, results, 1, n++);
1098         /* Grow it poorly */
1099         if (-1 != grow_vmr(vmrs[0], 0x3000))
1100                 printk("Bad grow test failed\n");
1101         check_vmrs(p, results, 1, n++);
1102         /* Make another right next to it */
1103         vmrs[1] = create_vmr(p, 0x4000, 0x1000);
1104         results[1].base = 0x4000;
1105         results[1].end = 0x5000;
1106         check_vmrs(p, results, 2, n++);
1107         /* try to grow through it */
1108         if (-1 != grow_vmr(vmrs[0], 0x5000))
1109                 printk("Bad grow test failed\n");
1110         check_vmrs(p, results, 2, n++);
1111         /* Merge them */
1112         merge_vmr(vmrs[0], vmrs[1]);
1113         results[0].end = 0x5000;
1114         results[1].base = 0;
1115         results[1].end = 0;
1116         check_vmrs(p, results, 1, n++);
1117         vmrs[1]= create_vmr(p, 0x6000, 0x4000);
1118         results[1].base = 0x6000;
1119         results[1].end = 0xa000;
1120         check_vmrs(p, results, 2, n++);
1121         /* try to merge unmergables (just testing ranges) */
1122         if (-1 != merge_vmr(vmrs[0], vmrs[1]))
1123                 printk("Bad merge test failed\n");
1124         check_vmrs(p, results, 2, n++);
1125         vmrs[2] = split_vmr(vmrs[1], 0x8000);
1126         results[1].end = 0x8000;
1127         results[2].base = 0x8000;
1128         results[2].end = 0xa000;
1129         check_vmrs(p, results, 3, n++);
1130         /* destroy one */
1131         destroy_vmr(vmrs[1]);
1132         results[1].base = 0x8000;
1133         results[1].end = 0xa000;
1134         check_vmrs(p, results, 2, n++);
1135         /* shrink */
1136         shrink_vmr(vmrs[2], 0x9000);
1137         results[1].base = 0x8000;
1138         results[1].end = 0x9000;
1139         check_vmrs(p, results, 2, n++); /* 10 */
1140         if (vmrs[2] != find_vmr(p, 0x8500))
1141                 printk("Failed to find the right vmr!\n");
1142         if (vmrs[2] != find_first_vmr(p, 0x8500))
1143                 printk("Failed to find the right vmr!\n");
1144         if (vmrs[2] != find_first_vmr(p, 0x7500))
1145                 printk("Failed to find the right vmr!\n");
1146         if (find_first_vmr(p, 0x9500))
1147                 printk("Found a vmr when we shouldn't!\n");
1148         /* grow up to another */
1149         grow_vmr(vmrs[0], 0x8000);
1150         results[0].end = 0x8000;
1151         check_vmrs(p, results, 2, n++);
1152         vmrs[0]->vm_prot = 88;
1153         vmrs[2]->vm_prot = 77;
1154         /* should be unmergeable due to perms */
1155         if (-1 != merge_vmr(vmrs[0], vmrs[2]))
1156                 printk("Bad merge test failed\n");
1157         check_vmrs(p, results, 2, n++);
1158         /* should merge now */
1159         vmrs[2]->vm_prot = 88;
1160         merge_vmr(vmrs[0], vmrs[2]);
1161         results[0].end = 0x9000;
1162         check_vmrs(p, results, 1, n++);
1163         destroy_vmr(vmrs[0]);
1164         check_vmrs(p, results, 0, n++);
1165         /* Check the automerge function */
1166         vmrs[0] = create_vmr(p, 0x2000, 0x1000);
1167         vmrs[1] = create_vmr(p, 0x3000, 0x1000);
1168         vmrs[2] = create_vmr(p, 0x4000, 0x1000);
1169         for (int i = 0; i < 3; i++) {
1170                 vmrs[i]->vm_prot = PROT_READ;
1171                 vmrs[i]->vm_flags = 0;
1172                 vmrs[i]->vm_file = 0; /* would like to test this, it's a pain for now */
1173         }
1174         vmrs[0] = merge_me(vmrs[1]);
1175         results[0].base = 0x2000;
1176         results[0].end = 0x5000;
1177         check_vmrs(p, results, 1, n++);
1178         destroy_vmr(vmrs[0]);
1179         check_vmrs(p, results, 0, n++);
1180         /* Check unfixed creation requests */
1181         vmrs[0] = create_vmr(p, 0x0000, 0x1000);
1182         vmrs[1] = create_vmr(p, 0x0000, 0x1000);
1183         vmrs[2] = create_vmr(p, 0x0000, 0x1000);
1184         results[0].base = 0x0000;
1185         results[0].end  = 0x1000;
1186         results[1].base = 0x1000;
1187         results[1].end  = 0x2000;
1188         results[2].base = 0x2000;
1189         results[2].end  = 0x3000;
1190         check_vmrs(p, results, 3, n++);
1191
1192         printk("Finished vm_regions test!\n");
1193 }
1194
1195 void test_radix_tree(void)
1196 {
1197         struct radix_tree real_tree = RADIX_INITIALIZER;
1198         struct radix_tree *tree = &real_tree;
1199         void *retval;
1200
1201         if (radix_insert(tree, 0, (void*)0xdeadbeef))
1202                 printk("Failed to insert at 0!\n");
1203         radix_delete(tree, 0);
1204         if (radix_insert(tree, 0, (void*)0xdeadbeef))
1205                 printk("Failed to re-insert at 0!\n");
1206
1207         if (radix_insert(tree, 3, (void*)0xdeadbeef))
1208                 printk("Failed to insert first!\n");
1209         radix_insert(tree, 4, (void*)0x04040404);
1210         assert((void*)0xdeadbeef == radix_lookup(tree, 3));
1211         for (int i = 5; i < 100; i++)
1212                 if ((retval = radix_lookup(tree, i))) {
1213                         printk("Extra item %p at slot %d in tree %p\n", retval, i,
1214                                tree);
1215                         print_radix_tree(tree);
1216                         monitor(0);
1217                 }
1218         if (radix_insert(tree, 65, (void*)0xcafebabe))
1219                 printk("Failed to insert a two-tier!\n");
1220         if (!radix_insert(tree, 4, (void*)0x03030303))
1221                 printk("Should not let us reinsert\n");
1222         if (radix_insert(tree, 4095, (void*)0x4095))
1223                 printk("Failed to insert a two-tier boundary!\n");
1224         if (radix_insert(tree, 4096, (void*)0x4096))
1225                 printk("Failed to insert a three-tier!\n");
1226         //print_radix_tree(tree);
1227         radix_delete(tree, 65);
1228         radix_delete(tree, 3);
1229         radix_delete(tree, 4);
1230         radix_delete(tree, 4095);
1231         radix_delete(tree, 4096);
1232         //print_radix_tree(tree);
1233         printk("Finished radix tree tests!\n");
1234 }
1235
1236 /* Assorted FS tests, which were hanging around in init.c */
1237 void test_random_fs(void)
1238 {
1239         int retval = do_symlink("/dir1/sym", "/bin/hello", S_IRWXU);
1240         if (retval)
1241                 printk("symlink1 creation failed\n");
1242         retval = do_symlink("/symdir", "/dir1/dir1-1", S_IRWXU);
1243         if (retval)
1244                 printk("symlink1 creation failed\n");
1245         retval = do_symlink("/dir1/test.txt", "/dir2/test2.txt", S_IRWXU);
1246         if (retval)
1247                 printk("symlink2 creation failed\n");
1248         retval = do_symlink("/dir1/dir1-1/up", "../../", S_IRWXU);
1249         if (retval)
1250                 printk("symlink3 creation failed\n");
1251         retval = do_symlink("/bin/hello-sym", "hello", S_IRWXU);
1252         if (retval)
1253                 printk("symlink4 creation failed\n");
1254         
1255         struct dentry *dentry;
1256         struct nameidata nd_r = {0}, *nd = &nd_r;
1257         retval = path_lookup("/dir1/sym", 0, nd);
1258         if (retval)
1259                 printk("symlink lookup failed: %d\n", retval);
1260         char *symname = nd->dentry->d_inode->i_op->readlink(nd->dentry);
1261         printk("Pathlookup got %s (sym)\n", nd->dentry->d_name.name);
1262         if (!symname)
1263                 printk("symlink reading failed\n");
1264         else
1265                 printk("Symname: %s (/bin/hello)\n", symname);
1266         path_release(nd);
1267         /* try with follow */
1268         memset(nd, 0, sizeof(struct nameidata));
1269         retval = path_lookup("/dir1/sym", LOOKUP_FOLLOW, nd);
1270         if (retval)
1271                 printk("symlink lookup failed: %d\n", retval);
1272         printk("Pathlookup got %s (hello)\n", nd->dentry->d_name.name);
1273         path_release(nd);
1274         
1275         /* try with a directory */
1276         memset(nd, 0, sizeof(struct nameidata));
1277         retval = path_lookup("/symdir/f1-1.txt", 0, nd);
1278         if (retval)
1279                 printk("symlink lookup failed: %d\n", retval);
1280         printk("Pathlookup got %s (f1-1.txt)\n", nd->dentry->d_name.name);
1281         path_release(nd);
1282         
1283         /* try with a rel path */
1284         printk("Try with a rel path\n");
1285         memset(nd, 0, sizeof(struct nameidata));
1286         retval = path_lookup("/symdir/up/hello.txt", 0, nd);
1287         if (retval)
1288                 printk("symlink lookup failed: %d\n", retval);
1289         printk("Pathlookup got %s (hello.txt)\n", nd->dentry->d_name.name);
1290         path_release(nd);
1291         
1292         printk("Try for an ELOOP\n");
1293         memset(nd, 0, sizeof(struct nameidata));
1294         retval = path_lookup("/symdir/up/symdir/up/symdir/up/symdir/up/hello.txt", 0, nd);
1295         if (retval)
1296                 printk("Symlink lookup failed (it should): %d (-40)\n", retval);
1297         path_release(nd);
1298 }
1299
1300 /* Kernel message to restart our kthread */
1301 static void __test_up_sem(uint32_t srcid, long a0, long a1, long a2)
1302 {
1303         struct semaphore *sem = (struct semaphore*)a0;
1304         printk("[kmsg] Upping the sem to start the kthread, stacktop is %p\n",
1305                    get_stack_top());
1306         if (!sem_up(sem)) {
1307                 printk("[kmsg] Crap, the sem didn't have a kthread waiting!\n");
1308                 return;
1309         }
1310         printk("Kthread will restart when we handle the __launch RKM\n");
1311 }
1312
1313 /* simple test - start one, do something else, and resume it.  For lack of a
1314  * better infrastructure, we send ourselves a kmsg to run the kthread, which
1315  * we'll handle in smp_idle (which you may have to manually call).  Note this
1316  * doesn't test things like memory being leaked, or dealing with processes. */
1317 void test_kthreads(void)
1318 {
1319         struct semaphore sem;
1320         sem_init(&sem, 1);              /* set to 1 to test the unwind */
1321         printk("We're a kthread!  Stacktop is %p.  Testing suspend, etc...\n",
1322                get_stack_top());
1323         /* So we have something that will wake us up.  Routine messages won't get
1324          * serviced in the kernel right away. */
1325         send_kernel_message(core_id(), __test_up_sem, (long)&sem, 0, 0,
1326                             KMSG_ROUTINE);
1327         /* Actually block (or try to) */
1328         /* This one shouldn't block - but will test the unwind (if 1 above) */
1329         printk("About to sleep, but should unwind (signal beat us)\n");
1330         sem_down(&sem);
1331         /* This one is for real, yo.  Run and tell that. */
1332         printk("About to sleep for real\n");
1333         sem_down(&sem);
1334         printk("Kthread restarted!, Stacktop is %p.\n", get_stack_top());
1335 }
1336
1337 /* Second player's kmsg */
1338 static void __test_kref_2(uint32_t srcid, long a0, long a1, long a2)
1339 {
1340         struct kref *kref = (struct kref*)a0;
1341         bool *done = (bool*)a1;
1342         enable_irq();
1343         for (int i = 0; i < 10000000; i++) {
1344                 kref_get(kref, 1);
1345                 set_core_timer(1, TRUE);
1346                 udelay(2);
1347                 kref_put(kref);
1348         }
1349         *done = TRUE;
1350 }
1351
1352 /* Runs a simple test between core 0 (caller) and core 2 */
1353 void test_kref(void)
1354 {
1355         struct kref local_kref;
1356         bool done = FALSE;
1357         
1358         kref_init(&local_kref, fake_release, 1);
1359         send_kernel_message(2, __test_kref_2, (long)&local_kref, (long)&done, 0,
1360                             KMSG_ROUTINE);
1361         for (int i = 0; i < 10000000; i++) {
1362                 kref_get(&local_kref, 1);
1363                 udelay(2);
1364                 kref_put(&local_kref);
1365         }
1366         while (!done)
1367                 cpu_relax();
1368         assert(kref_refcnt(&local_kref) == 1);
1369         printk("[TEST-KREF] Simple 2-core getting/putting passed.\n");
1370 }
1371
1372 void test_atomics(void)
1373 {
1374         /* subtract_and_test */
1375         atomic_t num;
1376         /* Test subing to 0 */
1377         atomic_init(&num, 1);
1378         assert(atomic_sub_and_test(&num, 1) == 1);
1379         atomic_init(&num, 2);
1380         assert(atomic_sub_and_test(&num, 2) == 1);
1381         /* Test not getting to 0 */
1382         atomic_init(&num, 1);
1383         assert(atomic_sub_and_test(&num, 0) == 0);
1384         atomic_init(&num, 2);
1385         assert(atomic_sub_and_test(&num, 1) == 0);
1386         /* Test negatives */
1387         atomic_init(&num, -1);
1388         assert(atomic_sub_and_test(&num, 1) == 0);
1389         atomic_init(&num, -1);
1390         assert(atomic_sub_and_test(&num, -1) == 1);
1391         /* Test larger nums */
1392         atomic_init(&num, 265);
1393         assert(atomic_sub_and_test(&num, 265) == 1);
1394         atomic_init(&num, 265);
1395         assert(atomic_sub_and_test(&num, 2) == 0);
1396
1397         /* CAS */
1398         /* Simple test, make sure the bool retval of CAS handles failure */
1399         void test_cas_val(long init_val)
1400         {
1401                 atomic_t actual_num;
1402                 long old_num;
1403                 int attempt;
1404                 atomic_init(&actual_num, init_val);
1405                 attempt = 0;
1406                 do {
1407                         old_num = atomic_read(&actual_num);
1408                         /* First time, try to fail */
1409                         if (attempt == 0) 
1410                                 old_num++;
1411                         attempt++;      
1412                 } while (!atomic_cas(&actual_num, old_num, old_num + 10));
1413                 if (atomic_read(&actual_num) != init_val + 10)
1414                         printk("FUCK, CAS test failed for %d\n", init_val);
1415         }
1416         test_cas_val(257);
1417         test_cas_val(1);
1418 }
1419
1420 /* Helper KMSG for test_abort.  Core 1 does this, while core 0 sends an IRQ. */
1421 static void __test_try_halt(uint32_t srcid, long a0, long a1, long a2)
1422 {
1423         disable_irq();
1424         /* wait 10 sec.  should have a bunch of ints pending */
1425         udelay(10000000);
1426         printk("Core 1 is about to halt\n");
1427         cpu_halt();
1428         printk("Returned from halting on core 1\n");
1429 }
1430
1431 /* x86 test, making sure our cpu_halt() and irq_handler() work.  If you want to
1432  * see it fail, you'll probably need to put a nop in the asm for cpu_halt(), and
1433  * comment out abort_halt() in irq_handler(). */
1434 void test_abort_halt(void)
1435 {
1436 #ifdef CONFIG_X86
1437         send_kernel_message(1, __test_try_halt, 0, 0, 0, KMSG_ROUTINE);
1438         /* wait 1 sec, enough time to for core 1 to be in its KMSG */
1439         udelay(1000000);
1440         /* Send an IPI */
1441         send_ipi(0x01, I_TESTING);
1442         printk("Core 0 sent the IPI\n");
1443 #endif /* CONFIG_X86 */
1444 }
1445
1446 /* Funcs and global vars for test_cv() */
1447 struct cond_var local_cv;
1448 atomic_t counter;
1449 struct cond_var *cv = &local_cv;
1450 volatile bool state = FALSE;            /* for test 3 */
1451
1452 void __test_cv_signal(uint32_t srcid, long a0, long a1, long a2)
1453 {
1454         if (atomic_read(&counter) % 4)
1455                 cv_signal(cv);
1456         else
1457                 cv_broadcast(cv);
1458         atomic_dec(&counter);
1459 }
1460
1461 void __test_cv_waiter(uint32_t srcid, long a0, long a1, long a2)
1462 {
1463         cv_lock(cv);
1464         /* check state, etc */
1465         cv_wait_and_unlock(cv);
1466         atomic_dec(&counter);
1467 }
1468
1469 void __test_cv_waiter_t3(uint32_t srcid, long a0, long a1, long a2)
1470 {
1471         udelay(a0);
1472         /* if state == false, we haven't seen the signal yet */
1473         cv_lock(cv);
1474         while (!state) {
1475                 cpu_relax();
1476                 cv_wait(cv);    /* unlocks and relocks */
1477         }
1478         cv_unlock(cv);
1479         /* Make sure we are done, tell the controller we are done */
1480         cmb();
1481         assert(state);
1482         atomic_dec(&counter);
1483 }
1484
1485 void test_cv(void)
1486 {
1487         int nr_msgs;
1488
1489         cv_init(cv);
1490         /* Test 0: signal without waiting */
1491         cv_broadcast(cv);
1492         cv_signal(cv);
1493         kthread_yield();
1494         printk("test_cv: signal without waiting complete\n");
1495
1496         /* Test 1: single / minimal shit */
1497         nr_msgs = num_cpus - 1; /* not using cpu 0 */
1498         atomic_init(&counter, nr_msgs);
1499         for (int i = 1; i < num_cpus; i++)
1500                 send_kernel_message(i, __test_cv_waiter, 0, 0, 0, KMSG_ROUTINE);
1501         udelay(1000000);
1502         cv_signal(cv);
1503         kthread_yield();
1504         while (atomic_read(&counter) != nr_msgs - 1)
1505                 cpu_relax();
1506         printk("test_cv: single signal complete\n");
1507         cv_broadcast(cv);
1508         /* broadcast probably woke up the waiters on our core.  since we want to
1509          * spin on their completion, we need to yield for a bit. */
1510         kthread_yield();
1511         while (atomic_read(&counter))
1512                 cpu_relax();
1513         printk("test_cv: broadcast signal complete\n");
1514
1515         /* Test 2: shitloads of waiters and signalers */
1516         nr_msgs = 0x500;        /* any more than 0x20000 could go OOM */
1517         atomic_init(&counter, nr_msgs);
1518         for (int i = 0; i < nr_msgs; i++) {
1519                 int cpu = (i % (num_cpus - 1)) + 1;
1520                 if (atomic_read(&counter) % 5)
1521                         send_kernel_message(cpu, __test_cv_waiter, 0, 0, 0, KMSG_ROUTINE);
1522                 else
1523                         send_kernel_message(cpu, __test_cv_signal, 0, 0, 0, KMSG_ROUTINE);
1524         }
1525         kthread_yield();        /* run whatever messages we sent to ourselves */
1526         while (atomic_read(&counter)) {
1527                 cpu_relax();
1528                 cv_broadcast(cv);
1529                 udelay(1000000);
1530                 kthread_yield();        /* run whatever messages we sent to ourselves */
1531         }
1532         assert(!cv->nr_waiters);
1533         printk("test_cv: massive message storm complete\n");
1534
1535         /* Test 3: basic one signaller, one receiver.  we want to vary the amount of
1536          * time the sender and receiver delays, starting with (1ms, 0ms) and ending
1537          * with (0ms, 1ms).  At each extreme, such as with the sender waiting 1ms,
1538          * the receiver/waiter should hit the "check and wait" point well before the
1539          * sender/signaller hits the "change state and signal" point. */
1540         for (int i = 0; i < 1000; i++) {
1541                 for (int j = 0; j < 10; j++) {  /* some extra chances at each point */
1542                         state = FALSE;
1543                         atomic_init(&counter, 1);       /* signal that the client is done */
1544                         /* client waits for i usec */
1545                         send_kernel_message(2, __test_cv_waiter_t3, i, 0, 0, KMSG_ROUTINE);
1546                         cmb();
1547                         udelay(1000 - i);       /* senders wait time: 1000..0 */
1548                         state = TRUE;
1549                         cv_signal(cv);
1550                         /* signal might have unblocked a kthread, let it run */
1551                         kthread_yield();
1552                         /* they might not have run at all yet (in which case they lost the
1553                          * race and don't need the signal).  but we need to wait til they're
1554                          * done */
1555                         while (atomic_read(&counter))
1556                                 cpu_relax();
1557                         assert(!cv->nr_waiters);
1558                 }
1559         }
1560         printk("test_cv: single sender/receiver complete\n");
1561 }
1562
1563 /* Based on a bug I noticed.  TODO: actual memset test... */
1564 void test_memset(void)
1565 {
1566         #define ARR_SZ 256
1567         
1568         void print_array(char *c, size_t len)
1569         {
1570                 for (int i = 0; i < len; i++)
1571                         printk("%04d: %02x\n", i, *c++);
1572         }
1573         
1574         void check_array(char *c, char x, size_t len)
1575         {
1576                 for (int i = 0; i < len; i++) {
1577                         if (*c != x) {
1578                                 printk("Char %d is %c (%02x), should be %c (%02x)\n", i, *c,
1579                                        *c, x, x);
1580                                 break;
1581                         }
1582                         c++;
1583                 }
1584         }
1585         
1586         void run_check(char *arr, int ch, size_t len)
1587         {
1588                 char *c = arr;
1589                 for (int i = 0; i < ARR_SZ; i++)
1590                         *c++ = 0x0;
1591                 memset(arr, ch, len - 4);
1592                 check_array(arr, ch, len - 4);
1593                 check_array(arr + len - 4, 0x0, 4);
1594         }
1595
1596         char bytes[ARR_SZ];
1597         run_check(bytes, 0xfe, 20);
1598         run_check(bytes, 0xc0fe, 20);
1599         printk("Done!\n");
1600 }
1601
1602 void __attribute__((noinline)) __longjmp_wrapper(struct jmpbuf* jb)
1603 {
1604         asm ("");
1605         printk("Starting: %s\n", __FUNCTION__);
1606         longjmp(jb, 1);
1607         // Should never get here
1608         printk("Exiting: %s\n", __FUNCTION__); 
1609 }
1610
1611 void test_setjmp()
1612 {
1613         struct jmpbuf jb;
1614         printk("Starting: %s\n", __FUNCTION__);
1615         if (setjmp(&jb)) {
1616           printk("After second setjmp return: %s\n", __FUNCTION__);
1617     }
1618     else {
1619           printk("After first setjmp return: %s\n", __FUNCTION__);
1620       __longjmp_wrapper(&jb);
1621     }
1622         printk("Exiting: %s\n", __FUNCTION__);
1623 }
1624