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