Have switch_{to,back} use an opaque uintptr_t
[akaros.git] / kern / src / ktest / pb_ktests.c
1 /*
2  * Postboot kernel tests: Tests to be ran after boot in kernel mode.
3  * TODO: Some of the tests here may not necessarily be tests to be ran after
4  *       boot. If that is the case, change them in
5  */
6
7 #include <arch/mmu.h>
8 #include <arch/arch.h>
9 #include <arch/uaccess.h>
10 #include <bitmask.h>
11 #include <smp.h>
12
13 #include <ros/memlayout.h>
14 #include <ros/common.h>
15 #include <ros/bcq.h>
16 #include <ros/ucq.h>
17
18 #include <atomic.h>
19 #include <stdio.h>
20 #include <assert.h>
21 #include <string.h>
22 #include <testing.h>
23 #include <trap.h>
24 #include <process.h>
25 #include <syscall.h>
26 #include <time.h>
27 #include <kfs.h>
28 #include <mm.h>
29 #include <multiboot.h>
30 #include <pmap.h>
31 #include <page_alloc.h>
32 #include <pmap.h>
33 #include <slab.h>
34 #include <kmalloc.h>
35 #include <hashtable.h>
36 #include <radix.h>
37 #include <circular_buffer.h>
38 #include <monitor.h>
39 #include <kthread.h>
40 #include <schedule.h>
41 #include <umem.h>
42 #include <init.h>
43 #include <ucq.h>
44 #include <setjmp.h>
45 #include <sort.h>
46
47 #include <apipe.h>
48 #include <rwlock.h>
49 #include <rendez.h>
50 #include <ktest.h>
51 #include <smallidpool.h>
52 #include <linker_func.h>
53
54 KTEST_SUITE("POSTBOOT")
55
56 #define l1 (available_caches.l1)
57 #define l2 (available_caches.l2)
58 #define l3 (available_caches.l3)
59
60 #ifdef CONFIG_X86
61
62 // TODO: Do test if possible inside this function, and add assertions.
63 bool test_ipi_sending(void)
64 {
65         int8_t state = 0;
66
67         register_irq(I_TESTING, test_hello_world_handler, NULL,
68                      MKBUS(BusIPI, 0, 0, 0));
69         enable_irqsave(&state);
70         cprintf("\nCORE 0 sending broadcast\n");
71         send_broadcast_ipi(I_TESTING);
72         udelay(3000000);
73         cprintf("\nCORE 0 sending all others\n");
74         send_all_others_ipi(I_TESTING);
75         udelay(3000000);
76         cprintf("\nCORE 0 sending self\n");
77         send_self_ipi(I_TESTING);
78         udelay(3000000);
79         cprintf("\nCORE 0 sending ipi to physical 1\n");
80         send_ipi(0x01, I_TESTING);
81         udelay(3000000);
82         cprintf("\nCORE 0 sending ipi to physical 2\n");
83         send_ipi(0x02, I_TESTING);
84         udelay(3000000);
85         cprintf("\nCORE 0 sending ipi to physical 3\n");
86         send_ipi(0x03, I_TESTING);
87         udelay(3000000);
88         cprintf("\nCORE 0 sending ipi to physical 15\n");
89         send_ipi(0x0f, I_TESTING);
90         udelay(3000000);
91         cprintf("\nCORE 0 sending ipi to logical 2\n");
92         send_group_ipi(0x02, I_TESTING);
93         udelay(3000000);
94         cprintf("\nCORE 0 sending ipi to logical 1\n");
95         send_group_ipi(0x01, I_TESTING);
96         udelay(3000000);
97         cprintf("\nDone!\n");
98         disable_irqsave(&state);
99
100         return true;
101 }
102
103 // TODO: Refactor to make it return and add assertions.
104 // Note this never returns and will muck with any other timer work
105 bool test_pic_reception(void)
106 {
107         register_irq(IdtPIC + IrqCLOCK, test_hello_world_handler, NULL,
108                      MKBUS(BusISA, 0, 0, 0));
109         pit_set_timer(100,TIMER_RATEGEN); // totally arbitrary time
110         pic_unmask_irq(0, 0);
111         cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
112         cprintf("PIC2 Mask = 0x%04x\n", inb(PIC2_DATA));
113         unmask_lapic_lvt(LAPIC_LVT_LINT0);
114         cprintf("Core %d's LINT0: 0x%08x\n", core_id(), read_mmreg32(LAPIC_LVT_LINT0));
115         enable_irq();
116         while(1);
117
118         return true;
119 }
120
121 #endif // CONFIG_X86
122
123 // TODO: Add assertions. Possibly the way to go is to extract relevant info 
124 //       from cache properties and make assertions on the colored pages lists 
125 //       based on those.
126 // TODO: The test was commented out. Figure out why was it like that and fix it.
127 bool test_page_coloring(void) 
128 {
129         /*
130         //Print the different cache properties of our machine
131         print_cache_properties("L1", l1);
132         cprintf("\n");
133         print_cache_properties("L2", l2);
134         cprintf("\n");
135         print_cache_properties("L3", l3);
136         cprintf("\n");
137
138         //Print some stats about our memory
139         cprintf("Max Address: %llu\n", MAX_VADDR);
140         cprintf("Num Pages: %u\n", npages);
141
142         //Declare a local variable for allocating pages 
143         page_t* page;
144
145         cprintf("Contents of the page free list:\n");
146         for(int i=0; i<llc_cache->num_colors; i++) {
147                 cprintf("  COLOR %d:\n", i);
148                 LIST_FOREACH(page, &colored_page_free_list[i], pg_link) {
149                         cprintf("    Page: %d\n", page2ppn(page));
150                 }
151         }
152
153         //Run through and allocate all pages through l1_page_alloc
154         cprintf("Allocating from L1 page colors:\n");
155         for(int i=0; i<get_cache_num_page_colors(l1); i++) {
156                 cprintf("  COLOR %d:\n", i);
157                 while(colored_page_alloc(l1, &page, i) != -ENOMEM)
158                         cprintf("    Page: %d\n", page2ppn(page));
159         }
160
161         //Put all the pages back by reinitializing
162         page_init();
163         
164         //Run through and allocate all pages through l2_page_alloc
165         cprintf("Allocating from L2 page colors:\n");
166         for(int i=0; i<get_cache_num_page_colors(l2); i++) {
167                 cprintf("  COLOR %d:\n", i);
168                 while(colored_page_alloc(l2, &page, i) != -ENOMEM)
169                         cprintf("    Page: %d\n", page2ppn(page));
170         }
171
172         //Put all the pages back by reinitializing
173         page_init();
174         
175         //Run through and allocate all pages through l3_page_alloc
176         cprintf("Allocating from L3 page colors:\n");
177         for(int i=0; i<get_cache_num_page_colors(l3); i++) {
178                 cprintf("  COLOR %d:\n", i);
179                 while(colored_page_alloc(l3, &page, i) != -ENOMEM)
180                         cprintf("    Page: %d\n", page2ppn(page));
181         }
182         
183         //Put all the pages back by reinitializing
184         page_init();
185         
186         //Run through and allocate all pages through page_alloc
187         cprintf("Allocating from global allocator:\n");
188         while(upage_alloc(&page) != -ENOMEM)
189                 cprintf("    Page: %d\n", page2ppn(page));
190         
191         if(colored_page_alloc(l2, &page, 0) != -ENOMEM)
192                 cprintf("Should not get here, all pages should already be gone!\n");
193         cprintf("All pages gone for sure...\n");
194         
195         //Now lets put a few pages back using page_free..
196         cprintf("Reinserting pages via page_free and reallocating them...\n");
197         page_free(&pages[0]);
198         page_free(&pages[15]);
199         page_free(&pages[7]);
200         page_free(&pages[6]);
201         page_free(&pages[4]);
202
203         while(upage_alloc(&page) != -ENOMEM)
204                 cprintf("Page: %d\n", page2ppn(page));  
205         
206         page_init();
207         */
208         return true;
209 }
210
211 // TODO: Add assertions.
212 bool test_color_alloc(void) {
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         return true;
251 }
252
253 barrier_t test_cpu_array;
254
255 // TODO: Add assertions, try to do everything from within this same function.
256 bool test_barrier(void)
257 {
258         cprintf("Core 0 initializing barrier\n");
259         init_barrier(&test_cpu_array, num_cores);
260         cprintf("Core 0 asking all cores to print ids, barrier, rinse, repeat\n");
261         smp_call_function_all(test_barrier_handler, NULL, 0);
262
263         return true;
264 }
265
266 // TODO: Maybe remove all the printing statements and instead use the 
267 //       KT_ASSERT_M macro to include a message on assertions.
268 bool test_interrupts_irqsave(void)
269 {
270         int8_t state = 0;
271         printd("Testing Nesting Enabling first, turning ints off:\n");
272         disable_irq();
273         printd("Interrupts are: %x\n", irq_is_enabled());
274         KT_ASSERT(!irq_is_enabled());
275         printd("Enabling IRQSave\n");
276         enable_irqsave(&state);
277         printd("Interrupts are: %x\n", irq_is_enabled());
278         KT_ASSERT(irq_is_enabled());
279         printd("Enabling IRQSave Again\n");
280         enable_irqsave(&state);
281         printd("Interrupts are: %x\n", irq_is_enabled());
282         KT_ASSERT(irq_is_enabled());
283         printd("Disabling IRQSave Once\n");
284         disable_irqsave(&state);
285         printd("Interrupts are: %x\n", irq_is_enabled());
286         KT_ASSERT(irq_is_enabled());
287         printd("Disabling IRQSave Again\n");
288         disable_irqsave(&state);
289         printd("Interrupts are: %x\n", irq_is_enabled());
290         KT_ASSERT(!irq_is_enabled());
291         printd("Done.  Should have been 0, 200, 200, 200, 0\n");
292
293         printd("Testing Nesting Disabling first, turning ints on:\n");
294         state = 0;
295         enable_irq();
296         printd("Interrupts are: %x\n", irq_is_enabled());
297         KT_ASSERT(irq_is_enabled());
298         printd("Disabling IRQSave Once\n");
299         disable_irqsave(&state);
300         printd("Interrupts are: %x\n", irq_is_enabled());
301         KT_ASSERT(!irq_is_enabled());
302         printd("Disabling IRQSave Again\n");
303         disable_irqsave(&state);
304         printd("Interrupts are: %x\n", irq_is_enabled());
305         KT_ASSERT(!irq_is_enabled());
306         printd("Enabling IRQSave Once\n");
307         enable_irqsave(&state);
308         printd("Interrupts are: %x\n", irq_is_enabled());
309         KT_ASSERT(!irq_is_enabled());
310         printd("Enabling IRQSave Again\n");
311         enable_irqsave(&state);
312         printd("Interrupts are: %x\n", irq_is_enabled());
313         KT_ASSERT(irq_is_enabled());
314         printd("Done.  Should have been 200, 0, 0, 0, 200 \n");
315
316         state = 0;
317         disable_irq();
318         printd("Ints are off, enabling then disabling.\n");
319         enable_irqsave(&state);
320         printd("Interrupts are: %x\n", irq_is_enabled());
321         KT_ASSERT(irq_is_enabled());
322         disable_irqsave(&state);
323         printd("Interrupts are: %x\n", irq_is_enabled());
324         KT_ASSERT(!irq_is_enabled());
325         printd("Done.  Should have been 200, 0\n");
326
327         state = 0;
328         enable_irq();
329         printd("Ints are on, enabling then disabling.\n");
330         enable_irqsave(&state);
331         printd("Interrupts are: %x\n", irq_is_enabled());
332         KT_ASSERT(irq_is_enabled());
333         disable_irqsave(&state);
334         printd("Interrupts are: %x\n", irq_is_enabled());
335         KT_ASSERT(irq_is_enabled());
336         printd("Done.  Should have been 200, 200\n");
337
338         state = 0;
339         disable_irq();
340         printd("Ints are off, disabling then enabling.\n");
341         disable_irqsave(&state);
342         printd("Interrupts are: %x\n", irq_is_enabled());
343         KT_ASSERT(!irq_is_enabled());
344         enable_irqsave(&state);
345         printd("Interrupts are: %x\n", irq_is_enabled());
346         KT_ASSERT(!irq_is_enabled());
347         printd("Done.  Should have been 0, 0\n");
348
349         state = 0;
350         enable_irq();
351         printd("Ints are on, disabling then enabling.\n");
352         disable_irqsave(&state);
353         printd("Interrupts are: %x\n", irq_is_enabled());
354         KT_ASSERT(!irq_is_enabled());
355         enable_irqsave(&state);
356         printd("Interrupts are: %x\n", irq_is_enabled());
357         KT_ASSERT(irq_is_enabled());
358         printd("Done.  Should have been 0, 200\n");
359
360         disable_irq();
361         return true;
362 }
363
364 // TODO: Maybe remove PRINT_BITMASK statements and use KT_ASSERT_M instead
365 //       somehow.
366 bool test_bitmasks(void)
367 {
368 #define masksize 67
369         DECL_BITMASK(mask, masksize);
370         CLR_BITMASK(mask, masksize);
371 //      PRINT_BITMASK(mask, masksize);
372         SET_BITMASK_BIT(mask, 0);
373         SET_BITMASK_BIT(mask, 11);
374         SET_BITMASK_BIT(mask, 17);
375         SET_BITMASK_BIT(mask, masksize-1);
376 //      PRINT_BITMASK(mask, masksize);
377         DECL_BITMASK(mask2, masksize);
378         COPY_BITMASK(mask2, mask, masksize);
379 //      printk("copy of original mask, should be the same as the prev\n");
380 //      PRINT_BITMASK(mask2, masksize);
381         CLR_BITMASK_BIT(mask, 11);
382 //      PRINT_BITMASK(mask, masksize);
383         KT_ASSERT_M("Bit 17 should be 1", 1 == GET_BITMASK_BIT(mask, 17));
384         KT_ASSERT_M("Bit 11 should be 0", 0 == GET_BITMASK_BIT(mask, 11));
385         FILL_BITMASK(mask, masksize);
386 //      PRINT_BITMASK(mask, masksize);
387         KT_ASSERT_M("Bitmask should not be clear after calling FILL_BITMASK", 
388                     0 == BITMASK_IS_CLEAR(mask,masksize));
389         CLR_BITMASK(mask, masksize);
390 //      PRINT_BITMASK(mask, masksize);
391         KT_ASSERT_M("Bitmask should be clear after calling CLR_BITMASK", 
392                     1 == BITMASK_IS_CLEAR(mask,masksize));
393         return true;
394 }
395
396 checklist_t *the_global_list;
397
398 static void test_checklist_handler(struct hw_trapframe *hw_tf, void *data)
399 {
400         udelay(1000000);
401         cprintf("down_checklist(%x,%d)\n", the_global_list, core_id());
402         down_checklist(the_global_list);
403 }
404
405 // TODO: Add assertions
406 bool test_checklists(void)
407 {
408         INIT_CHECKLIST(a_list, MAX_NUM_CORES);
409         the_global_list = &a_list;
410         printk("Checklist Build, mask size: %d\n", sizeof(a_list.mask.bits));
411         printk("mask\n");
412         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
413         SET_BITMASK_BIT(a_list.mask.bits, 11);
414         printk("Set bit 11\n");
415         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
416
417         CLR_BITMASK(a_list.mask.bits, a_list.mask.size);
418         INIT_CHECKLIST_MASK(a_mask, MAX_NUM_CORES);
419         FILL_BITMASK(a_mask.bits, num_cores);
420         //CLR_BITMASK_BIT(a_mask.bits, core_id());
421         //SET_BITMASK_BIT(a_mask.bits, 1);
422         //printk("New mask (1, 17, 25):\n");
423         printk("Created new mask, filled up to num_cores\n");
424         PRINT_BITMASK(a_mask.bits, a_mask.size);
425         printk("committing new mask\n");
426         commit_checklist_wait(&a_list, &a_mask);
427         printk("Old mask (copied onto):\n");
428         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
429         //smp_call_function_single(1, test_checklist_handler, 0, 0);
430
431         smp_call_function_all(test_checklist_handler, NULL, 0);
432
433         printk("Waiting on checklist\n");
434         waiton_checklist(&a_list);
435         printk("Done Waiting!\n");
436
437         return true;
438 }
439
440 atomic_t a, b, c;
441
442 static void test_incrementer_handler(struct hw_trapframe *tf, void *data)
443 {
444         assert(data);
445         atomic_inc(data);
446 }
447
448 static void test_null_handler(struct hw_trapframe *tf, void *data)
449 {
450         asm volatile("nop");
451 }
452
453 // TODO: Add assertions.
454 bool test_smp_call_functions(void)
455 {
456         int i;
457         atomic_init(&a, 0);
458         atomic_init(&b, 0);
459         atomic_init(&c, 0);
460         handler_wrapper_t *waiter0 = 0, *waiter1 = 0, *waiter2 = 0, *waiter3 = 0,
461                           *waiter4 = 0, *waiter5 = 0;
462         uint8_t me = core_id();
463         printk("\nCore %d: SMP Call Self (nowait):\n", me);
464         printk("---------------------\n");
465         smp_call_function_self(test_hello_world_handler, NULL, 0);
466         printk("\nCore %d: SMP Call Self (wait):\n", me);
467         printk("---------------------\n");
468         smp_call_function_self(test_hello_world_handler, NULL, &waiter0);
469         smp_call_wait(waiter0);
470         printk("\nCore %d: SMP Call All (nowait):\n", me);
471         printk("---------------------\n");
472         smp_call_function_all(test_hello_world_handler, NULL, 0);
473         printk("\nCore %d: SMP Call All (wait):\n", me);
474         printk("---------------------\n");
475         smp_call_function_all(test_hello_world_handler, NULL, &waiter0);
476         smp_call_wait(waiter0);
477         printk("\nCore %d: SMP Call All-Else Individually, in order (nowait):\n", me);
478         printk("---------------------\n");
479         for(i = 1; i < num_cores; i++)
480                 smp_call_function_single(i, test_hello_world_handler, NULL, 0);
481         printk("\nCore %d: SMP Call Self (wait):\n", me);
482         printk("---------------------\n");
483         smp_call_function_self(test_hello_world_handler, NULL, &waiter0);
484         smp_call_wait(waiter0);
485         printk("\nCore %d: SMP Call All-Else Individually, in order (wait):\n", me);
486         printk("---------------------\n");
487         for(i = 1; i < num_cores; i++)
488         {
489                 smp_call_function_single(i, test_hello_world_handler, NULL, &waiter0);
490                 smp_call_wait(waiter0);
491         }
492         printk("\nTesting to see if any IPI-functions are dropped when not waiting:\n");
493         printk("A: %d, B: %d, C: %d (should be 0,0,0)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
494         smp_call_function_all(test_incrementer_handler, &a, 0);
495         smp_call_function_all(test_incrementer_handler, &b, 0);
496         smp_call_function_all(test_incrementer_handler, &c, 0);
497         // if i can clobber a previous IPI, the interleaving might do it
498         smp_call_function_single(1 % num_cores, test_incrementer_handler, &a, 0);
499         smp_call_function_single(2 % num_cores, test_incrementer_handler, &b, 0);
500         smp_call_function_single(3 % num_cores, test_incrementer_handler, &c, 0);
501         smp_call_function_single(4 % num_cores, test_incrementer_handler, &a, 0);
502         smp_call_function_single(5 % num_cores, test_incrementer_handler, &b, 0);
503         smp_call_function_single(6 % num_cores, test_incrementer_handler, &c, 0);
504         smp_call_function_all(test_incrementer_handler, &a, 0);
505         smp_call_function_single(3 % num_cores, test_incrementer_handler, &c, 0);
506         smp_call_function_all(test_incrementer_handler, &b, 0);
507         smp_call_function_single(1 % num_cores, test_incrementer_handler, &a, 0);
508         smp_call_function_all(test_incrementer_handler, &c, 0);
509         smp_call_function_single(2 % num_cores, test_incrementer_handler, &b, 0);
510         // wait, so we're sure the others finish before printing.
511         // without this, we could (and did) get 19,18,19, since the B_inc
512         // handler didn't finish yet
513         smp_call_function_self(test_null_handler, NULL, &waiter0);
514         // need to grab all 5 handlers (max), since the code moves to the next free.
515         smp_call_function_self(test_null_handler, NULL, &waiter1);
516         smp_call_function_self(test_null_handler, NULL, &waiter2);
517         smp_call_function_self(test_null_handler, NULL, &waiter3);
518         smp_call_function_self(test_null_handler, NULL, &waiter4);
519         smp_call_wait(waiter0);
520         smp_call_wait(waiter1);
521         smp_call_wait(waiter2);
522         smp_call_wait(waiter3);
523         smp_call_wait(waiter4);
524         printk("A: %d, B: %d, C: %d (should be 19,19,19)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
525         printk("Attempting to deadlock by smp_calling with an outstanding wait:\n");
526         smp_call_function_self(test_null_handler, NULL, &waiter0);
527         printk("Sent one\n");
528         smp_call_function_self(test_null_handler, NULL, &waiter1);
529         printk("Sent two\n");
530         smp_call_wait(waiter0);
531         printk("Wait one\n");
532         smp_call_wait(waiter1);
533         printk("Wait two\n");
534         printk("\tMade it through!\n");
535         printk("Attempting to deadlock by smp_calling more than are available:\n");
536         printk("\tShould see an Insufficient message and a kernel warning.\n");
537         if (smp_call_function_self(test_null_handler, NULL, &waiter0))
538                 printk("\tInsufficient handlers to call function (0)\n");
539         if (smp_call_function_self(test_null_handler, NULL, &waiter1))
540                 printk("\tInsufficient handlers to call function (1)\n");
541         if (smp_call_function_self(test_null_handler, NULL, &waiter2))
542                 printk("\tInsufficient handlers to call function (2)\n");
543         if (smp_call_function_self(test_null_handler, NULL, &waiter3))
544                 printk("\tInsufficient handlers to call function (3)\n");
545         if (smp_call_function_self(test_null_handler, NULL, &waiter4))
546                 printk("\tInsufficient handlers to call function (4)\n");
547         if (smp_call_function_self(test_null_handler, NULL, &waiter5))
548                 printk("\tInsufficient handlers to call function (5)\n");
549         smp_call_wait(waiter0);
550         smp_call_wait(waiter1);
551         smp_call_wait(waiter2);
552         smp_call_wait(waiter3);
553         smp_call_wait(waiter4);
554         smp_call_wait(waiter5);
555         printk("\tMade it through!\n");
556
557         printk("Done\n");
558
559         return true;
560 }
561
562 #ifdef CONFIG_X86
563 // TODO: Fix the KT_ASSERTs
564 bool test_lapic_status_bit(void)
565 {
566         register_irq(I_TESTING, test_incrementer_handler, &a,
567                      MKBUS(BusIPI, 0, 0, 0));
568         #define NUM_IPI 100000
569         atomic_set(&a,0);
570         printk("IPIs received (should be 0): %d\n", a);
571         // KT_ASSERT_M("IPIs received should be 0", (0 == a));
572         for(int i = 0; i < NUM_IPI; i++) {
573                 send_ipi(7, I_TESTING);
574                 lapic_wait_to_send();
575         }
576         // need to wait a bit to let those IPIs get there
577         udelay(5000000);
578         printk("IPIs received (should be %d): %d\n", a, NUM_IPI);
579         // KT_ASSERT_M("IPIs received should be 100000", (NUM_IPI == a));
580         // hopefully that handler never fires again.  leaving it registered for now.
581
582         return true;
583 }
584 #endif // CONFIG_X86
585
586 /************************************************************/
587 /* ISR Handler Functions */
588
589 void test_hello_world_handler(struct hw_trapframe *hw_tf, void *data)
590 {
591         int trapno;
592         #if defined(CONFIG_X86)
593         trapno = hw_tf->tf_trapno;
594         #else
595         trapno = 0;
596         #endif
597
598         cprintf("Incoming IRQ, ISR: %d on core %d with tf at %p\n",
599                 trapno, core_id(), hw_tf);
600 }
601
602 void test_barrier_handler(struct hw_trapframe *hw_tf, void *data)
603 {
604         cprintf("Round 1: Core %d\n", core_id());
605         waiton_barrier(&test_cpu_array);
606         waiton_barrier(&test_cpu_array);
607         waiton_barrier(&test_cpu_array);
608         waiton_barrier(&test_cpu_array);
609         waiton_barrier(&test_cpu_array);
610         waiton_barrier(&test_cpu_array);
611         cprintf("Round 2: Core %d\n", core_id());
612         waiton_barrier(&test_cpu_array);
613         cprintf("Round 3: Core %d\n", core_id());
614         // uncomment to see it fucked up
615         //cprintf("Round 4: Core %d\n", core_id());
616 }
617
618 static void test_waiting_handler(struct hw_trapframe *hw_tf, void *data)
619 {
620         atomic_dec(data);
621 }
622
623 #ifdef CONFIG_X86
624 // TODO: Add assertions.
625 bool test_pit(void)
626 {
627         cprintf("Starting test for PIT now (10s)\n");
628         udelay_pit(10000000);
629         cprintf("End now\n");
630         cprintf("Starting test for TSC (if stable) now (10s)\n");
631         udelay(10000000);
632         cprintf("End now\n");
633
634         cprintf("Starting test for LAPIC (if stable) now (10s)\n");
635         enable_irq();
636         lapic_set_timer(10000000, FALSE);
637
638         atomic_t waiting;
639         atomic_init(&waiting, 1);
640         register_irq(I_TESTING, test_waiting_handler, &waiting,
641                      MKBUS(BusIPI, 0, 0, 0));
642         while(atomic_read(&waiting))
643                 cpu_relax();
644         cprintf("End now\n");
645
646         return true;
647 }
648
649 // TODO: Add assertions.
650 bool test_circ_buffer(void)
651 {
652         int arr[5] = {0, 1, 2, 3, 4};
653
654         for (int i = 0; i < 5; i++) {
655                 FOR_CIRC_BUFFER(i, 5, j)
656                         printk("Starting with current = %d, each value = %d\n", i, j);
657         }
658         
659         return true;
660 }
661
662 static void test_km_handler(uint32_t srcid, long a0, long a1, long a2)
663 {
664         printk("Received KM on core %d from core %d: arg0= %p, arg1 = %p, "
665                "arg2 = %p\n", core_id(), srcid, a0, a1, a2);
666         return;
667 }
668
669 // TODO: Add assertions. Try to do everything inside this function.
670 bool test_kernel_messages(void)
671 {
672         printk("Testing Kernel Messages\n");
673         /* Testing sending multiples, sending different types, alternating, and
674          * precendence (the immediates should trump the others) */
675         printk("sending 5 IMMED to core 1, sending (#,deadbeef,0)\n");
676         for (int i = 0; i < 5; i++)
677                 send_kernel_message(1, test_km_handler, (long)i, 0xdeadbeef, 0,
678                                     KMSG_IMMEDIATE);
679         udelay(5000000);
680         printk("sending 5 routine to core 1, sending (#,cafebabe,0)\n");
681         for (int i = 0; i < 5; i++)
682                 send_kernel_message(1, test_km_handler, (long)i, 0xcafebabe, 0,
683                                     KMSG_ROUTINE);
684         udelay(5000000);
685         printk("sending 10 routine and 3 immediate to core 2\n");
686         for (int i = 0; i < 10; i++)
687                 send_kernel_message(2, test_km_handler, (long)i, 0xcafebabe, 0,
688                                     KMSG_ROUTINE);
689         for (int i = 0; i < 3; i++)
690                 send_kernel_message(2, test_km_handler, (long)i, 0xdeadbeef, 0,
691                                     KMSG_IMMEDIATE);
692         udelay(5000000);
693         printk("sending 5 ea alternating to core 2\n");
694         for (int i = 0; i < 5; i++) {
695                 send_kernel_message(2, test_km_handler, (long)i, 0xdeadbeef, 0,
696                                     KMSG_IMMEDIATE);
697                 send_kernel_message(2, test_km_handler, (long)i, 0xcafebabe, 0,
698                                     KMSG_ROUTINE);
699         }
700         udelay(5000000);
701         
702         return true;
703 }
704 #endif // CONFIG_X86
705 static void test_single_cache(int iters, size_t size, int align, int flags,
706                               void (*ctor)(void *, size_t),
707                               void (*dtor)(void *, size_t))
708 {
709         struct kmem_cache *test_cache;
710         void *objects[iters];
711         test_cache = kmem_cache_create("test_cache", size, align, flags, ctor, dtor);
712         printk("Testing Kmem Cache:\n");
713         print_kmem_cache(test_cache);
714         for (int i = 0; i < iters; i++) {
715                 objects[i] = kmem_cache_alloc(test_cache, 0);
716                 printk("Buffer %d addr = %p\n", i, objects[i]);
717         }
718         for (int i = 0; i < iters; i++) {
719                 kmem_cache_free(test_cache, objects[i]);
720         }
721         kmem_cache_destroy(test_cache);
722         printk("\n\n\n\n");
723 }
724
725 void a_ctor(void *buf, size_t size)
726 {
727         printk("constructin tests\n");
728 }
729 void a_dtor(void *buf, size_t size)
730 {
731         printk("destructin tests\n");
732 }
733
734 // TODO: Make test_single_cache return something, and then add assertions here.
735 bool test_slab(void)
736 {
737         test_single_cache(10, 128, 512, 0, 0, 0);
738         test_single_cache(10, 128, 4, 0, a_ctor, a_dtor);
739         test_single_cache(10, 1024, 16, 0, 0, 0);
740
741         return true;
742 }
743
744 // TODO: Add assertions.
745 bool test_kmalloc(void)
746 {
747         printk("Testing Kmalloc\n");
748         void *bufs[NUM_KMALLOC_CACHES + 1];     
749         size_t size;
750         for (int i = 0; i < NUM_KMALLOC_CACHES + 1; i++){
751                 size = (KMALLOC_SMALLEST << i) - sizeof(struct kmalloc_tag);
752                 bufs[i] = kmalloc(size, 0);
753                 printk("Size %d, Addr = %p\n", size, bufs[i]);
754         }
755         for (int i = 0; i < NUM_KMALLOC_CACHES; i++) {
756                 printk("Freeing buffer %d\n", i);
757                 kfree(bufs[i]);
758         }
759         printk("Testing a large kmalloc\n");
760         size = (KMALLOC_LARGEST << 2);
761         bufs[0] = kmalloc(size, 0);
762         printk("Size %d, Addr = %p\n", size, bufs[0]);
763         kfree(bufs[0]);
764
765         return true;
766 }
767
768 static size_t test_hash_fn_col(void *k)
769 {
770         return (size_t)k % 2; // collisions in slots 0 and 1
771 }
772
773 bool test_hashtable(void)
774 {
775         struct test {int x; int y;};
776         struct test tstruct[10];
777
778         struct hashtable *h;
779         uintptr_t k = 5;
780         struct test *v = &tstruct[0];
781
782         h = create_hashtable(32, __generic_hash, __generic_eq);
783         
784         // test inserting one item, then finding it again
785         KT_ASSERT_M("It should be possible to insert items to a hashtable", 
786                     hashtable_insert(h, (void*)k, v));
787         v = NULL;
788         KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable", 
789                     (v = hashtable_search(h, (void*)k)));
790
791         KT_ASSERT_M("The extracted element should be the same we inserted", 
792                     (v == &tstruct[0]));
793
794         v = NULL;
795
796         KT_ASSERT_M("It should be possible to remove an existing element", 
797                     (v = hashtable_remove(h, (void*)k)));
798
799         KT_ASSERT_M("An element should not remain in a hashtable after deletion", 
800                     !(v = hashtable_search(h, (void*)k)));
801
802         /* Testing a bunch of items, insert, search, and removal */
803         for (int i = 0; i < 10; i++) {
804                 k = i; // vary the key, we don't do KEY collisions
805                 KT_ASSERT_M("It should be possible to insert elements to a hashtable", 
806                             (hashtable_insert(h, (void*)k, &tstruct[i])));
807         }
808         // read out the 10 items
809         for (int i = 0; i < 10; i++) {
810                 k = i;
811                 KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable", 
812                             (v = hashtable_search(h, (void*)k)));
813                 KT_ASSERT_M("The extracted element should be the same we inserted", 
814                             (v == &tstruct[i]));
815         }
816
817         KT_ASSERT_M("The total count of number of elements should be 10", 
818                     (10 == hashtable_count(h)));
819
820         // remove the 10 items
821         for (int i = 0; i < 10; i++) {
822                 k = i;
823                 KT_ASSERT_M("It should be possible to remove an existing element", 
824                             (v = hashtable_remove(h, (void*)k)));
825
826         }
827         // make sure they are all gone
828         for (int i = 0; i < 10; i++) {
829                 k = i;
830                 KT_ASSERT_M("An element should not remain in a hashtable after deletion", 
831                             !(v = hashtable_search(h, (void*)k)));
832         }
833
834         KT_ASSERT_M("The hashtable should be empty", 
835                     (0 == hashtable_count(h)));
836
837         hashtable_destroy(h);
838
839         // same test of a bunch of items, but with collisions.
840         /* Testing a bunch of items with collisions, etc. */
841         h = create_hashtable(32, test_hash_fn_col, __generic_eq);
842         // insert 10 items
843         for (int i = 0; i < 10; i++) {
844                 k = i; // vary the key, we don't do KEY collisions
845
846                 KT_ASSERT_M("It should be possible to insert elements to a hashtable", 
847                             (hashtable_insert(h, (void*)k, &tstruct[i])));
848         }
849         // read out the 10 items
850         for (int i = 0; i < 10; i++) {
851                 k = i;
852                 KT_ASSERT_M("It should be possible to find inserted stuff in a hashtable", 
853                             (v = hashtable_search(h, (void*)k)));
854                 KT_ASSERT_M("The extracted element should be the same we inserted", 
855                             (v == &tstruct[i]));
856         }
857
858         KT_ASSERT_M("The total count of number of elements should be 10", 
859                     (10 == hashtable_count(h)));
860
861         // remove the 10 items
862         for (int i = 0; i < 10; i++) {
863                 k = i;
864                 KT_ASSERT_M("It should be possible to remove an existing element", 
865                             (v = hashtable_remove(h, (void*)k)));
866         }
867         // make sure they are all gone
868         for (int i = 0; i < 10; i++) {
869                 k = i;
870
871                 KT_ASSERT_M("An element should not remain in a hashtable after deletion", 
872                             !(v = hashtable_search(h, (void*)k)));
873         }
874
875         KT_ASSERT_M("The hashtable should be empty", 
876                     (0 == hashtable_count(h)));
877
878         hashtable_destroy(h);
879
880         return true;
881 }
882
883 bool test_circular_buffer(void)
884 {
885         static const size_t cbsize = 4096;
886         struct circular_buffer cb;
887         char *bigbuf;
888         size_t csize, off, cnum, mxsize;
889         char buf[256];
890
891         KT_ASSERT_M("Failed to build the circular buffer",
892                                 circular_buffer_init(&cb, cbsize, NULL));
893
894         for (size_t i = 0; i < 8 * cbsize; i++) {
895                 size_t len = snprintf(buf, sizeof(buf), "%lu\n", i);
896
897                 KT_ASSERT_M("Circular buffer write failed",
898                                         circular_buffer_write(&cb, buf, len) == len);
899         }
900         cnum = off = 0;
901         while ((csize = circular_buffer_read(&cb, buf, sizeof(buf), off)) != 0) {
902                 char *top = buf + csize;
903                 char *ptr = buf;
904                 char *pnl;
905
906                 while ((pnl = memchr(ptr, '\n', top - ptr)) != NULL) {
907                         size_t num;
908
909                         *pnl = 0;
910                         num = strtoul(ptr, NULL, 10);
911                         KT_ASSERT_M("Numbers should be ascending", num >= cnum);
912                         cnum = num;
913                         ptr = pnl + 1;
914                 }
915
916                 off += ptr - buf;
917         }
918
919         for (size_t i = 0; i < (cbsize / sizeof(buf) + 1); i++) {
920                 memset(buf, (int) i, sizeof(buf));
921
922                 KT_ASSERT_M("Circular buffer write failed",
923                                         circular_buffer_write(&cb, buf,
924                                                                                   sizeof(buf)) == sizeof(buf));
925         }
926         cnum = off = 0;
927         while ((csize = circular_buffer_read(&cb, buf, sizeof(buf), off)) != 0) {
928                 size_t num = buf[0];
929
930                 KT_ASSERT_M("Invalid record read size", csize == sizeof(buf));
931
932                 if (off != 0)
933                         KT_ASSERT_M("Invalid record sequence number",
934                                                 num == ((cnum + 1) % 256));
935                 cnum = num;
936                 off += csize;
937         }
938
939         bigbuf = kzmalloc(cbsize, KMALLOC_WAIT);
940         KT_ASSERT(bigbuf != NULL);
941
942         mxsize = circular_buffer_max_write_size(&cb);
943         KT_ASSERT_M("Circular buffer max write failed",
944                                 circular_buffer_write(&cb, bigbuf, mxsize) == mxsize);
945
946         memset(bigbuf, 17, cbsize);
947         csize = circular_buffer_read(&cb, bigbuf, mxsize, 0);
948         KT_ASSERT_M("Invalid max record read size", csize == mxsize);
949
950         for (size_t i = 0; i < csize; i++)
951                 KT_ASSERT_M("Invalid max record value", bigbuf[i] == 0);
952
953         kfree(bigbuf);
954
955         circular_buffer_destroy(&cb);
956
957         return TRUE;
958 }
959
960 /* Ghetto test, only tests one prod or consumer at a time */
961 // TODO: Un-guetto test, add assertions.
962 bool test_bcq(void)
963 {
964         /* Tests a basic struct */
965         struct my_struct {
966                 int x;
967                 int y;
968         };
969         struct my_struct in_struct, out_struct;
970         
971         DEFINE_BCQ_TYPES(test, struct my_struct, 16);
972         struct test_bcq t_bcq;
973         bcq_init(&t_bcq, struct my_struct, 16);
974         
975         in_struct.x = 4;
976         in_struct.y = 5;
977         out_struct.x = 1;
978         out_struct.y = 2;
979         
980         bcq_enqueue(&t_bcq, &in_struct, 16, 5);
981         bcq_dequeue(&t_bcq, &out_struct, 16);
982         printk("out x %d. out y %d\n", out_struct.x, out_struct.y);
983         
984         /* Tests the BCQ a bit more, esp with overflow */
985         #define NR_ELEM_A_BCQ 8 /* NOTE: this must be a power of 2! */
986         DEFINE_BCQ_TYPES(my, int, NR_ELEM_A_BCQ);
987         struct my_bcq a_bcq;
988         bcq_init(&a_bcq, int, NR_ELEM_A_BCQ);
989         
990         int y = 2;
991         int output[100];
992         int retval[100];
993
994         /* Helpful debugger */
995         void print_a_bcq(struct my_bcq *bcq)
996         {
997                 printk("A BCQ (made of ints): %p\n", bcq);
998                 printk("\tprod_idx: %p\n", bcq->hdr.prod_idx);
999                 printk("\tcons_pub_idx: %p\n", bcq->hdr.cons_pub_idx);
1000                 printk("\tcons_pvt_idx: %p\n", bcq->hdr.cons_pvt_idx);
1001                 for (int i = 0; i < NR_ELEM_A_BCQ; i++) {
1002                         printk("Element %d, rdy_for_cons: %02p\n", i,
1003                                bcq->wraps[i].rdy_for_cons);
1004                 }
1005         }
1006
1007         /* Put in more than it can take */
1008         for (int i = 0; i < 15; i++) {
1009                 y = i;
1010                 retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
1011                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
1012         }
1013         //print_a_bcq(&a_bcq);
1014         
1015         /* Try to dequeue more than we put in */
1016         for (int i = 0; i < 15; i++) {
1017                 retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
1018                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
1019         }
1020         //print_a_bcq(&a_bcq);
1021         
1022         /* Put in some it should be able to take */
1023         for (int i = 0; i < 3; i++) {
1024                 y = i;
1025                 retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
1026                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
1027         }
1028         
1029         /* Take those, and then a couple extra */
1030         for (int i = 0; i < 5; i++) {
1031                 retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
1032                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
1033         }
1034         
1035         /* Try some one-for-one */
1036         for (int i = 0; i < 5; i++) {
1037                 y = i;
1038                 retval[i] = bcq_enqueue(&a_bcq, &y, NR_ELEM_A_BCQ, 10);
1039                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
1040                 retval[i] = bcq_dequeue(&a_bcq, &output[i], NR_ELEM_A_BCQ);
1041                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
1042         }
1043
1044         return true;
1045 }
1046
1047 /* Test a simple concurrent send and receive (one prod, one cons).  We spawn a
1048  * process that will go into _M mode on another core, and we'll do the test from
1049  * an alarm handler run on our core.  When we start up the process, we won't
1050  * return so we need to defer the work with an alarm. */
1051 // TODO: Check if we can add more assertions.
1052 bool test_ucq(void)
1053 {
1054         struct timer_chain *tchain = &per_cpu_info[core_id()].tchain;
1055         struct alarm_waiter *waiter = kmalloc(sizeof(struct alarm_waiter), 0);
1056
1057         /* Alarm handler: what we want to do after the process is up */
1058         void send_msgs(struct alarm_waiter *waiter)
1059         {
1060                 struct timer_chain *tchain;
1061                 struct proc *p = waiter->data;
1062                 uintptr_t old_proc;
1063                 struct ucq *ucq = (struct ucq*)USTACKTOP;
1064                 struct event_msg msg;
1065
1066                 printk("Running the alarm handler!\n");
1067                 printk("NR msg per page: %d\n", NR_MSG_PER_PAGE);
1068                 /* might not be mmaped yet, if not, abort.  We used to user_mem_check,
1069                  * but now we just touch it and PF. */
1070                 char touch = *(char*)ucq;
1071                 asm volatile ("" : : "r"(touch));
1072                 /* load their address space */
1073                 old_proc = switch_to(p);
1074                 /* So it's mmaped, see if it is ready (note that this is dangerous) */
1075                 if (!ucq->ucq_ready) {
1076                         printk("Not ready yet\n");
1077                         switch_back(p, old_proc);
1078                         goto abort;
1079                 }
1080                 /* So it's ready, time to finally do the tests... */
1081                 printk("[kernel] Finally starting the tests... \n");
1082                 /* 1: Send a simple message */
1083                 printk("[kernel] #1 Sending simple message (7, deadbeef)\n");
1084                 msg.ev_type = 7;
1085                 msg.ev_arg2 = 0xdeadbeef;
1086                 send_ucq_msg(ucq, p, &msg);
1087                 printk("nr_pages: %d\n", atomic_read(&ucq->nr_extra_pgs));
1088                 /* 2: Send a bunch.  In a VM, this causes one swap, and then a bunch of
1089                  * mmaps. */
1090                 printk("[kernel] #2 \n");
1091                 for (int i = 0; i < 5000; i++) {
1092                         msg.ev_type = i;
1093                         send_ucq_msg(ucq, p, &msg);
1094                 }
1095                 printk("nr_pages: %d\n", atomic_read(&ucq->nr_extra_pgs));
1096                 printk("[kernel] #3 \n");
1097                 /* 3: make sure we chained pages (assuming 1k is enough) */
1098                 for (int i = 0; i < 1000; i++) {
1099                         msg.ev_type = i;
1100                         send_ucq_msg(ucq, p, &msg);
1101                 }
1102                 printk("nr_pages: %d\n", atomic_read(&ucq->nr_extra_pgs));
1103                 /* other things we could do:
1104                  *  - concurrent producers / consumers...  ugh.
1105                  *  - would require a kmsg to another core, instead of a local alarm
1106                  */
1107                 /* done, switch back and free things */
1108                 switch_back(p, old_proc);
1109                 proc_decref(p);
1110                 kfree(waiter); /* since it was kmalloc()d */
1111                 return;
1112         abort:
1113                 tchain = &per_cpu_info[core_id()].tchain;
1114                 /* Set to run again */
1115                 set_awaiter_rel(waiter, 1000000);
1116                 set_alarm(tchain, waiter);
1117         }
1118         /* Set up a handler to run the real part of the test */
1119         init_awaiter(waiter, send_msgs);
1120         set_awaiter_rel(waiter, 1000000);       /* 1s should be long enough */
1121         set_alarm(tchain, waiter);
1122         /* Just spawn the program */
1123         struct file *program;
1124         program = do_file_open("/bin/ucq", O_READ, 0);
1125         
1126         KT_ASSERT_M("We should be able to find /bin/ucq", 
1127                     program);
1128
1129         struct proc *p = proc_create(program, NULL, NULL);
1130         proc_wakeup(p);
1131         /* instead of getting rid of the reference created in proc_create, we'll put
1132          * it in the awaiter */
1133         waiter->data = p;
1134         kref_put(&program->f_kref);
1135         /* Should never return from schedule (env_pop in there) also note you may
1136          * not get the process you created, in the event there are others floating
1137          * around that are runnable */
1138         run_scheduler();
1139         smp_idle();
1140         
1141         KT_ASSERT_M("We should never return from schedule",
1142                     false);
1143
1144         return true;
1145 }
1146
1147 /* rudimentary tests.  does the basics, create, merge, split, etc.  Feel free to
1148  * add more, esp for the error conditions and finding free slots.  This is also
1149  * a bit lazy with setting the caller's fields (perm, flags, etc). */
1150 // TODO: See if we could add more assertions, try to add more descriptive
1151 //       messages to assertions.
1152 bool test_vm_regions(void)
1153 {
1154         #define MAX_VMR_TESTS 10
1155         struct proc pr, *p = &pr;       /* too lazy to even create one */
1156         int n = 0;
1157         TAILQ_INIT(&p->vm_regions);
1158
1159         struct vmr_summary {
1160                 uintptr_t base; 
1161                 uintptr_t end; 
1162         };
1163         int check_vmrs(struct proc *p, struct vmr_summary *results, int len, int n)
1164         {
1165                 int count = 0;
1166                 struct vm_region *vmr;
1167                 TAILQ_FOREACH(vmr, &p->vm_regions, vm_link) {
1168                         if (count >= len) {
1169                                 printk("More vm_regions than expected\n");
1170                                 break;
1171                         }
1172                         if ((vmr->vm_base != results[count].base) ||
1173                             (vmr->vm_end != results[count].end)) {
1174                                 printk("VM test case %d failed!\n", n);
1175                                 print_vmrs(p);
1176                                 return -1;
1177                         }
1178                         count++;
1179                 }
1180                 return count;
1181         }
1182         struct vm_region *vmrs[MAX_VMR_TESTS];
1183         struct vmr_summary results[MAX_VMR_TESTS];
1184
1185         memset(results, 0, sizeof(results));
1186         /* Make one */
1187         vmrs[0] = create_vmr(p, 0x2000, 0x1000);
1188         results[0].base = 0x2000;
1189         results[0].end = 0x3000;
1190         check_vmrs(p, results, 1, n++);
1191         /* Grow it */
1192         grow_vmr(vmrs[0], 0x4000);
1193         results[0].base = 0x2000;
1194         results[0].end = 0x4000;
1195         check_vmrs(p, results, 1, n++);
1196         /* Grow it poorly */
1197         KT_ASSERT_M("It should pass bad grow test", 
1198                     (-1 == grow_vmr(vmrs[0], 0x3000)));
1199         check_vmrs(p, results, 1, n++);
1200         /* Make another right next to it */
1201         vmrs[1] = create_vmr(p, 0x4000, 0x1000);
1202         results[1].base = 0x4000;
1203         results[1].end = 0x5000;
1204         check_vmrs(p, results, 2, n++);
1205         /* try to grow through it */
1206         KT_ASSERT_M("It should pass bad grow test", 
1207                     (-1 == grow_vmr(vmrs[0], 0x5000)));
1208         check_vmrs(p, results, 2, n++);
1209         /* Merge them */
1210         merge_vmr(vmrs[0], vmrs[1]);
1211         results[0].end = 0x5000;
1212         results[1].base = 0;
1213         results[1].end = 0;
1214         check_vmrs(p, results, 1, n++);
1215         vmrs[1]= create_vmr(p, 0x6000, 0x4000);
1216         results[1].base = 0x6000;
1217         results[1].end = 0xa000;
1218         check_vmrs(p, results, 2, n++);
1219         /* try to merge unmergables (just testing ranges) */
1220         KT_ASSERT_M("It should pass bad merge test", 
1221                     (-1 == merge_vmr(vmrs[0], vmrs[1])));
1222         check_vmrs(p, results, 2, n++);
1223         vmrs[2] = split_vmr(vmrs[1], 0x8000);
1224         results[1].end = 0x8000;
1225         results[2].base = 0x8000;
1226         results[2].end = 0xa000;
1227         check_vmrs(p, results, 3, n++);
1228         /* destroy one */
1229         destroy_vmr(vmrs[1]);
1230         results[1].base = 0x8000;
1231         results[1].end = 0xa000;
1232         check_vmrs(p, results, 2, n++);
1233         /* shrink */
1234         shrink_vmr(vmrs[2], 0x9000);
1235         results[1].base = 0x8000;
1236         results[1].end = 0x9000;
1237         check_vmrs(p, results, 2, n++); /* 10 */
1238         KT_ASSERT_M("We should be able to find the right vmr", 
1239                     (vmrs[2] == find_vmr(p, 0x8500)));
1240         KT_ASSERT_M("We should be able to find the right vmr", 
1241                     (vmrs[2] == find_first_vmr(p, 0x8500)));
1242         KT_ASSERT_M("We should be able to find the right vmr", 
1243                     (vmrs[2] == find_first_vmr(p, 0x7500)));
1244         KT_ASSERT_M("We shouldn't be able to find a vmr", 
1245                     !(find_first_vmr(p, 0x9500)));
1246         /* grow up to another */
1247         grow_vmr(vmrs[0], 0x8000);
1248         results[0].end = 0x8000;
1249         check_vmrs(p, results, 2, n++);
1250         vmrs[0]->vm_prot = 88;
1251         vmrs[2]->vm_prot = 77;
1252         /* should be unmergeable due to perms */
1253         KT_ASSERT_M("It should pass bad merge test", 
1254                     -1 == merge_vmr(vmrs[0], vmrs[2]));
1255         check_vmrs(p, results, 2, n++);
1256         /* should merge now */
1257         vmrs[2]->vm_prot = 88;
1258         merge_vmr(vmrs[0], vmrs[2]);
1259         results[0].end = 0x9000;
1260         check_vmrs(p, results, 1, n++);
1261         destroy_vmr(vmrs[0]);
1262         check_vmrs(p, results, 0, n++);
1263         /* Check the automerge function */
1264         vmrs[0] = create_vmr(p, 0x2000, 0x1000);
1265         vmrs[1] = create_vmr(p, 0x3000, 0x1000);
1266         vmrs[2] = create_vmr(p, 0x4000, 0x1000);
1267         for (int i = 0; i < 3; i++) {
1268                 vmrs[i]->vm_prot = PROT_READ;
1269                 vmrs[i]->vm_flags = 0;
1270                 vmrs[i]->vm_file = 0; /* would like to test this, it's a pain for now */
1271         }
1272         vmrs[0] = merge_me(vmrs[1]);
1273         results[0].base = 0x2000;
1274         results[0].end = 0x5000;
1275         check_vmrs(p, results, 1, n++);
1276         destroy_vmr(vmrs[0]);
1277         check_vmrs(p, results, 0, n++);
1278         /* Check unfixed creation requests */
1279         vmrs[0] = create_vmr(p, 0x0000, 0x1000);
1280         vmrs[1] = create_vmr(p, 0x0000, 0x1000);
1281         vmrs[2] = create_vmr(p, 0x0000, 0x1000);
1282         results[0].base = 0x0000;
1283         results[0].end  = 0x1000;
1284         results[1].base = 0x1000;
1285         results[1].end  = 0x2000;
1286         results[2].base = 0x2000;
1287         results[2].end  = 0x3000;
1288         check_vmrs(p, results, 3, n++);
1289
1290         return true;
1291 }
1292
1293 bool test_radix_tree(void)
1294 {
1295         struct radix_tree real_tree = RADIX_INITIALIZER;
1296         struct radix_tree *tree = &real_tree;
1297         void *retval;
1298
1299         KT_ASSERT_M("It should be possible to insert at 0", 
1300                     !radix_insert(tree, 0, (void*)0xdeadbeef, 0));
1301         radix_delete(tree, 0);
1302         KT_ASSERT_M("It should be possible to re-insert at 0", 
1303                     !radix_insert(tree, 0, (void*)0xdeadbeef, 0));
1304
1305         KT_ASSERT_M("It should be possible to insert first", 
1306                     !radix_insert(tree, 3, (void*)0xdeadbeef, 0));
1307         radix_insert(tree, 4, (void*)0x04040404, 0);
1308         KT_ASSERT((void*)0xdeadbeef == radix_lookup(tree, 3));
1309         for (int i = 5; i < 100; i++)
1310                 if ((retval = radix_lookup(tree, i))) {
1311                         printk("Extra item %p at slot %d in tree %p\n", retval, i,
1312                                tree);
1313                         print_radix_tree(tree);
1314                         monitor(0);
1315                 }
1316         KT_ASSERT_M("It should be possible to insert a two-tier", 
1317                     !radix_insert(tree, 65, (void*)0xcafebabe, 0));
1318         KT_ASSERT_M("It should not be possible to reinsert", 
1319                     radix_insert(tree, 4, (void*)0x03030303, 0));
1320         KT_ASSERT_M("It should be possible to insert a two-tier boundary", 
1321                     !radix_insert(tree, 4095, (void*)0x4095, 0));
1322         KT_ASSERT_M("It should be possible to insert a three-tier", 
1323                     !radix_insert(tree, 4096, (void*)0x4096, 0));
1324         //print_radix_tree(tree);
1325         radix_delete(tree, 65);
1326         radix_delete(tree, 3);
1327         radix_delete(tree, 4);
1328         radix_delete(tree, 4095);
1329         radix_delete(tree, 4096);
1330         //print_radix_tree(tree);
1331
1332         return true;
1333 }
1334
1335 /* Assorted FS tests, which were hanging around in init.c */
1336 // TODO: remove all the print statements and try to convert most into assertions
1337 bool test_random_fs(void)
1338 {
1339         int retval = do_symlink("/dir1/sym", "/bin/hello", S_IRWXU);
1340         KT_ASSERT_M("symlink1 should be created successfully", 
1341                     (!retval));
1342         retval = do_symlink("/symdir", "/dir1/dir1-1", S_IRWXU);
1343         KT_ASSERT_M("symlink1 should be created successfully", 
1344                     (!retval));
1345         retval = do_symlink("/dir1/test.txt", "/dir2/test2.txt", S_IRWXU);
1346         KT_ASSERT_M("symlink2 should be created successfully", 
1347                     (!retval));
1348         retval = do_symlink("/dir1/dir1-1/up", "../../", S_IRWXU);
1349         KT_ASSERT_M("symlink3 should be created successfully", 
1350                     (!retval));
1351         retval = do_symlink("/bin/hello-sym", "hello", S_IRWXU);
1352         KT_ASSERT_M("symlink4 should be created successfully", 
1353                     (!retval));
1354
1355         struct dentry *dentry;
1356         struct nameidata nd_r = {0}, *nd = &nd_r;
1357         retval = path_lookup("/dir1/sym", 0, nd);
1358         KT_ASSERT_M("symlink lookup should work for an existing symlink", 
1359                     (!retval)); 
1360         char *symname = nd->dentry->d_inode->i_op->readlink(nd->dentry);
1361         printk("Pathlookup got %s (sym)\n", nd->dentry->d_name.name);
1362         if (!symname)
1363                 printk("symlink reading failed\n");
1364         else
1365                 printk("Symname: %s (/bin/hello)\n", symname);
1366         path_release(nd);
1367         /* try with follow */
1368         memset(nd, 0, sizeof(struct nameidata));
1369         retval = path_lookup("/dir1/sym", LOOKUP_FOLLOW, nd);
1370         
1371         KT_ASSERT_M("symlink lookup should work for an existing symlink", 
1372                     (!retval));
1373         printk("Pathlookup got %s (hello)\n", nd->dentry->d_name.name);
1374         path_release(nd);
1375         
1376         /* try with a directory */
1377         memset(nd, 0, sizeof(struct nameidata));
1378         retval = path_lookup("/symdir/f1-1.txt", 0, nd);
1379         KT_ASSERT_M("symlink lookup should work for an existing symlink", 
1380                     (!retval));
1381         printk("Pathlookup got %s (f1-1.txt)\n", nd->dentry->d_name.name);
1382         path_release(nd);
1383         
1384         /* try with a rel path */
1385         printk("Try with a rel path\n");
1386         memset(nd, 0, sizeof(struct nameidata));
1387         retval = path_lookup("/symdir/up/hello.txt", 0, nd);
1388         KT_ASSERT_M("symlink lookup should work for an existing symlink", 
1389                     (!retval));
1390         printk("Pathlookup got %s (hello.txt)\n", nd->dentry->d_name.name);
1391         path_release(nd);
1392         
1393         printk("Try for an ELOOP\n");
1394         memset(nd, 0, sizeof(struct nameidata));
1395         retval = path_lookup("/symdir/up/symdir/up/symdir/up/symdir/up/hello.txt", 0, nd);
1396         KT_ASSERT_M("symlink lookup should fail for a non existing symlink", 
1397                     (retval));
1398         path_release(nd);
1399
1400         return true;
1401 }
1402
1403 /* Kernel message to restart our kthread */
1404 static void __test_up_sem(uint32_t srcid, long a0, long a1, long a2)
1405 {
1406         struct semaphore *sem = (struct semaphore*)a0;
1407         printk("[kmsg] Upping the sem to start the kthread, stacktop is %p\n",
1408                    get_stack_top());
1409         if (!sem_up(sem)) {
1410                 printk("[kmsg] Crap, the sem didn't have a kthread waiting!\n");
1411                 return;
1412         }
1413         printk("Kthread will restart when we handle the __launch RKM\n");
1414 }
1415
1416 /* simple test - start one, do something else, and resume it.  For lack of a
1417  * better infrastructure, we send ourselves a kmsg to run the kthread, which
1418  * we'll handle in smp_idle (which you may have to manually call).  Note this
1419  * doesn't test things like memory being leaked, or dealing with processes. */
1420 // TODO: Add assertions.
1421 bool test_kthreads(void)
1422 {
1423         struct semaphore sem = SEMAPHORE_INITIALIZER(sem, 1);
1424         printk("We're a kthread!  Stacktop is %p.  Testing suspend, etc...\n",
1425                get_stack_top());
1426         /* So we have something that will wake us up.  Routine messages won't get
1427          * serviced in the kernel right away. */
1428         send_kernel_message(core_id(), __test_up_sem, (long)&sem, 0, 0,
1429                             KMSG_ROUTINE);
1430         /* Actually block (or try to) */
1431         /* This one shouldn't block - but will test the unwind (if 1 above) */
1432         printk("About to sleep, but should unwind (signal beat us)\n");
1433         sem_down(&sem);
1434         /* This one is for real, yo.  Run and tell that. */
1435         printk("About to sleep for real\n");
1436         sem_down(&sem);
1437         printk("Kthread restarted!, Stacktop is %p.\n", get_stack_top());
1438
1439         return true;
1440 }
1441
1442 /* Second player's kmsg */
1443 static void __test_kref_2(uint32_t srcid, long a0, long a1, long a2)
1444 {
1445         struct kref *kref = (struct kref*)a0;
1446         bool *done = (bool*)a1;
1447         enable_irq();
1448         for (int i = 0; i < 10000000; i++) {
1449                 kref_get(kref, 1);
1450                 set_core_timer(1, TRUE);
1451                 udelay(2);
1452                 kref_put(kref);
1453         }
1454         *done = TRUE;
1455 }
1456
1457 /* Runs a simple test between core 0 (caller) and core 2 */
1458 // TODO: I believe we need more assertions.
1459 bool test_kref(void)
1460 {
1461         struct kref local_kref;
1462         bool done = FALSE;
1463         
1464         kref_init(&local_kref, fake_release, 1);
1465         send_kernel_message(2, __test_kref_2, (long)&local_kref, (long)&done, 0,
1466                             KMSG_ROUTINE);
1467         for (int i = 0; i < 10000000; i++) {
1468                 kref_get(&local_kref, 1);
1469                 udelay(2);
1470                 kref_put(&local_kref);
1471         }
1472         while (!done)
1473                 cpu_relax();
1474         KT_ASSERT(kref_refcnt(&local_kref) == 1);
1475         printk("[TEST-KREF] Simple 2-core getting/putting passed.\n");
1476
1477         return true;
1478 }
1479
1480 // TODO: Add more descriptive assertion messages.
1481 bool test_atomics(void)
1482 {
1483         /* subtract_and_test */
1484         atomic_t num;
1485         /* Test subing to 0 */
1486         atomic_init(&num, 1);
1487         KT_ASSERT(atomic_sub_and_test(&num, 1) == 1);
1488         atomic_init(&num, 2);
1489         KT_ASSERT(atomic_sub_and_test(&num, 2) == 1);
1490         /* Test not getting to 0 */
1491         atomic_init(&num, 1);
1492         KT_ASSERT(atomic_sub_and_test(&num, 0) == 0);
1493         atomic_init(&num, 2);
1494         KT_ASSERT(atomic_sub_and_test(&num, 1) == 0);
1495         /* Test negatives */
1496         atomic_init(&num, -1);
1497         KT_ASSERT(atomic_sub_and_test(&num, 1) == 0);
1498         atomic_init(&num, -1);
1499         KT_ASSERT(atomic_sub_and_test(&num, -1) == 1);
1500         /* Test larger nums */
1501         atomic_init(&num, 265);
1502         KT_ASSERT(atomic_sub_and_test(&num, 265) == 1);
1503         atomic_init(&num, 265);
1504         KT_ASSERT(atomic_sub_and_test(&num, 2) == 0);
1505
1506         /* CAS */
1507         /* Simple test, make sure the bool retval of CAS handles failure */
1508         bool test_cas_val(long init_val)
1509         {
1510                 atomic_t actual_num;
1511                 long old_num;
1512                 int attempt;
1513                 atomic_init(&actual_num, init_val);
1514                 attempt = 0;
1515                 do {
1516                         old_num = atomic_read(&actual_num);
1517                         /* First time, try to fail */
1518                         if (attempt == 0) 
1519                                 old_num++;
1520                         attempt++;      
1521                 } while (!atomic_cas(&actual_num, old_num, old_num + 10));
1522                 if (atomic_read(&actual_num) != init_val + 10) {
1523                         return false;
1524                 } else {
1525                         return true;
1526                 }
1527         }
1528         KT_ASSERT_M("CAS test for 257 should be successful.",
1529                     test_cas_val(257));
1530         KT_ASSERT_M("CAS test for 1 should be successful.",
1531                     test_cas_val(1));
1532         return true;
1533 }
1534
1535 /* Helper KMSG for test_abort.  Core 1 does this, while core 0 sends an IRQ. */
1536 static void __test_try_halt(uint32_t srcid, long a0, long a1, long a2)
1537 {
1538         disable_irq();
1539         /* wait 10 sec.  should have a bunch of ints pending */
1540         udelay(10000000);
1541         printk("Core 1 is about to halt\n");
1542         cpu_halt();
1543         printk("Returned from halting on core 1\n");
1544 }
1545
1546 /* x86 test, making sure our cpu_halt() and handle_irq() work.  If you want to
1547  * see it fail, you'll probably need to put a nop in the asm for cpu_halt(), and
1548  * comment out abort_halt() in handle_irq(). */
1549 // TODO: Add assertions.
1550 bool test_abort_halt(void)
1551 {
1552 #ifdef CONFIG_X86
1553         send_kernel_message(1, __test_try_halt, 0, 0, 0, KMSG_ROUTINE);
1554         /* wait 1 sec, enough time to for core 1 to be in its KMSG */
1555         udelay(1000000);
1556         /* Send an IPI */
1557         send_ipi(0x01, I_TESTING);
1558         printk("Core 0 sent the IPI\n");
1559 #endif /* CONFIG_X86 */
1560         return true;
1561 }
1562
1563 /* Funcs and global vars for test_cv() */
1564 static struct cond_var local_cv;
1565 static atomic_t counter;
1566 static struct cond_var *cv = &local_cv;
1567 static volatile bool state = FALSE;             /* for test 3 */
1568
1569 void __test_cv_signal(uint32_t srcid, long a0, long a1, long a2)
1570 {
1571         if (atomic_read(&counter) % 4)
1572                 cv_signal(cv);
1573         else
1574                 cv_broadcast(cv);
1575         atomic_dec(&counter);
1576 }
1577
1578 void __test_cv_waiter(uint32_t srcid, long a0, long a1, long a2)
1579 {
1580         cv_lock(cv);
1581         /* check state, etc */
1582         cv_wait_and_unlock(cv);
1583         atomic_dec(&counter);
1584 }
1585
1586 void __test_cv_waiter_t3(uint32_t srcid, long a0, long a1, long a2)
1587 {
1588         udelay(a0);
1589         /* if state == false, we haven't seen the signal yet */
1590         cv_lock(cv);
1591         while (!state) {
1592                 cpu_relax();
1593                 cv_wait(cv);    /* unlocks and relocks */
1594         }
1595         cv_unlock(cv);
1596         /* Make sure we are done, tell the controller we are done */
1597         cmb();
1598         assert(state);
1599         atomic_dec(&counter);
1600 }
1601
1602 // TODO: Add more assertions.
1603 bool test_cv(void)
1604 {
1605         int nr_msgs;
1606
1607         cv_init(cv);
1608         /* Test 0: signal without waiting */
1609         cv_broadcast(cv);
1610         cv_signal(cv);
1611         kthread_yield();
1612         printk("test_cv: signal without waiting complete\n");
1613
1614         /* Test 1: single / minimal shit */
1615         nr_msgs = num_cores - 1; /* not using cpu 0 */
1616         atomic_init(&counter, nr_msgs);
1617         for (int i = 1; i < num_cores; i++)
1618                 send_kernel_message(i, __test_cv_waiter, 0, 0, 0, KMSG_ROUTINE);
1619         udelay(1000000);
1620         cv_signal(cv);
1621         kthread_yield();
1622         while (atomic_read(&counter) != nr_msgs - 1)
1623                 cpu_relax();
1624         printk("test_cv: single signal complete\n");
1625         cv_broadcast(cv);
1626         /* broadcast probably woke up the waiters on our core.  since we want to
1627          * spin on their completion, we need to yield for a bit. */
1628         kthread_yield();
1629         while (atomic_read(&counter))
1630                 cpu_relax();
1631         printk("test_cv: broadcast signal complete\n");
1632
1633         /* Test 2: shitloads of waiters and signalers */
1634         nr_msgs = 0x500;        /* any more than 0x20000 could go OOM */
1635         atomic_init(&counter, nr_msgs);
1636         for (int i = 0; i < nr_msgs; i++) {
1637                 int cpu = (i % (num_cores - 1)) + 1;
1638                 if (atomic_read(&counter) % 5)
1639                         send_kernel_message(cpu, __test_cv_waiter, 0, 0, 0, KMSG_ROUTINE);
1640                 else
1641                         send_kernel_message(cpu, __test_cv_signal, 0, 0, 0, KMSG_ROUTINE);
1642         }
1643         kthread_yield();        /* run whatever messages we sent to ourselves */
1644         while (atomic_read(&counter)) {
1645                 cpu_relax();
1646                 cv_broadcast(cv);
1647                 udelay(1000000);
1648                 kthread_yield();        /* run whatever messages we sent to ourselves */
1649         }
1650         KT_ASSERT(!cv->nr_waiters);
1651         printk("test_cv: massive message storm complete\n");
1652
1653         /* Test 3: basic one signaller, one receiver.  we want to vary the amount of
1654          * time the sender and receiver delays, starting with (1ms, 0ms) and ending
1655          * with (0ms, 1ms).  At each extreme, such as with the sender waiting 1ms,
1656          * the receiver/waiter should hit the "check and wait" point well before the
1657          * sender/signaller hits the "change state and signal" point. */
1658         for (int i = 0; i < 1000; i++) {
1659                 for (int j = 0; j < 10; j++) {  /* some extra chances at each point */
1660                         state = FALSE;
1661                         atomic_init(&counter, 1);       /* signal that the client is done */
1662                         /* client waits for i usec */
1663                         send_kernel_message(2, __test_cv_waiter_t3, i, 0, 0, KMSG_ROUTINE);
1664                         cmb();
1665                         udelay(1000 - i);       /* senders wait time: 1000..0 */
1666                         state = TRUE;
1667                         cv_signal(cv);
1668                         /* signal might have unblocked a kthread, let it run */
1669                         kthread_yield();
1670                         /* they might not have run at all yet (in which case they lost the
1671                          * race and don't need the signal).  but we need to wait til they're
1672                          * done */
1673                         while (atomic_read(&counter))
1674                                 cpu_relax();
1675                         KT_ASSERT(!cv->nr_waiters);
1676                 }
1677         }
1678         printk("test_cv: single sender/receiver complete\n");
1679
1680         return true;
1681 }
1682
1683 /* Based on a bug I noticed.  TODO: actual memset test... */
1684 bool test_memset(void)
1685 {
1686         #define ARR_SZ 256
1687         
1688         void print_array(char *c, size_t len)
1689         {
1690                 for (int i = 0; i < len; i++)
1691                         printk("%04d: %02x\n", i, *c++);
1692         }
1693         
1694         bool check_array(char *c, char x, size_t len)
1695         {
1696                 for (int i = 0; i < len; i++) {
1697                         #define ASSRT_SIZE 64
1698                         char *assrt_msg = (char*) kmalloc(ASSRT_SIZE, 0);
1699                         snprintf(assrt_msg, ASSRT_SIZE, 
1700                                      "Char %d is %c (%02x), should be %c (%02x)", i, *c, *c,
1701                                      x, x);
1702                         KT_ASSERT_M(assrt_msg, (*c == x));
1703                         c++;
1704                 }
1705                 return true;
1706         }
1707         
1708         bool run_check(char *arr, int ch, size_t len)
1709         {
1710                 char *c = arr;
1711                 for (int i = 0; i < ARR_SZ; i++)
1712                         *c++ = 0x0;
1713                 memset(arr, ch, len - 4);
1714                 if (check_array(arr, ch, len - 4) &&
1715                     check_array(arr + len - 4, 0x0, 4)) {
1716                         return true;
1717                 } else {
1718                         return false;
1719                 }
1720         }
1721
1722         char bytes[ARR_SZ];
1723
1724         if (!run_check(bytes, 0xfe, 20) || !run_check(bytes, 0xc0fe, 20)) {
1725                 return false;
1726         }
1727
1728         return true;
1729 }
1730
1731 void __attribute__((noinline)) __longjmp_wrapper(struct jmpbuf* jb)
1732 {
1733         asm ("");
1734         printk("Starting: %s\n", __FUNCTION__);
1735         longjmp(jb, 1);
1736         // Should never get here
1737         printk("Exiting: %s\n", __FUNCTION__); 
1738 }
1739
1740 // TODO: Add assertions.
1741 bool test_setjmp()
1742 {
1743         struct jmpbuf jb;
1744         printk("Starting: %s\n", __FUNCTION__);
1745         if (setjmp(&jb)) {
1746           printk("After second setjmp return: %s\n", __FUNCTION__);
1747     }
1748     else {
1749           printk("After first setjmp return: %s\n", __FUNCTION__);
1750       __longjmp_wrapper(&jb);
1751     }
1752         printk("Exiting: %s\n", __FUNCTION__);
1753
1754         return true;
1755 }
1756
1757 // TODO: add assertions.
1758 bool test_apipe(void)
1759 {
1760         static struct atomic_pipe test_pipe;
1761
1762         struct some_struct {
1763                 long x;
1764                 int y;
1765         };
1766         /* Don't go too big, or you'll run off the stack */
1767         #define MAX_BATCH 100
1768
1769         void __test_apipe_writer(uint32_t srcid, long a0, long a1, long a2)
1770         {
1771                 int ret, count_todo;
1772                 int total = 0;
1773                 struct some_struct local_str[MAX_BATCH];
1774                 for (int i = 0; i < MAX_BATCH; i++) {
1775                         local_str[i].x = 0xf00;
1776                         local_str[i].y = 0xba5;
1777                 }
1778                 /* testing 0, and max out at 50. [0, ... 50] */
1779                 for (int i = 0; i < MAX_BATCH + 1; i++) {
1780                         count_todo = i;
1781                         while (count_todo) {
1782                                 ret = apipe_write(&test_pipe, &local_str, count_todo);
1783                                 /* Shouldn't break, based on the loop counters */
1784                                 if (!ret) {
1785                                         printk("Writer breaking with %d left\n", count_todo);
1786                                         break;
1787                                 }
1788                                 total += ret;
1789                                 count_todo -= ret;
1790                         }
1791                 }
1792                 printk("Writer done, added %d elems\n", total);
1793                 apipe_close_writer(&test_pipe);
1794         }
1795
1796         void __test_apipe_reader(uint32_t srcid, long a0, long a1, long a2)
1797         {
1798                 int ret, count_todo;
1799                 int total = 0;
1800                 struct some_struct local_str[MAX_BATCH] = {{0}};
1801                 /* reversed loop compared to the writer [50, ... 0] */
1802                 for (int i = MAX_BATCH; i >= 0; i--) {
1803                         count_todo = i;
1804                         while (count_todo) {
1805                                 ret = apipe_read(&test_pipe, &local_str, count_todo);
1806                                 if (!ret) {
1807                                         printk("Reader breaking with %d left\n", count_todo);
1808                                         break;
1809                                 }
1810                                 total += ret;
1811                                 count_todo -= ret;
1812                         }
1813                 }
1814                 printk("Reader done, took %d elems\n", total);
1815                 for (int i = 0; i < MAX_BATCH; i++) {
1816                         assert(local_str[i].x == 0xf00);
1817                         assert(local_str[i].y == 0xba5);
1818                 }
1819                 apipe_close_reader(&test_pipe);
1820         }
1821
1822         void *pipe_buf = kpage_alloc_addr();
1823         KT_ASSERT(pipe_buf);
1824         apipe_init(&test_pipe, pipe_buf, PGSIZE, sizeof(struct some_struct));
1825         printd("*ap_buf %p\n", test_pipe.ap_buf);
1826         printd("ap_ring_sz %p\n", test_pipe.ap_ring_sz);
1827         printd("ap_elem_sz %p\n", test_pipe.ap_elem_sz);
1828         printd("ap_rd_off %p\n", test_pipe.ap_rd_off);
1829         printd("ap_wr_off %p\n", test_pipe.ap_wr_off);
1830         printd("ap_nr_readers %p\n", test_pipe.ap_nr_readers);
1831         printd("ap_nr_writers %p\n", test_pipe.ap_nr_writers);
1832         send_kernel_message(0, __test_apipe_writer, 0, 0, 0, KMSG_ROUTINE);
1833         /* Once we start synchronizing with a kmsg / kthread that could be on a
1834          * different core, we run the chance of being migrated when we block. */
1835         __test_apipe_reader(0, 0, 0, 0);
1836         /* Wait til the first test is done */
1837         while (test_pipe.ap_nr_writers) {
1838                 kthread_yield();
1839                 cpu_relax();
1840         }
1841         /* Try cross core (though CV wake ups schedule on the waking core) */
1842         apipe_open_reader(&test_pipe);
1843         apipe_open_writer(&test_pipe);
1844         send_kernel_message(1, __test_apipe_writer, 0, 0, 0, KMSG_ROUTINE);
1845         __test_apipe_reader(0, 0, 0, 0);
1846         /* We could be on core 1 now.  If we were called from core0, our caller
1847          * might expect us to return while being on core 0 (like if we were kfunc'd
1848          * from the monitor.  Be careful if you copy this code. */
1849
1850         return true;
1851 }
1852
1853 static struct rwlock rwlock, *rwl = &rwlock;
1854 static atomic_t rwlock_counter;
1855 // TODO: Add assertions.
1856 bool test_rwlock(void)
1857 {
1858         bool ret;
1859         rwinit(rwl);
1860         /* Basic: can i lock twice, recursively? */
1861         rlock(rwl);
1862         ret = canrlock(rwl);
1863         KT_ASSERT(ret);
1864         runlock(rwl);
1865         runlock(rwl);
1866         /* Other simply tests */
1867         wlock(rwl);
1868         wunlock(rwl);
1869
1870         /* Just some half-assed different operations */
1871         void __test_rwlock(uint32_t srcid, long a0, long a1, long a2)
1872         {
1873                 int rand = read_tsc() & 0xff;
1874                 for (int i = 0; i < 10000; i++) {
1875                         switch ((rand * i) % 5) {
1876                                 case 0:
1877                                 case 1:
1878                                         rlock(rwl);
1879                                         runlock(rwl);
1880                                         break;
1881                                 case 2:
1882                                 case 3:
1883                                         if (canrlock(rwl))
1884                                                 runlock(rwl);
1885                                         break;
1886                                 case 4:
1887                                         wlock(rwl);
1888                                         wunlock(rwl);
1889                                         break;
1890                         }
1891                 }
1892                 /* signal to allow core 0 to finish */
1893                 atomic_dec(&rwlock_counter);
1894         }
1895                 
1896         /* send 4 messages to each non core 0 */
1897         atomic_init(&rwlock_counter, (num_cores - 1) * 4);
1898         for (int i = 1; i < num_cores; i++)
1899                 for (int j = 0; j < 4; j++)
1900                         send_kernel_message(i, __test_rwlock, 0, 0, 0, KMSG_ROUTINE);
1901         while (atomic_read(&rwlock_counter))
1902                 cpu_relax();
1903         printk("rwlock test complete\n");
1904
1905         return true;
1906 }
1907
1908 /* Funcs and global vars for test_rv() */
1909 static struct rendez local_rv;
1910 static struct rendez *rv = &local_rv;
1911 /* reusing state and counter from test_cv... */
1912
1913 static int __rendez_cond(void *arg)
1914 {
1915         return *(bool*)arg;
1916 }
1917
1918 void __test_rv_wakeup(uint32_t srcid, long a0, long a1, long a2)
1919 {
1920         if (atomic_read(&counter) % 4)
1921                 cv_signal(cv);
1922         else
1923                 cv_broadcast(cv);
1924         atomic_dec(&counter);
1925 }
1926
1927 void __test_rv_sleeper(uint32_t srcid, long a0, long a1, long a2)
1928 {
1929         rendez_sleep(rv, __rendez_cond, (void*)&state);
1930         atomic_dec(&counter);
1931 }
1932
1933 void __test_rv_sleeper_timeout(uint32_t srcid, long a0, long a1, long a2)
1934 {
1935         /* half-assed amount of time. */
1936         rendez_sleep_timeout(rv, __rendez_cond, (void*)&state, a0);
1937         atomic_dec(&counter);
1938 }
1939
1940 // TODO: Add more assertions.
1941 bool test_rv(void)
1942 {
1943         int nr_msgs;
1944
1945         rendez_init(rv);
1946         /* Test 0: signal without waiting */
1947         rendez_wakeup(rv);
1948         kthread_yield();
1949         printk("test_rv: wakeup without sleeping complete\n");
1950
1951         /* Test 1: a few sleepers */
1952         nr_msgs = num_cores - 1; /* not using cpu 0 */
1953         atomic_init(&counter, nr_msgs);
1954         state = FALSE;
1955         for (int i = 1; i < num_cores; i++)
1956                 send_kernel_message(i, __test_rv_sleeper, 0, 0, 0, KMSG_ROUTINE);
1957         udelay(1000000);
1958         cmb();
1959         state = TRUE;
1960         rendez_wakeup(rv);
1961         /* broadcast probably woke up the waiters on our core.  since we want to
1962          * spin on their completion, we need to yield for a bit. */
1963         kthread_yield();
1964         while (atomic_read(&counter))
1965                 cpu_relax();
1966         printk("test_rv: bulk wakeup complete\n");
1967
1968         /* Test 2: different types of sleepers / timeouts */
1969         state = FALSE;
1970         nr_msgs = 0x500;        /* any more than 0x20000 could go OOM */
1971         atomic_init(&counter, nr_msgs);
1972         for (int i = 0; i < nr_msgs; i++) {
1973                 int cpu = (i % (num_cores - 1)) + 1;
1974                 /* timeouts from 0ms ..5000ms (enough that they should wake via cond */
1975                 if (atomic_read(&counter) % 5)
1976                         send_kernel_message(cpu, __test_rv_sleeper_timeout, i * 4000, 0, 0,
1977                                             KMSG_ROUTINE);
1978                 else
1979                         send_kernel_message(cpu, __test_rv_sleeper, 0, 0, 0, KMSG_ROUTINE);
1980         }
1981         kthread_yield();        /* run whatever messages we sent to ourselves */
1982         state = TRUE;
1983         while (atomic_read(&counter)) {
1984                 cpu_relax();
1985                 rendez_wakeup(rv);
1986                 udelay(1000000);
1987                 kthread_yield();        /* run whatever messages we sent to ourselves */
1988         }
1989         KT_ASSERT(!rv->cv.nr_waiters);
1990         printk("test_rv: lots of sleepers/timeouts complete\n");
1991
1992         return true;
1993 }
1994
1995 /* Cheap test for the alarm internal management */
1996 // TODO: Add assertions.
1997 bool test_alarm(void)
1998 {
1999         uint64_t now = tsc2usec(read_tsc());
2000         struct alarm_waiter await1, await2;
2001         struct timer_chain *tchain = &per_cpu_info[0].tchain;
2002         void shouldnt_run(struct alarm_waiter *awaiter)
2003         {
2004                 printk("Crap, %p ran!\n", awaiter);
2005         }
2006         void empty_run(struct alarm_waiter *awaiter)
2007         {
2008                 printk("Yay, %p ran (hopefully twice)!\n", awaiter);
2009         }
2010         /* Test basic insert, move, remove */
2011         init_awaiter(&await1, shouldnt_run);
2012         set_awaiter_abs(&await1, now + 1000000000);
2013         set_alarm(tchain, &await1);
2014         reset_alarm_abs(tchain, &await1, now + 1000000000 - 50);
2015         reset_alarm_abs(tchain, &await1, now + 1000000000 + 50);
2016         unset_alarm(tchain, &await1);
2017         /* Test insert of one that fired already */
2018         init_awaiter(&await2, empty_run);
2019         set_awaiter_rel(&await2, 1);
2020         set_alarm(tchain, &await2);
2021         enable_irq();
2022         udelay(1000);
2023         reset_alarm_abs(tchain, &await2, now + 10);
2024         udelay(1000);
2025         unset_alarm(tchain, &await2);
2026
2027         printk("%s complete\n", __FUNCTION__);
2028
2029         return true;
2030 }
2031
2032 bool test_kmalloc_incref(void)
2033 {
2034         /* this test is a bit invasive of the kmalloc internals */
2035         void *__get_unaligned_orig_buf(void *buf)
2036         {
2037                 int *tag_flags = (int*)(buf - sizeof(int));
2038                 if ((*tag_flags & KMALLOC_FLAG_MASK) == KMALLOC_TAG_UNALIGN)
2039                         return (buf - (*tag_flags >> KMALLOC_ALIGN_SHIFT));
2040                 else
2041                         return 0;
2042         }
2043
2044         bool test_buftag(void *b, struct kmalloc_tag *btag, char *str)
2045         {
2046                 KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 1);
2047                 kmalloc_incref(b);
2048                 KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 2);
2049                 kfree(b);
2050                 KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 1);
2051                 kfree(b);
2052                 /* dangerous read, it's been freed */
2053                 KT_ASSERT_M(str, kref_refcnt(&btag->kref) == 0);
2054                 return TRUE;
2055         }
2056
2057         void *b1, *b2, *b2o;
2058         struct kmalloc_tag *b1tag, *b2tag;
2059
2060         /* no realigned case */
2061         b1 = kmalloc(55, 0);
2062         KT_ASSERT(!__get_unaligned_orig_buf(b1));
2063         b1tag = (struct kmalloc_tag*)(b1 - sizeof(struct kmalloc_tag));
2064
2065         /* realigned case.  alloc'd before b1's test, so we know we get different
2066          * buffers. */
2067         b2 = kmalloc_align(55, 0, 64);
2068         b2o = __get_unaligned_orig_buf(b2);
2069         KT_ASSERT(b2o);
2070         b2tag = (struct kmalloc_tag*)(b2o - sizeof(struct kmalloc_tag));
2071
2072         test_buftag(b1, b1tag, "b1, no realign");
2073         test_buftag(b2, b2tag, "b2, realigned");
2074
2075         return TRUE;
2076 }
2077
2078 /* Some ghetto things:
2079  * - ASSERT_M only lets you have a string, not a format string.
2080  * - put doesn't return, so we have a "loud" test for that.  alternatively, we
2081  *   could have put panic, but then we couldn't test it at all.  and i don't
2082  *   particularly want it to have a return value.
2083  * - ASSERT_M just blindly returns.  we're leaking memory.
2084  */
2085 bool test_u16pool(void)
2086 {
2087         #define AMT 4096
2088         int *t;
2089         struct u16_pool *id = create_u16_pool(AMT);
2090         int i, x, y;
2091         int numalloc;
2092         KT_ASSERT(id);
2093
2094         t = kzmalloc(sizeof(int) * (AMT + 1), KMALLOC_WAIT);
2095         for (x = 0; x < 1024; x++) {
2096                 KT_ASSERT_M("Should be empty", id->tos == 0);
2097                 for (i = 0; i < id->size; i++) {
2098                         int p = get_u16(id);
2099                         if (p < 0)
2100                                 KT_ASSERT_M("Couldn't get enough", 0);
2101                         t[i] = p;
2102                 }
2103                 numalloc = i;
2104                 // free them at random. With luck, we don't get too many duplicate
2105                 // hits.
2106                 for (y = i = 0; i < numalloc; y++) {
2107                         /* could read genrand, but that could be offline */
2108                         int f = (uint16_t)read_tsc() % numalloc;
2109                         if (!t[f])
2110                                 continue;
2111                         put_u16(id, t[f]);
2112                         t[f] = 0;
2113                         i++;
2114                         /* that's long enough... */
2115                         if (y > 2 * id->size)
2116                                 break;
2117                 }
2118                 /* grab the leftovers */
2119                 for (i = 0; i < id->size; i++) {
2120                         if (!t[i])
2121                                 continue;
2122                         put_u16(id, t[i]);
2123                         t[i] = 0;
2124                 }
2125                 /* all of our previous checks failed to give back 0 */
2126                 put_u16(id, 0);
2127         }
2128
2129         // pop too many.
2130         bool we_broke = FALSE;
2131         for (i = 0; i < id->size * 2; i++) {
2132                 x = get_u16(id);
2133                 if (x == -1) {
2134                         we_broke = TRUE;
2135                         break;
2136                 }
2137                 t[i] = x;
2138         }
2139         KT_ASSERT_M("Should have failed to get too many", we_broke);
2140
2141         numalloc = i;
2142
2143         printd("Allocated %d items\n", numalloc);
2144         for (i = 0; i < numalloc; i++) {
2145                 put_u16(id, t[i]);
2146                 t[i] = 0;
2147         }
2148         KT_ASSERT_M("Should be empty", id->tos == 0);
2149
2150         printk("Ignore next BAD, testing bad alloc\n");
2151         put_u16(id, 25);        // should get an error.
2152         for (i = 0; i < id->size; i++) {
2153                 int v = get_u16(id);
2154                 if (t[v])
2155                         printd("BAD: %d pops twice!\n", v);
2156                 KT_ASSERT_M("Popped twice!", t[v] == 0);
2157                 t[v] = 1;
2158                 //printk("%d,", v);
2159         }
2160
2161         for (i = 1; i < id->size; i++) {
2162                 if (!t[i])
2163                         printd("BAD: %d was not set\n", i);
2164                 KT_ASSERT_M("Wasn't set!", t[i]);
2165         }
2166
2167         kfree(t);
2168         return FALSE;
2169 }
2170
2171 bool test_uaccess(void)
2172 {
2173         char buf[128] = { 0 };
2174         char buf2[128] = { 0 };
2175         struct proc *tmp;
2176         int err;
2177         static const size_t mmap_size = 4096;
2178         void *addr;
2179
2180         err = proc_alloc(&tmp, 0, 0);
2181         KT_ASSERT_M("Failed to alloc a temp proc", err == 0);
2182         /* Tell everyone we're ready in case some ops don't work on PROC_CREATED */
2183         __proc_set_state(tmp, PROC_RUNNABLE_S);
2184
2185         addr = mmap(tmp, 0, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, -1, 0);
2186
2187         KT_ASSERT_M("Mmap failed", addr != MAP_FAILED);
2188
2189         KT_ASSERT_M(
2190                 "Copy to user (u8) to mapped address should not fail",
2191                 copy_to_user(addr, buf, 1) == 0);
2192         KT_ASSERT_M(
2193                 "Copy to user (u16) to mapped address should not fail",
2194                 copy_to_user(addr, buf, 2) == 0);
2195         KT_ASSERT_M(
2196                 "Copy to user (u32) to mapped address should not fail",
2197                 copy_to_user(addr, buf, 4) == 0);
2198         KT_ASSERT_M(
2199                 "Copy to user (u64) to mapped address should not fail",
2200                 copy_to_user(addr, buf, 8) == 0);
2201         KT_ASSERT_M(
2202                 "Copy to user (mem) to mapped address should not fail",
2203                 copy_to_user(addr, buf, sizeof(buf)) == 0);
2204
2205         KT_ASSERT_M(
2206                 "Copy from user (u8) to mapped address should not fail",
2207                 copy_from_user(buf, addr, 1) == 0);
2208         KT_ASSERT_M(
2209                 "Copy from user (u16) to mapped address should not fail",
2210                 copy_from_user(buf, addr, 2) == 0);
2211         KT_ASSERT_M(
2212                 "Copy from user (u32) to mapped address should not fail",
2213                 copy_from_user(buf, addr, 4) == 0);
2214         KT_ASSERT_M(
2215                 "Copy from user (u64) to mapped address should not fail",
2216                 copy_from_user(buf, addr, 8) == 0);
2217         KT_ASSERT_M(
2218                 "Copy from user (mem) to mapped address should not fail",
2219                 copy_from_user(buf, addr, sizeof(buf)) == 0);
2220
2221         KT_ASSERT_M(
2222                 "String copy to user to mapped address should not fail",
2223                 strcpy_to_user(current, addr, "Akaros") == 0);
2224         KT_ASSERT_M(
2225                 "String copy from user to mapped address should not fail",
2226                 strcpy_from_user(current, buf, addr) == 0);
2227         KT_ASSERT_M("The copied string content should be matching",
2228                                 memcmp(buf, "Akaros", 7) == 0);
2229
2230         munmap(tmp, (uintptr_t) addr, mmap_size);
2231
2232
2233         KT_ASSERT_M("Copy to user (u8) to not mapped address should fail",
2234                                 copy_to_user(addr, buf, 1) == -EFAULT);
2235         KT_ASSERT_M("Copy to user (u16) to not mapped address should fail",
2236                                 copy_to_user(addr, buf, 2) == -EFAULT);
2237         KT_ASSERT_M("Copy to user (u32) to not mapped address should fail",
2238                                 copy_to_user(addr, buf, 4) == -EFAULT);
2239         KT_ASSERT_M("Copy to user (u64) to not mapped address should fail",
2240                                 copy_to_user(addr, buf, 8) == -EFAULT);
2241         KT_ASSERT_M("Copy to user (mem) to not mapped address should fail",
2242                                 copy_to_user(addr, buf, sizeof(buf)) == -EFAULT);
2243
2244         KT_ASSERT_M("Copy from user (u8) to not mapped address should fail",
2245                                 copy_from_user(buf, addr, 1) == -EFAULT);
2246         KT_ASSERT_M("Copy from user (u16) to not mapped address should fail",
2247                                 copy_from_user(buf, addr, 2) == -EFAULT);
2248         KT_ASSERT_M("Copy from user (u32) to not mapped address should fail",
2249                                 copy_from_user(buf, addr, 4) == -EFAULT);
2250         KT_ASSERT_M("Copy from user (u64) to not mapped address should fail",
2251                                 copy_from_user(buf, addr, 8) == -EFAULT);
2252         KT_ASSERT_M("Copy from user (mem) to not mapped address should fail",
2253                                 copy_from_user(buf, addr, sizeof(buf)) == -EFAULT);
2254
2255         KT_ASSERT_M(
2256                 "String copy to user to not mapped address should fail",
2257                 strcpy_to_user(NULL, addr, "Akaros") == -EFAULT);
2258         KT_ASSERT_M(
2259                 "String copy from user to not mapped address should fail",
2260                 strcpy_from_user(NULL, buf, addr) == -EFAULT);
2261
2262         KT_ASSERT_M("Copy from user with kernel side source pointer should fail",
2263                                 copy_from_user(buf, buf2, sizeof(buf)) == -EFAULT);
2264         KT_ASSERT_M("Copy to user with kernel side source pointer should fail",
2265                                 copy_to_user(buf, buf2, sizeof(buf)) == -EFAULT);
2266
2267         proc_decref(tmp);
2268         return TRUE;
2269 }
2270
2271 bool test_sort(void)
2272 {
2273         int cmp_longs_asc(const void *p1, const void *p2)
2274         {
2275                 const long v1 = *(const long *) p1;
2276                 const long v2 = *(const long *) p2;
2277
2278                 return v1 < v2 ? -1 : (v1 > v2 ? 1 : 0);
2279         }
2280
2281         int cmp_longs_desc(const void *p1, const void *p2)
2282         {
2283                 const long v1 = *(const long *) p1;
2284                 const long v2 = *(const long *) p2;
2285
2286                 return v1 < v2 ? 1 : (v1 > v2 ? -1 : 0);
2287         }
2288
2289         size_t i;
2290         long long_set_1[] = {
2291                 -9, 11, 0, 23, 123, -99, 3, 11, 23, -999, 872, 17, 21
2292         };
2293         long long_set_2[] = {
2294                 31, 77, -1, 2, 0, 64, 11, 19, 69, 111, -89, 17, 21, 44, 77
2295         };
2296
2297         sort(long_set_1, ARRAY_SIZE(long_set_1), sizeof(long), cmp_longs_asc);
2298         for (i = 1; i < ARRAY_SIZE(long_set_1); i++)
2299                 KT_ASSERT(long_set_1[i - 1] <= long_set_1[i]);
2300
2301         sort(long_set_2, ARRAY_SIZE(long_set_2), sizeof(long), cmp_longs_desc);
2302         for (i = 1; i < ARRAY_SIZE(long_set_2); i++)
2303                 KT_ASSERT(long_set_2[i - 1] >= long_set_2[i]);
2304
2305         return TRUE;
2306 }
2307
2308 bool test_cmdline_parse(void)
2309 {
2310         static const char *fake_cmdline =
2311                 "kernel -root=/foo -simple -num=123 -quoted='abc \\'' -dup=311 "
2312                 "-dup='akaros' -empty='' -inner=-outer -outer=-inner=xyz";
2313         const char *opt;
2314         char param[128];
2315
2316         /* Note that the get_boot_option() API should be passed NULL the first time
2317          * it is called, in normal cases, and should be passed the value returned by
2318          * previous call to get_boot_option(), in case multiple options with same
2319          * name have to be fetched.
2320          */
2321         opt = get_boot_option(fake_cmdline, "-root", param, sizeof(param));
2322         KT_ASSERT_M("Unable to parse -root option", opt);
2323         KT_ASSERT_M("Invalid -root option value", strcmp(param, "/foo") == 0);
2324
2325         opt = get_boot_option(fake_cmdline, "-root", NULL, 0);
2326         KT_ASSERT_M("Unable to parse -root option when param not provided", opt);
2327
2328         opt = get_boot_option(fake_cmdline, "-simple", param, sizeof(param));
2329         KT_ASSERT_M("Unable to parse -simple option", opt);
2330         KT_ASSERT_M("Invalid -simple option value", strcmp(param, "") == 0);
2331
2332         opt = get_boot_option(fake_cmdline, "-num", param, sizeof(param));
2333         KT_ASSERT_M("Unable to parse -num option", opt);
2334         KT_ASSERT_M("Invalid -num option value", strcmp(param, "123") == 0);
2335
2336         opt = get_boot_option(fake_cmdline, "-quoted", param, sizeof(param));
2337         KT_ASSERT_M("Unable to parse -quoted option", opt);
2338         KT_ASSERT_M("Invalid -quoted option value", strcmp(param, "abc '") == 0);
2339
2340         opt = get_boot_option(fake_cmdline, "-dup", param, sizeof(param));
2341         KT_ASSERT_M("Unable to parse -dup option", opt);
2342         KT_ASSERT_M("Invalid -dup option first value", strcmp(param, "311") == 0);
2343
2344         opt = get_boot_option(opt, "-dup", param, sizeof(param));
2345         KT_ASSERT_M("Unable to parse -dup option", opt);
2346         KT_ASSERT_M("Invalid -dup option second value",
2347                                 strcmp(param, "akaros") == 0);
2348
2349         opt = get_boot_option(fake_cmdline, "-inner", param, sizeof(param));
2350         KT_ASSERT_M("Unable to parse -inner option", opt);
2351         KT_ASSERT_M("Invalid -inner option value", strcmp(param, "-outer") == 0);
2352
2353         opt = get_boot_option(opt, "-inner", param, sizeof(param));
2354         KT_ASSERT_M("Should not be parsing -inner as value", !opt);
2355
2356         opt = get_boot_option(fake_cmdline, "-outer", param, sizeof(param));
2357         KT_ASSERT_M("Unable to parse -outer option", opt);
2358         KT_ASSERT_M("Invalid -outer option value",
2359                                 strcmp(param, "-inner=xyz") == 0);
2360
2361         opt = get_boot_option(fake_cmdline, "-missing", param, sizeof(param));
2362         KT_ASSERT_M("Should not be parsing -missing option", !opt);
2363
2364         opt = get_boot_option(fake_cmdline, "-inne", NULL, 0);
2365         KT_ASSERT_M("Should not be parsing -inne option", !opt);
2366
2367         opt = get_boot_option(fake_cmdline, "-outera", NULL, 0);
2368         KT_ASSERT_M("Should not be parsing -outera option", !opt);
2369
2370         opt = get_boot_option(fake_cmdline, "-empty", param, sizeof(param));
2371         KT_ASSERT_M("Unable to parse -empty option", opt);
2372         KT_ASSERT_M("Invalid -empty option value", strcmp(param, "") == 0);
2373
2374         return TRUE;
2375 }
2376
2377 static struct ktest ktests[] = {
2378 #ifdef CONFIG_X86
2379         KTEST_REG(ipi_sending,        CONFIG_TEST_ipi_sending),
2380         KTEST_REG(pic_reception,      CONFIG_TEST_pic_reception),
2381         KTEST_REG(lapic_status_bit,   CONFIG_TEST_lapic_status_bit),
2382         KTEST_REG(pit,                CONFIG_TEST_pit),
2383         KTEST_REG(circ_buffer,        CONFIG_TEST_circ_buffer),
2384         KTEST_REG(kernel_messages,    CONFIG_TEST_kernel_messages),
2385 #endif // CONFIG_X86
2386 #ifdef CONFIG_PAGE_COLORING
2387         KTEST_REG(page_coloring,      CONFIG_TEST_page_coloring),
2388         KTEST_REG(color_alloc,        CONFIG_TEST_color_alloc),
2389 #endif // CONFIG_PAGE_COLORING
2390         KTEST_REG(barrier,            CONFIG_TEST_barrier),
2391         KTEST_REG(interrupts_irqsave, CONFIG_TEST_interrupts_irqsave),
2392         KTEST_REG(bitmasks,           CONFIG_TEST_bitmasks),
2393         KTEST_REG(checklists,         CONFIG_TEST_checklists),
2394         KTEST_REG(smp_call_functions, CONFIG_TEST_smp_call_functions),
2395         KTEST_REG(slab,               CONFIG_TEST_slab),
2396         KTEST_REG(kmalloc,            CONFIG_TEST_kmalloc),
2397         KTEST_REG(hashtable,          CONFIG_TEST_hashtable),
2398         KTEST_REG(circular_buffer,    CONFIG_TEST_circular_buffer),
2399         KTEST_REG(bcq,                CONFIG_TEST_bcq),
2400         KTEST_REG(ucq,                CONFIG_TEST_ucq),
2401         KTEST_REG(vm_regions,         CONFIG_TEST_vm_regions),
2402         KTEST_REG(radix_tree,         CONFIG_TEST_radix_tree),
2403         KTEST_REG(random_fs,          CONFIG_TEST_random_fs),
2404         KTEST_REG(kthreads,           CONFIG_TEST_kthreads),
2405         KTEST_REG(kref,               CONFIG_TEST_kref),
2406         KTEST_REG(atomics,            CONFIG_TEST_atomics),
2407         KTEST_REG(abort_halt,         CONFIG_TEST_abort_halt),
2408         KTEST_REG(cv,                 CONFIG_TEST_cv),
2409         KTEST_REG(memset,             CONFIG_TEST_memset),
2410         KTEST_REG(setjmp,             CONFIG_TEST_setjmp),
2411         KTEST_REG(apipe,              CONFIG_TEST_apipe),
2412         KTEST_REG(rwlock,             CONFIG_TEST_rwlock),
2413         KTEST_REG(rv,                 CONFIG_TEST_rv),
2414         KTEST_REG(alarm,              CONFIG_TEST_alarm),
2415         KTEST_REG(kmalloc_incref,     CONFIG_TEST_kmalloc_incref),
2416         KTEST_REG(u16pool,            CONFIG_TEST_u16pool),
2417         KTEST_REG(uaccess,            CONFIG_TEST_uaccess),
2418         KTEST_REG(sort,               CONFIG_TEST_sort),
2419         KTEST_REG(cmdline_parse,      CONFIG_TEST_cmdline_parse),
2420 };
2421 static int num_ktests = sizeof(ktests) / sizeof(struct ktest);
2422 linker_func_1(register_pb_ktests)
2423 {
2424         REGISTER_KTESTS(ktests, num_ktests);
2425 }
2426
2427 /* Linker function tests.  Keep them commented, etc. */
2428 #if 0
2429 linker_func_1(xme11)
2430 {
2431         printk("xme11\n");
2432 }
2433
2434 linker_func_1(xme12)
2435 {
2436         printk("xme12\n");
2437 }
2438
2439 linker_func_1(xme13)
2440 {
2441         printk("xme13\n");
2442 }
2443
2444 linker_func_1(xme14)
2445 {
2446         printk("xme14\n");
2447 }
2448
2449 linker_func_1(xme15)
2450 {
2451         printk("xme15\n");
2452 }
2453
2454 linker_func_2(xme21)
2455 {
2456         printk("xme21\n");
2457 }
2458
2459 linker_func_2(xme22)
2460 {
2461         printk("xme22\n");
2462 }
2463
2464 linker_func_2(xme23)
2465 {
2466         printk("xme23\n");
2467 }
2468
2469 linker_func_2(xme24)
2470 {
2471         printk("xme24\n");
2472 }
2473
2474 linker_func_2(xme25)
2475 {
2476         printk("xme25\n");
2477 }
2478
2479 linker_func_3(xme31)
2480 {
2481         printk("xme31\n");
2482 }
2483
2484 linker_func_3(xme32)
2485 {
2486         printk("xme32\n");
2487 }
2488
2489 linker_func_3(xme33)
2490 {
2491         printk("xme33\n");
2492 }
2493
2494 linker_func_3(xme34)
2495 {
2496         printk("xme34\n");
2497 }
2498
2499 linker_func_3(xme35)
2500 {
2501         printk("xme35\n");
2502 }
2503
2504 linker_func_4(xme41)
2505 {
2506         printk("xme41\n");
2507 }
2508
2509 linker_func_4(xme42)
2510 {
2511         printk("xme42\n");
2512 }
2513
2514 linker_func_4(xme43)
2515 {
2516         printk("xme43\n");
2517 }
2518
2519 linker_func_4(xme44)
2520 {
2521         printk("xme44\n");
2522 }
2523
2524 linker_func_4(xme45)
2525 {
2526         printk("xme45\n");
2527 }
2528 #endif /* linker func tests */