Fixes bug with radix_delete()
[akaros.git] / kern / src / testing.c
1
2 #ifdef __SHARC__
3 #pragma nosharc
4 #endif
5
6 #include <arch/mmu.h>
7 #include <arch/arch.h>
8 #include <arch/bitmask.h>
9 #include <smp.h>
10
11 #include <ros/memlayout.h>
12 #include <ros/common.h>
13 #include <ros/bcq.h>
14
15 #include <atomic.h>
16 #include <stdio.h>
17 #include <assert.h>
18 #include <string.h>
19 #include <testing.h>
20 #include <trap.h>
21 #include <arch/trap.h>
22 #include <process.h>
23 #include <syscall.h>
24 #include <timing.h>
25 #include <kfs.h>
26 #include <multiboot.h>
27 #include <pmap.h>
28 #include <page_alloc.h>
29 #include <pmap.h>
30 #include <slab.h>
31 #include <kmalloc.h>
32 #include <hashtable.h>
33 #include <radix.h>
34 #include <monitor.h>
35
36 #define l1 (available_caches.l1)
37 #define l2 (available_caches.l2)
38 #define l3 (available_caches.l3)
39
40 #ifdef __i386__
41
42 void test_ipi_sending(void)
43 {
44         extern handler_t (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
45         int8_t state = 0;
46
47         register_interrupt_handler(interrupt_handlers, I_TESTING,
48                                    test_hello_world_handler, NULL);
49         enable_irqsave(&state);
50         cprintf("\nCORE 0 sending broadcast\n");
51         send_broadcast_ipi(I_TESTING);
52         udelay(3000000);
53         cprintf("\nCORE 0 sending all others\n");
54         send_all_others_ipi(I_TESTING);
55         udelay(3000000);
56         cprintf("\nCORE 0 sending self\n");
57         send_self_ipi(I_TESTING);
58         udelay(3000000);
59         cprintf("\nCORE 0 sending ipi to physical 1\n");
60         send_ipi(get_hw_coreid(0x01), I_TESTING);
61         udelay(3000000);
62         cprintf("\nCORE 0 sending ipi to physical 2\n");
63         send_ipi(get_hw_coreid(0x02), I_TESTING);
64         udelay(3000000);
65         cprintf("\nCORE 0 sending ipi to physical 3\n");
66         send_ipi(get_hw_coreid(0x03), I_TESTING);
67         udelay(3000000);
68         cprintf("\nCORE 0 sending ipi to physical 15\n");
69         send_ipi(get_hw_coreid(0x0f), I_TESTING);
70         udelay(3000000);
71         cprintf("\nCORE 0 sending ipi to logical 2\n");
72         send_group_ipi(0x02, I_TESTING);
73         udelay(3000000);
74         cprintf("\nCORE 0 sending ipi to logical 1\n");
75         send_group_ipi(0x01, I_TESTING);
76         udelay(3000000);
77         cprintf("\nDone!\n");
78         disable_irqsave(&state);
79 }
80
81 // Note this never returns and will muck with any other timer work
82 void test_pic_reception(void)
83 {
84         register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
85         pit_set_timer(100,TIMER_RATEGEN); // totally arbitrary time
86         pic_unmask_irq(0);
87         cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
88         cprintf("PIC2 Mask = 0x%04x\n", inb(PIC2_DATA));
89         unmask_lapic_lvt(LAPIC_LVT_LINT0);
90         cprintf("Core %d's LINT0: 0x%08x\n", core_id(), read_mmreg32(LAPIC_LVT_LINT0));
91         enable_irq();
92         while(1);
93 }
94
95 void test_ioapic_pit_reroute(void) 
96 {
97         register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
98         ioapic_route_irq(0, 3); 
99
100         cprintf("Starting pit on core 3....\n");
101         udelay(3000000);
102         pit_set_timer(0xFFFE,TIMER_RATEGEN); // totally arbitrary time
103         
104         udelay(3000000);
105         ioapic_unroute_irq(0);
106         udelay(300000);
107         cprintf("Masked pit. Waiting before return...\n");
108         udelay(3000000);
109 }
110
111 #endif // __i386__
112
113
114 void test_print_info(void)
115 {
116         cprintf("\nCORE 0 asking all cores to print info:\n");
117         smp_call_function_all(test_print_info_handler, NULL, 0);
118         cprintf("\nDone!\n");
119 }
120
121 void test_page_coloring(void) 
122 {
123 /*
124         //Print the different cache properties of our machine
125         print_cache_properties("L1", l1);
126         cprintf("\n");
127         print_cache_properties("L2", l2);
128         cprintf("\n");
129         print_cache_properties("L3", l3);
130         cprintf("\n");
131
132         //Print some stats about our memory
133         cprintf("Max Address: %llu\n", MAX_VADDR);
134         cprintf("Num Pages: %u\n", npages);
135
136         //Declare a local variable for allocating pages 
137         page_t* page;
138
139         cprintf("Contents of the page free list:\n");
140         for(int i=0; i<llc_cache->num_colors; i++) {
141                 cprintf("  COLOR %d:\n", i);
142                 LIST_FOREACH(page, &colored_page_free_list[i], pg_link) {
143                         cprintf("    Page: %d\n", page2ppn(page));
144                 }
145         }
146
147         //Run through and allocate all pages through l1_page_alloc
148         cprintf("Allocating from L1 page colors:\n");
149         for(int i=0; i<get_cache_num_page_colors(l1); i++) {
150                 cprintf("  COLOR %d:\n", i);
151                 while(colored_page_alloc(l1, &page, i) != -ENOMEM)
152                         cprintf("    Page: %d\n", page2ppn(page));
153         }
154
155         //Put all the pages back by reinitializing
156         page_init();
157         
158         //Run through and allocate all pages through l2_page_alloc
159         cprintf("Allocating from L2 page colors:\n");
160         for(int i=0; i<get_cache_num_page_colors(l2); i++) {
161                 cprintf("  COLOR %d:\n", i);
162                 while(colored_page_alloc(l2, &page, i) != -ENOMEM)
163                         cprintf("    Page: %d\n", page2ppn(page));
164         }
165
166         //Put all the pages back by reinitializing
167         page_init();
168         
169         //Run through and allocate all pages through l3_page_alloc
170         cprintf("Allocating from L3 page colors:\n");
171         for(int i=0; i<get_cache_num_page_colors(l3); i++) {
172                 cprintf("  COLOR %d:\n", i);
173                 while(colored_page_alloc(l3, &page, i) != -ENOMEM)
174                         cprintf("    Page: %d\n", page2ppn(page));
175         }
176         
177         //Put all the pages back by reinitializing
178         page_init();
179         
180         //Run through and allocate all pages through page_alloc
181         cprintf("Allocating from global allocator:\n");
182         while(upage_alloc(&page) != -ENOMEM)
183                 cprintf("    Page: %d\n", page2ppn(page));
184         
185         if(colored_page_alloc(l2, &page, 0) != -ENOMEM)
186                 cprintf("Should not get here, all pages should already be gone!\n");
187         cprintf("All pages gone for sure...\n");
188         
189         //Now lets put a few pages back using page_free..
190         cprintf("Reinserting pages via page_free and reallocating them...\n");
191         page_free(&pages[0]);
192         page_free(&pages[15]);
193         page_free(&pages[7]);
194         page_free(&pages[6]);
195         page_free(&pages[4]);
196
197         while(upage_alloc(&page) != -ENOMEM)
198                 cprintf("Page: %d\n", page2ppn(page));  
199         
200         page_init();
201 */
202 }
203
204 void test_color_alloc() {
205         size_t checkpoint = 0;
206         uint8_t* colors_map = kmalloc(BYTES_FOR_BITMASK(llc_cache->num_colors), 0);
207         cache_color_alloc(l2, colors_map);
208         cache_color_alloc(l3, colors_map);
209         cache_color_alloc(l3, colors_map);
210         cache_color_alloc(l2, colors_map);
211         cache_color_free(llc_cache, colors_map);
212         cache_color_free(llc_cache, colors_map);
213         cache_color_free(llc_cache, colors_map);
214         cache_color_free(llc_cache, colors_map);
215         cache_color_free(llc_cache, colors_map);
216         cache_color_free(llc_cache, colors_map);
217         cache_color_free(llc_cache, colors_map);
218         cache_color_free(llc_cache, colors_map);
219         cache_color_free(llc_cache, colors_map);
220         cache_color_free(llc_cache, colors_map);
221         cache_color_free(llc_cache, colors_map);
222         cache_color_free(llc_cache, colors_map);
223         cache_color_free(llc_cache, colors_map);
224         cache_color_free(llc_cache, colors_map);
225         cache_color_free(llc_cache, colors_map);
226         cache_color_free(llc_cache, colors_map);
227         cache_color_free(l2, colors_map);
228         cache_color_free(llc_cache, colors_map);
229         cache_color_free(llc_cache, colors_map);
230
231 print_cache_colors:
232         printk("L1 free colors, tot colors: %d\n", l1->num_colors);
233         PRINT_BITMASK(l1->free_colors_map, l1->num_colors);
234         printk("L2 free colors, tot colors: %d\n", l2->num_colors);
235         PRINT_BITMASK(l2->free_colors_map, l2->num_colors);
236         printk("L3 free colors, tot colors: %d\n", l3->num_colors);
237         PRINT_BITMASK(l3->free_colors_map, l3->num_colors);
238         printk("Process allocated colors\n");
239         PRINT_BITMASK(colors_map, llc_cache->num_colors);
240         printk("test_color_alloc() complete!\n");
241 }
242
243 barrier_t test_cpu_array;
244
245 void test_barrier(void)
246 {
247         cprintf("Core 0 initializing barrier\n");
248         init_barrier(&test_cpu_array, num_cpus);
249         cprintf("Core 0 asking all cores to print ids, barrier, rinse, repeat\n");
250         smp_call_function_all(test_barrier_handler, NULL, 0);
251 }
252
253 void test_interrupts_irqsave(void)
254 {
255         int8_t state = 0;
256         printd("Testing Nesting Enabling first, turning ints off:\n");
257         disable_irq();
258         printd("Interrupts are: %x\n", irq_is_enabled());
259         assert(!irq_is_enabled());
260         printd("Enabling IRQSave\n");
261         enable_irqsave(&state);
262         printd("Interrupts are: %x\n", irq_is_enabled());
263         assert(irq_is_enabled());
264         printd("Enabling IRQSave Again\n");
265         enable_irqsave(&state);
266         printd("Interrupts are: %x\n", irq_is_enabled());
267         assert(irq_is_enabled());
268         printd("Disabling IRQSave Once\n");
269         disable_irqsave(&state);
270         printd("Interrupts are: %x\n", irq_is_enabled());
271         assert(irq_is_enabled());
272         printd("Disabling IRQSave Again\n");
273         disable_irqsave(&state);
274         printd("Interrupts are: %x\n", irq_is_enabled());
275         assert(!irq_is_enabled());
276         printd("Done.  Should have been 0, 200, 200, 200, 0\n");
277
278         printd("Testing Nesting Disabling first, turning ints on:\n");
279         state = 0;
280         enable_irq();
281         printd("Interrupts are: %x\n", irq_is_enabled());
282         assert(irq_is_enabled());
283         printd("Disabling IRQSave Once\n");
284         disable_irqsave(&state);
285         printd("Interrupts are: %x\n", irq_is_enabled());
286         assert(!irq_is_enabled());
287         printd("Disabling IRQSave Again\n");
288         disable_irqsave(&state);
289         printd("Interrupts are: %x\n", irq_is_enabled());
290         assert(!irq_is_enabled());
291         printd("Enabling IRQSave Once\n");
292         enable_irqsave(&state);
293         printd("Interrupts are: %x\n", irq_is_enabled());
294         assert(!irq_is_enabled());
295         printd("Enabling IRQSave Again\n");
296         enable_irqsave(&state);
297         printd("Interrupts are: %x\n", irq_is_enabled());
298         assert(irq_is_enabled());
299         printd("Done.  Should have been 200, 0, 0, 0, 200 \n");
300
301         state = 0;
302         disable_irq();
303         printd("Ints are off, enabling then disabling.\n");
304         enable_irqsave(&state);
305         printd("Interrupts are: %x\n", irq_is_enabled());
306         assert(irq_is_enabled());
307         disable_irqsave(&state);
308         printd("Interrupts are: %x\n", irq_is_enabled());
309         assert(!irq_is_enabled());
310         printd("Done.  Should have been 200, 0\n");
311
312         state = 0;
313         enable_irq();
314         printd("Ints are on, enabling then disabling.\n");
315         enable_irqsave(&state);
316         printd("Interrupts are: %x\n", irq_is_enabled());
317         assert(irq_is_enabled());
318         disable_irqsave(&state);
319         printd("Interrupts are: %x\n", irq_is_enabled());
320         assert(irq_is_enabled());
321         printd("Done.  Should have been 200, 200\n");
322
323         state = 0;
324         disable_irq();
325         printd("Ints are off, disabling then enabling.\n");
326         disable_irqsave(&state);
327         printd("Interrupts are: %x\n", irq_is_enabled());
328         assert(!irq_is_enabled());
329         enable_irqsave(&state);
330         printd("Interrupts are: %x\n", irq_is_enabled());
331         assert(!irq_is_enabled());
332         printd("Done.  Should have been 0, 0\n");
333
334         state = 0;
335         enable_irq();
336         printd("Ints are on, disabling then enabling.\n");
337         disable_irqsave(&state);
338         printd("Interrupts are: %x\n", irq_is_enabled());
339         assert(!irq_is_enabled());
340         enable_irqsave(&state);
341         printd("Interrupts are: %x\n", irq_is_enabled());
342         assert(irq_is_enabled());
343         printd("Done.  Should have been 0, 200\n");
344
345         disable_irq();
346         cprintf("Passed enable_irqsave tests\n");
347 }
348
349 void test_bitmasks(void)
350 {
351 #define masksize 67
352         DECL_BITMASK(mask, masksize);
353         printk("size of mask %d\n", sizeof(mask));
354         CLR_BITMASK(mask, masksize);
355         PRINT_BITMASK(mask, masksize);
356         printk("cleared\n");
357         SET_BITMASK_BIT(mask, 0);
358         SET_BITMASK_BIT(mask, 11);
359         SET_BITMASK_BIT(mask, 17);
360         SET_BITMASK_BIT(mask, masksize-1);
361         printk("bits set\n");
362         PRINT_BITMASK(mask, masksize);
363         DECL_BITMASK(mask2, masksize);
364         COPY_BITMASK(mask2, mask, masksize);
365         printk("copy of original mask, should be the same as the prev\n");
366         PRINT_BITMASK(mask2, masksize);
367         CLR_BITMASK_BIT(mask, 11);
368         printk("11 cleared\n");
369         PRINT_BITMASK(mask, masksize);
370         printk("bit 17 is %d (should be 1)\n", GET_BITMASK_BIT(mask, 17));
371         printk("bit 11 is %d (should be 0)\n", GET_BITMASK_BIT(mask, 11));
372         FILL_BITMASK(mask, masksize);
373         PRINT_BITMASK(mask, masksize);
374         printk("should be all 1's, except for a few at the end\n");
375         printk("Is Clear?: %d (should be 0)\n", BITMASK_IS_CLEAR(mask,masksize));
376         CLR_BITMASK(mask, masksize);
377         PRINT_BITMASK(mask, masksize);
378         printk("Is Clear?: %d (should be 1)\n", BITMASK_IS_CLEAR(mask,masksize));
379         printk("should be cleared\n");
380 }
381
382 checklist_t *RO the_global_list;
383
384 void test_checklist_handler(trapframe_t *tf, void* data)
385 {
386         udelay(1000000);
387         cprintf("down_checklist(%x,%d)\n", the_global_list, core_id());
388         down_checklist(the_global_list);
389 }
390
391 void test_checklists(void)
392 {
393         INIT_CHECKLIST(a_list, MAX_NUM_CPUS);
394         the_global_list = &a_list;
395         printk("Checklist Build, mask size: %d\n", sizeof(a_list.mask.bits));
396         printk("mask\n");
397         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
398         SET_BITMASK_BIT(a_list.mask.bits, 11);
399         printk("Set bit 11\n");
400         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
401
402         CLR_BITMASK(a_list.mask.bits, a_list.mask.size);
403         INIT_CHECKLIST_MASK(a_mask, MAX_NUM_CPUS);
404         FILL_BITMASK(a_mask.bits, num_cpus);
405         //CLR_BITMASK_BIT(a_mask.bits, core_id());
406         //SET_BITMASK_BIT(a_mask.bits, 1);
407         //printk("New mask (1, 17, 25):\n");
408         printk("Created new mask, filled up to num_cpus\n");
409         PRINT_BITMASK(a_mask.bits, a_mask.size);
410         printk("committing new mask\n");
411         commit_checklist_wait(&a_list, &a_mask);
412         printk("Old mask (copied onto):\n");
413         PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
414         //smp_call_function_single(1, test_checklist_handler, 0, 0);
415
416         smp_call_function_all(test_checklist_handler, NULL, 0);
417
418         printk("Waiting on checklist\n");
419         waiton_checklist(&a_list);
420         printk("Done Waiting!\n");
421
422 }
423
424 atomic_t a, b, c;
425
426 #ifdef __IVY__
427 void test_incrementer_handler(trapframe_t *tf, atomic_t *data)
428 #else
429 void test_incrementer_handler(trapframe_t *tf, void *data)
430 #endif
431 {
432         assert(data);
433         atomic_inc(data);
434 }
435
436 void test_null_handler(trapframe_t *tf, void* data)
437 {
438         asm volatile("nop");
439 }
440
441 void test_smp_call_functions(void)
442 {
443         int i;
444         atomic_init(&a, 0);
445         atomic_init(&b, 0);
446         atomic_init(&c, 0);
447         handler_wrapper_t *waiter0 = 0, *waiter1 = 0, *waiter2 = 0, *waiter3 = 0,
448                           *waiter4 = 0, *waiter5 = 0;
449         uint8_t me = core_id();
450         printk("\nCore %d: SMP Call Self (nowait):\n", me);
451         printk("---------------------\n");
452         smp_call_function_self(test_hello_world_handler, NULL, 0);
453         printk("\nCore %d: SMP Call Self (wait):\n", me);
454         printk("---------------------\n");
455         smp_call_function_self(test_hello_world_handler, NULL, &waiter0);
456         smp_call_wait(waiter0);
457         printk("\nCore %d: SMP Call All (nowait):\n", me);
458         printk("---------------------\n");
459         smp_call_function_all(test_hello_world_handler, NULL, 0);
460         printk("\nCore %d: SMP Call All (wait):\n", me);
461         printk("---------------------\n");
462         smp_call_function_all(test_hello_world_handler, NULL, &waiter0);
463         smp_call_wait(waiter0);
464         printk("\nCore %d: SMP Call All-Else Individually, in order (nowait):\n", me);
465         printk("---------------------\n");
466         for(i = 1; i < num_cpus; i++)
467                 smp_call_function_single(i, test_hello_world_handler, NULL, 0);
468         printk("\nCore %d: SMP Call Self (wait):\n", me);
469         printk("---------------------\n");
470         smp_call_function_self(test_hello_world_handler, NULL, &waiter0);
471         smp_call_wait(waiter0);
472         printk("\nCore %d: SMP Call All-Else Individually, in order (wait):\n", me);
473         printk("---------------------\n");
474         for(i = 1; i < num_cpus; i++)
475         {
476                 smp_call_function_single(i, test_hello_world_handler, NULL, &waiter0);
477                 smp_call_wait(waiter0);
478         }
479         printk("\nTesting to see if any IPI-functions are dropped when not waiting:\n");
480         printk("A: %d, B: %d, C: %d (should be 0,0,0)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
481         smp_call_function_all(test_incrementer_handler, &a, 0);
482         smp_call_function_all(test_incrementer_handler, &b, 0);
483         smp_call_function_all(test_incrementer_handler, &c, 0);
484         // if i can clobber a previous IPI, the interleaving might do it
485         smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
486         smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
487         smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
488         smp_call_function_single(4 % num_cpus, test_incrementer_handler, &a, 0);
489         smp_call_function_single(5 % num_cpus, test_incrementer_handler, &b, 0);
490         smp_call_function_single(6 % num_cpus, test_incrementer_handler, &c, 0);
491         smp_call_function_all(test_incrementer_handler, &a, 0);
492         smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
493         smp_call_function_all(test_incrementer_handler, &b, 0);
494         smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
495         smp_call_function_all(test_incrementer_handler, &c, 0);
496         smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
497         // wait, so we're sure the others finish before printing.
498         // without this, we could (and did) get 19,18,19, since the B_inc
499         // handler didn't finish yet
500         smp_call_function_self(test_null_handler, NULL, &waiter0);
501         // need to grab all 5 handlers (max), since the code moves to the next free.
502         smp_call_function_self(test_null_handler, NULL, &waiter1);
503         smp_call_function_self(test_null_handler, NULL, &waiter2);
504         smp_call_function_self(test_null_handler, NULL, &waiter3);
505         smp_call_function_self(test_null_handler, NULL, &waiter4);
506         smp_call_wait(waiter0);
507         smp_call_wait(waiter1);
508         smp_call_wait(waiter2);
509         smp_call_wait(waiter3);
510         smp_call_wait(waiter4);
511         printk("A: %d, B: %d, C: %d (should be 19,19,19)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
512         printk("Attempting to deadlock by smp_calling with an outstanding wait:\n");
513         smp_call_function_self(test_null_handler, NULL, &waiter0);
514         printk("Sent one\n");
515         smp_call_function_self(test_null_handler, NULL, &waiter1);
516         printk("Sent two\n");
517         smp_call_wait(waiter0);
518         printk("Wait one\n");
519         smp_call_wait(waiter1);
520         printk("Wait two\n");
521         printk("\tMade it through!\n");
522         printk("Attempting to deadlock by smp_calling more than are available:\n");
523         printk("\tShould see an Insufficient message and a kernel warning.\n");
524         if (smp_call_function_self(test_null_handler, NULL, &waiter0))
525                 printk("\tInsufficient handlers to call function (0)\n");
526         if (smp_call_function_self(test_null_handler, NULL, &waiter1))
527                 printk("\tInsufficient handlers to call function (1)\n");
528         if (smp_call_function_self(test_null_handler, NULL, &waiter2))
529                 printk("\tInsufficient handlers to call function (2)\n");
530         if (smp_call_function_self(test_null_handler, NULL, &waiter3))
531                 printk("\tInsufficient handlers to call function (3)\n");
532         if (smp_call_function_self(test_null_handler, NULL, &waiter4))
533                 printk("\tInsufficient handlers to call function (4)\n");
534         if (smp_call_function_self(test_null_handler, NULL, &waiter5))
535                 printk("\tInsufficient handlers to call function (5)\n");
536         smp_call_wait(waiter0);
537         smp_call_wait(waiter1);
538         smp_call_wait(waiter2);
539         smp_call_wait(waiter3);
540         smp_call_wait(waiter4);
541         smp_call_wait(waiter5);
542         printk("\tMade it through!\n");
543
544         printk("Done\n");
545 }
546
547 #ifdef __i386__
548 void test_lapic_status_bit(void)
549 {
550         register_interrupt_handler(interrupt_handlers, I_TESTING,
551                                    test_incrementer_handler, &a);
552         #define NUM_IPI 100000
553         atomic_set(&a,0);
554         printk("IPIs received (should be 0): %d\n", a);
555         for(int i = 0; i < NUM_IPI; i++) {
556                 send_ipi(get_hw_coreid(7), I_TESTING);
557                 lapic_wait_to_send();
558         }
559         // need to wait a bit to let those IPIs get there
560         udelay(5000000);
561         printk("IPIs received (should be %d): %d\n", a, NUM_IPI);
562         // hopefully that handler never fires again.  leaving it registered for now.
563 }
564 #endif // __i386__
565
566 /************************************************************/
567 /* ISR Handler Functions */
568
569 void test_hello_world_handler(trapframe_t *tf, void* data)
570 {
571         int trapno;
572         #if defined(__i386__)
573         trapno = tf->tf_trapno;
574         #elif defined(__sparc_v8__)
575         trapno = (tf->tbr >> 4) & 0xFF;
576         #else
577         trapno = 0;
578         #endif
579
580         cprintf("Incoming IRQ, ISR: %d on core %d with tf at 0x%08x\n",
581                 trapno, core_id(), tf);
582 }
583
584 spinlock_t print_info_lock = SPINLOCK_INITIALIZER;
585
586 void test_print_info_handler(trapframe_t *tf, void* data)
587 {
588         uint64_t tsc = read_tsc();
589
590         spin_lock_irqsave(&print_info_lock);
591         cprintf("----------------------------\n");
592         cprintf("This is Core %d\n", core_id());
593         cprintf("Timestamp = %lld\n", tsc);
594 #ifdef __i386__
595         cprintf("Hardware core %d\n", hw_core_id());
596         cprintf("MTRR_DEF_TYPE = 0x%08x\n", read_msr(IA32_MTRR_DEF_TYPE));
597         cprintf("MTRR Phys0 Base = 0x%016llx, Mask = 0x%016llx\n",
598                 read_msr(0x200), read_msr(0x201));
599         cprintf("MTRR Phys1 Base = 0x%016llx, Mask = 0x%016llx\n",
600                 read_msr(0x202), read_msr(0x203));
601         cprintf("MTRR Phys2 Base = 0x%016llx, Mask = 0x%016llx\n",
602                 read_msr(0x204), read_msr(0x205));
603         cprintf("MTRR Phys3 Base = 0x%016llx, Mask = 0x%016llx\n",
604                 read_msr(0x206), read_msr(0x207));
605         cprintf("MTRR Phys4 Base = 0x%016llx, Mask = 0x%016llx\n",
606                 read_msr(0x208), read_msr(0x209));
607         cprintf("MTRR Phys5 Base = 0x%016llx, Mask = 0x%016llx\n",
608                 read_msr(0x20a), read_msr(0x20b));
609         cprintf("MTRR Phys6 Base = 0x%016llx, Mask = 0x%016llx\n",
610                 read_msr(0x20c), read_msr(0x20d));
611         cprintf("MTRR Phys7 Base = 0x%016llx, Mask = 0x%016llx\n",
612                 read_msr(0x20e), read_msr(0x20f));
613 #endif // __i386__
614         cprintf("----------------------------\n");
615         spin_unlock_irqsave(&print_info_lock);
616 }
617
618 void test_barrier_handler(trapframe_t *tf, void* data)
619 {
620         cprintf("Round 1: Core %d\n", core_id());
621         waiton_barrier(&test_cpu_array);
622         waiton_barrier(&test_cpu_array);
623         waiton_barrier(&test_cpu_array);
624         waiton_barrier(&test_cpu_array);
625         waiton_barrier(&test_cpu_array);
626         waiton_barrier(&test_cpu_array);
627         cprintf("Round 2: Core %d\n", core_id());
628         waiton_barrier(&test_cpu_array);
629         cprintf("Round 3: Core %d\n", core_id());
630         // uncomment to see it fucked up
631         //cprintf("Round 4: Core %d\n", core_id());
632 }
633
634 #ifdef __IVY__
635 static void test_waiting_handler(trapframe_t *tf, atomic_t *data)
636 #else
637 static void test_waiting_handler(trapframe_t *tf, void *data)
638 #endif
639 {
640         atomic_dec(data);
641 }
642
643 #ifdef __i386__
644 void test_pit(void)
645 {
646         cprintf("Starting test for PIT now (10s)\n");
647         udelay_pit(10000000);
648         cprintf("End now\n");
649         cprintf("Starting test for TSC (if stable) now (10s)\n");
650         udelay(10000000);
651         cprintf("End now\n");
652
653         cprintf("Starting test for LAPIC (if stable) now (10s)\n");
654         enable_irq();
655         lapic_set_timer(10000000, FALSE);
656
657         atomic_t waiting;
658         atomic_init(&waiting, 1);
659         register_interrupt_handler(interrupt_handlers, I_TESTING,
660                                    test_waiting_handler, &waiting);
661         while(atomic_read(&waiting))
662                 cpu_relax();
663         cprintf("End now\n");
664 }
665
666 void test_circ_buffer(void)
667 {
668         int arr[5] = {0, 1, 2, 3, 4};
669
670         for (int i = 0; i < 5; i++) {
671                 FOR_CIRC_BUFFER(i, 5, j)
672                         printk("Starting with current = %d, each value = %d\n", i, j);
673         }
674         return;
675 }
676
677 void test_km_handler(trapframe_t* tf, uint32_t srcid, void *a0, void *a1,
678                      void *a2)
679 {
680         printk("Received KM on core %d from core %d: arg0= 0x%08x, arg1 = "
681                "0x%08x, arg2 = 0x%08x\n", core_id(), srcid, a0, a1, a2);
682         return;
683 }
684
685 void test_kernel_messages(void)
686 {
687         printk("Testing Kernel Messages\n");
688         /* Testing sending multiples, sending different types, alternating, and
689          * precendence (the immediates should trump the others) */
690         printk("sending 5 IMMED to core 1, sending (#,deadbeef,0)\n");
691         for (int i = 0; i < 5; i++)
692                 send_kernel_message(1, test_km_handler, (void*)i, (void*)0xdeadbeef,
693                                     (void*)0, KMSG_IMMEDIATE);
694         udelay(5000000);
695         printk("sending 5 routine to core 1, sending (#,cafebabe,0)\n");
696         for (int i = 0; i < 5; i++)
697                 send_kernel_message(1, test_km_handler, (void*)i, (void*)0xcafebabe,
698                                     (void*)0, KMSG_ROUTINE);
699         udelay(5000000);
700         printk("sending 10 routine and 3 immediate to core 2\n");
701         for (int i = 0; i < 10; i++)
702                 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xcafebabe,
703                                     (void*)0, KMSG_ROUTINE);
704         for (int i = 0; i < 3; i++)
705                 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xdeadbeef,
706                                     (void*)0, KMSG_IMMEDIATE);
707         udelay(5000000);
708         printk("sending 5 ea alternating to core 2\n");
709         for (int i = 0; i < 5; i++) {
710                 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xdeadbeef,
711                                     (void*)0, KMSG_IMMEDIATE);
712                 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xcafebabe,
713                                     (void*)0, KMSG_ROUTINE);
714         }
715         udelay(5000000);
716         return;
717 }
718 #endif // __i386__
719
720 static void test_single_cache(int iters, size_t size, int align, int flags,
721                               void (*ctor)(void *, size_t),
722                               void (*dtor)(void *, size_t))
723 {
724         struct kmem_cache *test_cache;
725         void *objects[iters];
726         test_cache = kmem_cache_create("test_cache", size, align, flags, ctor, dtor);
727         printk("Testing Kmem Cache:\n");
728         print_kmem_cache(test_cache);
729         for (int i = 0; i < iters; i++) {
730                 objects[i] = kmem_cache_alloc(test_cache, 0);
731                 printk("Buffer %d addr = %p\n", i, objects[i]);
732         }
733         for (int i = 0; i < iters; i++) {
734                 kmem_cache_free(test_cache, objects[i]);
735         }
736         kmem_cache_destroy(test_cache);
737         printk("\n\n\n\n");
738 }
739
740 void a_ctor(void *buf, size_t size)
741 {
742         printk("constructin tests\n");
743 }
744 void a_dtor(void *buf, size_t size)
745 {
746         printk("destructin tests\n");
747 }
748
749 void test_slab(void)
750 {
751         test_single_cache(10, 128, 512, 0, 0, 0);
752         test_single_cache(10, 128, 4, 0, a_ctor, a_dtor);
753         test_single_cache(10, 1024, 16, 0, 0, 0);
754 }
755
756 void test_kmalloc(void)
757 {
758         printk("Testing Kmalloc\n");
759         void *bufs[NUM_KMALLOC_CACHES + 1];     
760         size_t size;
761         for (int i = 0; i < NUM_KMALLOC_CACHES + 1; i++){
762                 size = (KMALLOC_SMALLEST << i) - KMALLOC_OFFSET;
763                 bufs[i] = kmalloc(size, 0);
764                 printk("Size %d, Addr = %p\n", size, bufs[i]);
765         }
766         for (int i = 0; i < NUM_KMALLOC_CACHES; i++) {
767                 printk("Freeing buffer %d\n", i);
768                 kfree(bufs[i]);
769         }
770         printk("Testing a large kmalloc\n");
771         size = (KMALLOC_LARGEST << 2);
772         bufs[0] = kmalloc(size, 0);
773         printk("Size %d, Addr = %p\n", size, bufs[0]);
774         kfree(bufs[0]);
775 }
776
777 static size_t test_hash_fn_col(void *k)
778 {
779         return (size_t)k % 2; // collisions in slots 0 and 1
780 }
781
782 void test_hashtable(void)
783 {
784         struct test {int x; int y;};
785         struct test tstruct[10];
786
787         struct hashtable *h;
788         int k = 5;
789         struct test *v = &tstruct[0];
790
791         h = create_hashtable(32, __generic_hash, __generic_eq);
792         
793         // test inserting one item, then finding it again
794         printk("Tesing one item, insert, search, and removal\n");
795         if(!hashtable_insert(h, (void*)k, v))
796                 printk("Failed to insert to hashtable!\n");
797         v = NULL;
798         if (!(v = hashtable_search(h, (void*)k)))
799                 printk("Failed to find in hashtable!\n");
800         if (v != &tstruct[0])
801                 printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[0]);
802         v = NULL;
803         if (!(v = hashtable_remove(h, (void*)k)))
804                 printk("Failed to remove from hashtable!\n");
805         // shouldn't be able to find it again
806         if ((v = hashtable_search(h, (void*)k)))
807                 printk("Should not have been able to find in hashtable!\n");
808         
809         printk("Tesing a bunch of items, insert, search, and removal\n");
810         for (int i = 0; i < 10; i++) {
811                 k = i; // vary the key, we don't do KEY collisions
812                 if(!hashtable_insert(h, (void*)k, &tstruct[i]))
813                         printk("Failed to insert iter %d to hashtable!\n", i);
814         }
815         // read out the 10 items
816         for (int i = 0; i < 10; i++) {
817                 k = i;
818                 if (!(v = hashtable_search(h, (void*)k)))
819                         printk("Failed to find in hashtable!\n");
820                 if (v != &tstruct[i])
821                         printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[i]);
822         }
823         if (hashtable_count(h) != 10)
824                 printk("Wrong accounting of number of elements!\n");
825         // remove the 10 items
826         for (int i = 0; i < 10; i++) {
827                 k = i;
828                 if (!(v = hashtable_remove(h, (void*)k)))
829                         printk("Failed to remove from hashtable!\n");
830         }
831         // make sure they are all gone
832         for (int i = 0; i < 10; i++) {
833                 k = i;
834                 if ((v = hashtable_search(h, (void*)k)))
835                         printk("Should not have been able to find in hashtable!\n");
836         }
837         if (hashtable_count(h))
838                 printk("Wrong accounting of number of elements!\n");
839         hashtable_destroy(h);
840
841         // same test of a bunch of items, but with collisions.
842         printk("Tesing a bunch of items with collisions, etc.\n");
843         h = create_hashtable(32, test_hash_fn_col, __generic_eq);
844         // insert 10 items
845         for (int i = 0; i < 10; i++) {
846                 k = i; // vary the key, we don't do KEY collisions
847                 if(!hashtable_insert(h, (void*)k, &tstruct[i]))
848                         printk("Failed to insert iter %d to hashtable!\n", i);
849         }
850         // read out the 10 items
851         for (int i = 0; i < 10; i++) {
852                 k = i;
853                 if (!(v = hashtable_search(h, (void*)k)))
854                         printk("Failed to find in hashtable!\n");
855                 if (v != &tstruct[i])
856                         printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[i]);
857         }
858         if (hashtable_count(h) != 10)
859                 printk("Wrong accounting of number of elements!\n");
860         // remove the 10 items
861         for (int i = 0; i < 10; i++) {
862                 k = i;
863                 if (!(v = hashtable_remove(h, (void*)k)))
864                         printk("Failed to remove from hashtable!\n");
865         }
866         // make sure they are all gone
867         for (int i = 0; i < 10; i++) {
868                 k = i;
869                 if ((v = hashtable_search(h, (void*)k)))
870                         printk("Should not have been able to find in hashtable!\n");
871         }
872         if (hashtable_count(h))
873                 printk("Wrong accounting of number of elements!\n");
874         hashtable_destroy(h);
875 }
876
877 /* Ghetto test, only tests one prod or consumer at a time */
878 void test_bcq(void)
879 {
880         struct my_struct {
881                 int x;
882                 int y;
883         };
884         struct my_struct in_struct, out_struct;
885         
886         DEFINE_BCQ_TYPES(test, struct my_struct, 16);
887         struct test_bcq t_bcq;
888         bcq_init(&t_bcq, struct my_struct, 16);
889         
890         in_struct.x = 4;
891         in_struct.y = 5;
892         out_struct.x = 1;
893         out_struct.y = 2;
894         
895         bcq_enqueue(&t_bcq, &in_struct, 16, 5);
896         bcq_dequeue(&t_bcq, &out_struct, 16);
897         printk("out x %d. out y %d\n", out_struct.x, out_struct.y);
898         
899         DEFINE_BCQ_TYPES(my, int, 8);
900         struct my_bcq a_bcq;
901         bcq_init(&a_bcq, int, 8);
902         
903         int y = 2;
904         int output[100];
905         int retval[100];
906         
907         for (int i = 0; i < 15; i++) {
908                 y = i;
909                 retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
910                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
911         }
912         
913         for (int i = 0; i < 15; i++) {
914                 retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
915                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
916         }
917         
918         for (int i = 0; i < 3; i++) {
919                 y = i;
920                 retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
921                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
922         }
923         
924         for (int i = 0; i < 5; i++) {
925                 retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
926                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
927         }
928         
929         for (int i = 0; i < 5; i++) {
930                 y = i;
931                 retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
932                 printk("enqueued: %d, had retval %d \n", y, retval[i]);
933                 retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
934                 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
935         }
936         
937 }
938
939 /* rudimentary tests.  does the basics, create, merge, split, etc.  Feel free to
940  * add more, esp for the error conditions and finding free slots.  This is also
941  * a bit lazy with setting the caller's fields (perm, flags, etc). */
942 void test_vm_regions(void)
943 {
944         #define MAX_VMR_TESTS 10
945         struct proc pr, *p = &pr;       /* too lazy to even create one */
946         int n = 0;
947         TAILQ_INIT(&p->vm_regions);
948
949         struct vmr_summary {
950                 uintptr_t base; 
951                 uintptr_t end; 
952         };
953         int check_vmrs(struct proc *p, struct vmr_summary *results, int len, int n)
954         {
955                 int count = 0;
956                 struct vm_region *vmr;
957                 TAILQ_FOREACH(vmr, &p->vm_regions, vm_link) {
958                         if (count >= len) {
959                                 printk("More vm_regions than expected\n");
960                                 break;
961                         }
962                         if ((vmr->vm_base != results[count].base) ||
963                             (vmr->vm_end != results[count].end)) {
964                                 printk("VM test case %d failed!\n", n);
965                                 print_vmrs(p);
966                                 return -1;
967                         }
968                         count++;
969                 }
970                 return count;
971         }
972         struct vm_region *vmrs[MAX_VMR_TESTS];
973         struct vmr_summary results[MAX_VMR_TESTS];
974
975         memset(results, 0, sizeof(results));
976         /* Make one */
977         vmrs[0] = create_vmr(p, 0x2000, 0x1000);
978         results[0].base = 0x2000;
979         results[0].end = 0x3000;
980         check_vmrs(p, results, 1, n++);
981         /* Grow it */
982         grow_vmr(vmrs[0], 0x4000);
983         results[0].base = 0x2000;
984         results[0].end = 0x4000;
985         check_vmrs(p, results, 1, n++);
986         /* Grow it poorly */
987         if (-1 != grow_vmr(vmrs[0], 0x3000))
988                 printk("Bad grow test failed\n");
989         check_vmrs(p, results, 1, n++);
990         /* Make another right next to it */
991         vmrs[1] = create_vmr(p, 0x4000, 0x1000);
992         results[1].base = 0x4000;
993         results[1].end = 0x5000;
994         check_vmrs(p, results, 2, n++);
995         /* try to grow through it */
996         if (-1 != grow_vmr(vmrs[0], 0x5000))
997                 printk("Bad grow test failed\n");
998         check_vmrs(p, results, 2, n++);
999         /* Merge them */
1000         merge_vmr(vmrs[0], vmrs[1]);
1001         results[0].end = 0x5000;
1002         results[1].base = 0;
1003         results[1].end = 0;
1004         check_vmrs(p, results, 1, n++);
1005         vmrs[1]= create_vmr(p, 0x6000, 0x4000);
1006         results[1].base = 0x6000;
1007         results[1].end = 0xa000;
1008         check_vmrs(p, results, 2, n++);
1009         /* try to merge unmergables (just testing ranges) */
1010         if (-1 != merge_vmr(vmrs[0], vmrs[1]))
1011                 printk("Bad merge test failed\n");
1012         check_vmrs(p, results, 2, n++);
1013         vmrs[2] = split_vmr(vmrs[1], 0x8000);
1014         results[1].end = 0x8000;
1015         results[2].base = 0x8000;
1016         results[2].end = 0xa000;
1017         check_vmrs(p, results, 3, n++);
1018         /* destroy one */
1019         destroy_vmr(vmrs[1]);
1020         results[1].base = 0x8000;
1021         results[1].end = 0xa000;
1022         check_vmrs(p, results, 2, n++);
1023         /* shrink */
1024         shrink_vmr(vmrs[2], 0x9000);
1025         results[1].base = 0x8000;
1026         results[1].end = 0x9000;
1027         check_vmrs(p, results, 2, n++); /* 10 */
1028         if (vmrs[2] != find_vmr(p, 0x8500))
1029                 printk("Failed to find the right vmr!\n");
1030         if (vmrs[2] != find_first_vmr(p, 0x8500))
1031                 printk("Failed to find the right vmr!\n");
1032         if (vmrs[2] != find_first_vmr(p, 0x7500))
1033                 printk("Failed to find the right vmr!\n");
1034         if (find_first_vmr(p, 0x9500))
1035                 printk("Found a vmr when we shouldn't!\n");
1036         /* grow up to another */
1037         grow_vmr(vmrs[0], 0x8000);
1038         results[0].end = 0x8000;
1039         check_vmrs(p, results, 2, n++);
1040         vmrs[0]->vm_prot = 88;
1041         vmrs[2]->vm_prot = 77;
1042         /* should be unmergeable due to perms */
1043         if (-1 != merge_vmr(vmrs[0], vmrs[2]))
1044                 printk("Bad merge test failed\n");
1045         check_vmrs(p, results, 2, n++);
1046         /* should merge now */
1047         vmrs[2]->vm_prot = 88;
1048         merge_vmr(vmrs[0], vmrs[2]);
1049         results[0].end = 0x9000;
1050         check_vmrs(p, results, 1, n++);
1051         destroy_vmr(vmrs[0]);
1052         check_vmrs(p, results, 0, n++);
1053         /* Check the automerge function */
1054         vmrs[0] = create_vmr(p, 0x2000, 0x1000);
1055         vmrs[1] = create_vmr(p, 0x3000, 0x1000);
1056         vmrs[2] = create_vmr(p, 0x4000, 0x1000);
1057         for (int i = 0; i < 3; i++) {
1058                 vmrs[i]->vm_prot = PROT_READ;
1059                 vmrs[i]->vm_flags = 0;
1060                 vmrs[i]->vm_file = 0; /* would like to test this, it's a pain for now */
1061         }
1062         vmrs[0] = merge_me(vmrs[1]);
1063         results[0].base = 0x2000;
1064         results[0].end = 0x5000;
1065         check_vmrs(p, results, 1, n++);
1066         destroy_vmr(vmrs[0]);
1067         check_vmrs(p, results, 0, n++);
1068         /* Check unfixed creation requests */
1069         vmrs[0] = create_vmr(p, 0x0000, 0x1000);
1070         vmrs[1] = create_vmr(p, 0x0000, 0x1000);
1071         vmrs[2] = create_vmr(p, 0x0000, 0x1000);
1072         results[0].base = 0x0000;
1073         results[0].end  = 0x1000;
1074         results[1].base = 0x1000;
1075         results[1].end  = 0x2000;
1076         results[2].base = 0x2000;
1077         results[2].end  = 0x3000;
1078         check_vmrs(p, results, 3, n++);
1079
1080         printk("Finished vm_regions test!\n");
1081 }
1082
1083 void test_radix_tree(void)
1084 {
1085         struct radix_tree real_tree = RADIX_INITIALIZER;
1086         struct radix_tree *tree = &real_tree;
1087         void *retval;
1088
1089         if (radix_insert(tree, 0, (void*)0xdeadbeef))
1090                 printk("Failed to insert at 0!\n");
1091         radix_delete(tree, 0);
1092         if (radix_insert(tree, 0, (void*)0xdeadbeef))
1093                 printk("Failed to re-insert at 0!\n");
1094
1095         if (radix_insert(tree, 3, (void*)0xdeadbeef))
1096                 printk("Failed to insert first!\n");
1097         radix_insert(tree, 4, (void*)0x04040404);
1098         assert((void*)0xdeadbeef == radix_lookup(tree, 3));
1099         for (int i = 5; i < 100; i++)
1100                 if ((retval = radix_lookup(tree, i))) {
1101                         printk("Extra item %08p at slot %d in tree %08p\n", retval, i,
1102                                tree);
1103                         print_radix_tree(tree);
1104                         monitor(0);
1105                 }
1106         if (radix_insert(tree, 65, (void*)0xcafebabe))
1107                 printk("Failed to insert a two-tier!\n");
1108         if (!radix_insert(tree, 4, (void*)0x03030303))
1109                 printk("Should not let us reinsert\n");
1110         if (radix_insert(tree, 4095, (void*)0x4095))
1111                 printk("Failed to insert a two-tier boundary!\n");
1112         if (radix_insert(tree, 4096, (void*)0x4096))
1113                 printk("Failed to insert a three-tier!\n");
1114         //print_radix_tree(tree);
1115         radix_delete(tree, 65);
1116         radix_delete(tree, 3);
1117         radix_delete(tree, 4);
1118         radix_delete(tree, 4095);
1119         radix_delete(tree, 4096);
1120         //print_radix_tree(tree);
1121         printk("Finished radix tree tests!\n");
1122 }
1123
1124 /* Assorted FS tests, which were hanging around in init.c */
1125 void test_random_fs(void)
1126 {
1127         int retval = do_symlink("/dir1/sym", "/bin/hello", S_IRWXU);
1128         if (retval)
1129                 printk("symlink1 creation failed\n");
1130         retval = do_symlink("/symdir", "/dir1/dir1-1", S_IRWXU);
1131         if (retval)
1132                 printk("symlink1 creation failed\n");
1133         retval = do_symlink("/dir1/test.txt", "/dir2/test2.txt", S_IRWXU);
1134         if (retval)
1135                 printk("symlink2 creation failed\n");
1136         retval = do_symlink("/dir1/dir1-1/up", "../../", S_IRWXU);
1137         if (retval)
1138                 printk("symlink3 creation failed\n");
1139         retval = do_symlink("/bin/hello-sym", "hello", S_IRWXU);
1140         if (retval)
1141                 printk("symlink4 creation failed\n");
1142         
1143         struct dentry *dentry;
1144         struct nameidata nd_r = {0}, *nd = &nd_r;
1145         retval = path_lookup("/dir1/sym", 0, nd);
1146         if (retval)
1147                 printk("symlink lookup failed: %d\n", retval);
1148         char *symname = nd->dentry->d_inode->i_op->readlink(nd->dentry);
1149         printk("Pathlookup got %s (sym)\n", nd->dentry->d_name.name);
1150         if (!symname)
1151                 printk("symlink reading failed\n");
1152         else
1153                 printk("Symname: %s (/bin/hello)\n", symname);
1154         path_release(nd);
1155         /* try with follow */
1156         memset(nd, 0, sizeof(struct nameidata));
1157         retval = path_lookup("/dir1/sym", LOOKUP_FOLLOW, nd);
1158         if (retval)
1159                 printk("symlink lookup failed: %d\n", retval);
1160         printk("Pathlookup got %s (hello)\n", nd->dentry->d_name.name);
1161         path_release(nd);
1162         
1163         /* try with a directory */
1164         memset(nd, 0, sizeof(struct nameidata));
1165         retval = path_lookup("/symdir/f1-1.txt", 0, nd);
1166         if (retval)
1167                 printk("symlink lookup failed: %d\n", retval);
1168         printk("Pathlookup got %s (f1-1.txt)\n", nd->dentry->d_name.name);
1169         path_release(nd);
1170         
1171         /* try with a rel path */
1172         printk("Try with a rel path\n");
1173         memset(nd, 0, sizeof(struct nameidata));
1174         retval = path_lookup("/symdir/up/hello.txt", 0, nd);
1175         if (retval)
1176                 printk("symlink lookup failed: %d\n", retval);
1177         printk("Pathlookup got %s (hello.txt)\n", nd->dentry->d_name.name);
1178         path_release(nd);
1179         
1180         printk("Try for an ELOOP\n");
1181         memset(nd, 0, sizeof(struct nameidata));
1182         retval = path_lookup("/symdir/up/symdir/up/symdir/up/symdir/up/hello.txt", 0, nd);
1183         if (retval)
1184                 printk("Symlink lookup failed (it should): %d (-40)\n", retval);
1185         path_release(nd);
1186 }