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