8 #include <arch/bitmask.h>
11 #include <ros/memlayout.h>
12 #include <ros/common.h>
21 #include <arch/trap.h>
26 #include <multiboot.h>
28 #include <page_alloc.h>
32 #include <hashtable.h>
34 #define l1 (available_caches.l1)
35 #define l2 (available_caches.l2)
36 #define l3 (available_caches.l3)
40 void test_ipi_sending(void)
42 extern handler_t (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
45 register_interrupt_handler(interrupt_handlers, I_TESTING,
46 test_hello_world_handler, NULL);
47 enable_irqsave(&state);
48 cprintf("\nCORE 0 sending broadcast\n");
49 send_broadcast_ipi(I_TESTING);
51 cprintf("\nCORE 0 sending all others\n");
52 send_all_others_ipi(I_TESTING);
54 cprintf("\nCORE 0 sending self\n");
55 send_self_ipi(I_TESTING);
57 cprintf("\nCORE 0 sending ipi to physical 1\n");
58 send_ipi(get_hw_coreid(0x01), I_TESTING);
60 cprintf("\nCORE 0 sending ipi to physical 2\n");
61 send_ipi(get_hw_coreid(0x02), I_TESTING);
63 cprintf("\nCORE 0 sending ipi to physical 3\n");
64 send_ipi(get_hw_coreid(0x03), I_TESTING);
66 cprintf("\nCORE 0 sending ipi to physical 15\n");
67 send_ipi(get_hw_coreid(0x0f), I_TESTING);
69 cprintf("\nCORE 0 sending ipi to logical 2\n");
70 send_group_ipi(0x02, I_TESTING);
72 cprintf("\nCORE 0 sending ipi to logical 1\n");
73 send_group_ipi(0x01, I_TESTING);
76 disable_irqsave(&state);
79 // Note this never returns and will muck with any other timer work
80 void test_pic_reception(void)
82 register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
83 pit_set_timer(100,TIMER_RATEGEN); // totally arbitrary time
85 cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
86 cprintf("PIC2 Mask = 0x%04x\n", inb(PIC2_DATA));
87 unmask_lapic_lvt(LAPIC_LVT_LINT0);
88 cprintf("Core %d's LINT0: 0x%08x\n", core_id(), read_mmreg32(LAPIC_LVT_LINT0));
93 void test_ioapic_pit_reroute(void)
95 register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler, NULL);
96 ioapic_route_irq(0, 3);
98 cprintf("Starting pit on core 3....\n");
100 pit_set_timer(0xFFFE,TIMER_RATEGEN); // totally arbitrary time
103 ioapic_unroute_irq(0);
105 cprintf("Masked pit. Waiting before return...\n");
112 void test_print_info(void)
114 cprintf("\nCORE 0 asking all cores to print info:\n");
115 smp_call_function_all(test_print_info_handler, NULL, 0);
116 cprintf("\nDone!\n");
119 void test_page_coloring(void)
122 //Print the different cache properties of our machine
123 print_cache_properties("L1", l1);
125 print_cache_properties("L2", l2);
127 print_cache_properties("L3", l3);
130 //Print some stats about our memory
131 cprintf("Max Address: %llu\n", MAX_VADDR);
132 cprintf("Num Pages: %u\n", npages);
134 //Declare a local variable for allocating pages
137 cprintf("Contents of the page free list:\n");
138 for(int i=0; i<llc_cache->num_colors; i++) {
139 cprintf(" COLOR %d:\n", i);
140 LIST_FOREACH(page, &colored_page_free_list[i], pg_link) {
141 cprintf(" Page: %d\n", page2ppn(page));
145 //Run through and allocate all pages through l1_page_alloc
146 cprintf("Allocating from L1 page colors:\n");
147 for(int i=0; i<get_cache_num_page_colors(l1); i++) {
148 cprintf(" COLOR %d:\n", i);
149 while(colored_page_alloc(l1, &page, i) != -ENOMEM)
150 cprintf(" Page: %d\n", page2ppn(page));
153 //Put all the pages back by reinitializing
156 //Run through and allocate all pages through l2_page_alloc
157 cprintf("Allocating from L2 page colors:\n");
158 for(int i=0; i<get_cache_num_page_colors(l2); i++) {
159 cprintf(" COLOR %d:\n", i);
160 while(colored_page_alloc(l2, &page, i) != -ENOMEM)
161 cprintf(" Page: %d\n", page2ppn(page));
164 //Put all the pages back by reinitializing
167 //Run through and allocate all pages through l3_page_alloc
168 cprintf("Allocating from L3 page colors:\n");
169 for(int i=0; i<get_cache_num_page_colors(l3); i++) {
170 cprintf(" COLOR %d:\n", i);
171 while(colored_page_alloc(l3, &page, i) != -ENOMEM)
172 cprintf(" Page: %d\n", page2ppn(page));
175 //Put all the pages back by reinitializing
178 //Run through and allocate all pages through page_alloc
179 cprintf("Allocating from global allocator:\n");
180 while(upage_alloc(&page) != -ENOMEM)
181 cprintf(" Page: %d\n", page2ppn(page));
183 if(colored_page_alloc(l2, &page, 0) != -ENOMEM)
184 cprintf("Should not get here, all pages should already be gone!\n");
185 cprintf("All pages gone for sure...\n");
187 //Now lets put a few pages back using page_free..
188 cprintf("Reinserting pages via page_free and reallocating them...\n");
189 page_free(&pages[0]);
190 page_free(&pages[15]);
191 page_free(&pages[7]);
192 page_free(&pages[6]);
193 page_free(&pages[4]);
195 while(upage_alloc(&page) != -ENOMEM)
196 cprintf("Page: %d\n", page2ppn(page));
202 void test_color_alloc() {
203 size_t checkpoint = 0;
204 uint8_t* colors_map = kmalloc(BYTES_FOR_BITMASK(llc_cache->num_colors), 0);
205 cache_color_alloc(l2, colors_map);
206 cache_color_alloc(l3, colors_map);
207 cache_color_alloc(l3, colors_map);
208 cache_color_alloc(l2, colors_map);
209 cache_color_free(llc_cache, colors_map);
210 cache_color_free(llc_cache, 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(l2, colors_map);
226 cache_color_free(llc_cache, colors_map);
227 cache_color_free(llc_cache, colors_map);
230 printk("L1 free colors, tot colors: %d\n", l1->num_colors);
231 PRINT_BITMASK(l1->free_colors_map, l1->num_colors);
232 printk("L2 free colors, tot colors: %d\n", l2->num_colors);
233 PRINT_BITMASK(l2->free_colors_map, l2->num_colors);
234 printk("L3 free colors, tot colors: %d\n", l3->num_colors);
235 PRINT_BITMASK(l3->free_colors_map, l3->num_colors);
236 printk("Process allocated colors\n");
237 PRINT_BITMASK(colors_map, llc_cache->num_colors);
238 printk("test_color_alloc() complete!\n");
241 barrier_t test_cpu_array;
243 void test_barrier(void)
245 cprintf("Core 0 initializing barrier\n");
246 init_barrier(&test_cpu_array, num_cpus);
247 cprintf("Core 0 asking all cores to print ids, barrier, rinse, repeat\n");
248 smp_call_function_all(test_barrier_handler, NULL, 0);
251 void test_interrupts_irqsave(void)
254 printd("Testing Nesting Enabling first, turning ints off:\n");
256 printd("Interrupts are: %x\n", irq_is_enabled());
257 assert(!irq_is_enabled());
258 printd("Enabling IRQSave\n");
259 enable_irqsave(&state);
260 printd("Interrupts are: %x\n", irq_is_enabled());
261 assert(irq_is_enabled());
262 printd("Enabling IRQSave Again\n");
263 enable_irqsave(&state);
264 printd("Interrupts are: %x\n", irq_is_enabled());
265 assert(irq_is_enabled());
266 printd("Disabling IRQSave Once\n");
267 disable_irqsave(&state);
268 printd("Interrupts are: %x\n", irq_is_enabled());
269 assert(irq_is_enabled());
270 printd("Disabling IRQSave Again\n");
271 disable_irqsave(&state);
272 printd("Interrupts are: %x\n", irq_is_enabled());
273 assert(!irq_is_enabled());
274 printd("Done. Should have been 0, 200, 200, 200, 0\n");
276 printd("Testing Nesting Disabling first, turning ints on:\n");
279 printd("Interrupts are: %x\n", irq_is_enabled());
280 assert(irq_is_enabled());
281 printd("Disabling IRQSave Once\n");
282 disable_irqsave(&state);
283 printd("Interrupts are: %x\n", irq_is_enabled());
284 assert(!irq_is_enabled());
285 printd("Disabling IRQSave Again\n");
286 disable_irqsave(&state);
287 printd("Interrupts are: %x\n", irq_is_enabled());
288 assert(!irq_is_enabled());
289 printd("Enabling IRQSave Once\n");
290 enable_irqsave(&state);
291 printd("Interrupts are: %x\n", irq_is_enabled());
292 assert(!irq_is_enabled());
293 printd("Enabling IRQSave Again\n");
294 enable_irqsave(&state);
295 printd("Interrupts are: %x\n", irq_is_enabled());
296 assert(irq_is_enabled());
297 printd("Done. Should have been 200, 0, 0, 0, 200 \n");
301 printd("Ints are off, enabling then disabling.\n");
302 enable_irqsave(&state);
303 printd("Interrupts are: %x\n", irq_is_enabled());
304 assert(irq_is_enabled());
305 disable_irqsave(&state);
306 printd("Interrupts are: %x\n", irq_is_enabled());
307 assert(!irq_is_enabled());
308 printd("Done. Should have been 200, 0\n");
312 printd("Ints are on, enabling then disabling.\n");
313 enable_irqsave(&state);
314 printd("Interrupts are: %x\n", irq_is_enabled());
315 assert(irq_is_enabled());
316 disable_irqsave(&state);
317 printd("Interrupts are: %x\n", irq_is_enabled());
318 assert(irq_is_enabled());
319 printd("Done. Should have been 200, 200\n");
323 printd("Ints are off, disabling then enabling.\n");
324 disable_irqsave(&state);
325 printd("Interrupts are: %x\n", irq_is_enabled());
326 assert(!irq_is_enabled());
327 enable_irqsave(&state);
328 printd("Interrupts are: %x\n", irq_is_enabled());
329 assert(!irq_is_enabled());
330 printd("Done. Should have been 0, 0\n");
334 printd("Ints are on, disabling then enabling.\n");
335 disable_irqsave(&state);
336 printd("Interrupts are: %x\n", irq_is_enabled());
337 assert(!irq_is_enabled());
338 enable_irqsave(&state);
339 printd("Interrupts are: %x\n", irq_is_enabled());
340 assert(irq_is_enabled());
341 printd("Done. Should have been 0, 200\n");
344 cprintf("Passed enable_irqsave tests\n");
347 void test_bitmasks(void)
350 DECL_BITMASK(mask, masksize);
351 printk("size of mask %d\n", sizeof(mask));
352 CLR_BITMASK(mask, masksize);
353 PRINT_BITMASK(mask, masksize);
355 SET_BITMASK_BIT(mask, 0);
356 SET_BITMASK_BIT(mask, 11);
357 SET_BITMASK_BIT(mask, 17);
358 SET_BITMASK_BIT(mask, masksize-1);
359 printk("bits set\n");
360 PRINT_BITMASK(mask, masksize);
361 DECL_BITMASK(mask2, masksize);
362 COPY_BITMASK(mask2, mask, masksize);
363 printk("copy of original mask, should be the same as the prev\n");
364 PRINT_BITMASK(mask2, masksize);
365 CLR_BITMASK_BIT(mask, 11);
366 printk("11 cleared\n");
367 PRINT_BITMASK(mask, masksize);
368 printk("bit 17 is %d (should be 1)\n", GET_BITMASK_BIT(mask, 17));
369 printk("bit 11 is %d (should be 0)\n", GET_BITMASK_BIT(mask, 11));
370 FILL_BITMASK(mask, masksize);
371 PRINT_BITMASK(mask, masksize);
372 printk("should be all 1's, except for a few at the end\n");
373 printk("Is Clear?: %d (should be 0)\n", BITMASK_IS_CLEAR(mask,masksize));
374 CLR_BITMASK(mask, masksize);
375 PRINT_BITMASK(mask, masksize);
376 printk("Is Clear?: %d (should be 1)\n", BITMASK_IS_CLEAR(mask,masksize));
377 printk("should be cleared\n");
380 checklist_t *RO the_global_list;
382 void test_checklist_handler(trapframe_t *tf, void* data)
385 cprintf("down_checklist(%x,%d)\n", the_global_list, core_id());
386 down_checklist(the_global_list);
389 void test_checklists(void)
391 INIT_CHECKLIST(a_list, MAX_NUM_CPUS);
392 the_global_list = &a_list;
393 printk("Checklist Build, mask size: %d\n", sizeof(a_list.mask.bits));
395 PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
396 SET_BITMASK_BIT(a_list.mask.bits, 11);
397 printk("Set bit 11\n");
398 PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
400 CLR_BITMASK(a_list.mask.bits, a_list.mask.size);
401 INIT_CHECKLIST_MASK(a_mask, MAX_NUM_CPUS);
402 FILL_BITMASK(a_mask.bits, num_cpus);
403 //CLR_BITMASK_BIT(a_mask.bits, core_id());
404 //SET_BITMASK_BIT(a_mask.bits, 1);
405 //printk("New mask (1, 17, 25):\n");
406 printk("Created new mask, filled up to num_cpus\n");
407 PRINT_BITMASK(a_mask.bits, a_mask.size);
408 printk("committing new mask\n");
409 commit_checklist_wait(&a_list, &a_mask);
410 printk("Old mask (copied onto):\n");
411 PRINT_BITMASK(a_list.mask.bits, a_list.mask.size);
412 //smp_call_function_single(1, test_checklist_handler, 0, 0);
414 smp_call_function_all(test_checklist_handler, NULL, 0);
416 printk("Waiting on checklist\n");
417 waiton_checklist(&a_list);
418 printk("Done Waiting!\n");
425 void test_incrementer_handler(trapframe_t *tf, atomic_t *data)
427 void test_incrementer_handler(trapframe_t *tf, void *data)
434 void test_null_handler(trapframe_t *tf, void* data)
439 void test_smp_call_functions(void)
445 handler_wrapper_t *waiter0 = 0, *waiter1 = 0, *waiter2 = 0, *waiter3 = 0,
446 *waiter4 = 0, *waiter5 = 0;
447 uint8_t me = core_id();
448 printk("\nCore %d: SMP Call Self (nowait):\n", me);
449 printk("---------------------\n");
450 smp_call_function_self(test_hello_world_handler, NULL, 0);
451 printk("\nCore %d: SMP Call Self (wait):\n", me);
452 printk("---------------------\n");
453 smp_call_function_self(test_hello_world_handler, NULL, &waiter0);
454 smp_call_wait(waiter0);
455 printk("\nCore %d: SMP Call All (nowait):\n", me);
456 printk("---------------------\n");
457 smp_call_function_all(test_hello_world_handler, NULL, 0);
458 printk("\nCore %d: SMP Call All (wait):\n", me);
459 printk("---------------------\n");
460 smp_call_function_all(test_hello_world_handler, NULL, &waiter0);
461 smp_call_wait(waiter0);
462 printk("\nCore %d: SMP Call All-Else Individually, in order (nowait):\n", me);
463 printk("---------------------\n");
464 for(i = 1; i < num_cpus; i++)
465 smp_call_function_single(i, 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-Else Individually, in order (wait):\n", me);
471 printk("---------------------\n");
472 for(i = 1; i < num_cpus; i++)
474 smp_call_function_single(i, test_hello_world_handler, NULL, &waiter0);
475 smp_call_wait(waiter0);
477 printk("\nTesting to see if any IPI-functions are dropped when not waiting:\n");
478 printk("A: %d, B: %d, C: %d (should be 0,0,0)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
479 smp_call_function_all(test_incrementer_handler, &a, 0);
480 smp_call_function_all(test_incrementer_handler, &b, 0);
481 smp_call_function_all(test_incrementer_handler, &c, 0);
482 // if i can clobber a previous IPI, the interleaving might do it
483 smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
484 smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
485 smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
486 smp_call_function_single(4 % num_cpus, test_incrementer_handler, &a, 0);
487 smp_call_function_single(5 % num_cpus, test_incrementer_handler, &b, 0);
488 smp_call_function_single(6 % num_cpus, test_incrementer_handler, &c, 0);
489 smp_call_function_all(test_incrementer_handler, &a, 0);
490 smp_call_function_single(3 % num_cpus, test_incrementer_handler, &c, 0);
491 smp_call_function_all(test_incrementer_handler, &b, 0);
492 smp_call_function_single(1 % num_cpus, test_incrementer_handler, &a, 0);
493 smp_call_function_all(test_incrementer_handler, &c, 0);
494 smp_call_function_single(2 % num_cpus, test_incrementer_handler, &b, 0);
495 // wait, so we're sure the others finish before printing.
496 // without this, we could (and did) get 19,18,19, since the B_inc
497 // handler didn't finish yet
498 smp_call_function_self(test_null_handler, NULL, &waiter0);
499 // need to grab all 5 handlers (max), since the code moves to the next free.
500 smp_call_function_self(test_null_handler, NULL, &waiter1);
501 smp_call_function_self(test_null_handler, NULL, &waiter2);
502 smp_call_function_self(test_null_handler, NULL, &waiter3);
503 smp_call_function_self(test_null_handler, NULL, &waiter4);
504 smp_call_wait(waiter0);
505 smp_call_wait(waiter1);
506 smp_call_wait(waiter2);
507 smp_call_wait(waiter3);
508 smp_call_wait(waiter4);
509 printk("A: %d, B: %d, C: %d (should be 19,19,19)\n", atomic_read(&a), atomic_read(&b), atomic_read(&c));
510 printk("Attempting to deadlock by smp_calling with an outstanding wait:\n");
511 smp_call_function_self(test_null_handler, NULL, &waiter0);
512 printk("Sent one\n");
513 smp_call_function_self(test_null_handler, NULL, &waiter1);
514 printk("Sent two\n");
515 smp_call_wait(waiter0);
516 printk("Wait one\n");
517 smp_call_wait(waiter1);
518 printk("Wait two\n");
519 printk("\tMade it through!\n");
520 printk("Attempting to deadlock by smp_calling more than are available:\n");
521 printk("\tShould see an Insufficient message and a kernel warning.\n");
522 if (smp_call_function_self(test_null_handler, NULL, &waiter0))
523 printk("\tInsufficient handlers to call function (0)\n");
524 if (smp_call_function_self(test_null_handler, NULL, &waiter1))
525 printk("\tInsufficient handlers to call function (1)\n");
526 if (smp_call_function_self(test_null_handler, NULL, &waiter2))
527 printk("\tInsufficient handlers to call function (2)\n");
528 if (smp_call_function_self(test_null_handler, NULL, &waiter3))
529 printk("\tInsufficient handlers to call function (3)\n");
530 if (smp_call_function_self(test_null_handler, NULL, &waiter4))
531 printk("\tInsufficient handlers to call function (4)\n");
532 if (smp_call_function_self(test_null_handler, NULL, &waiter5))
533 printk("\tInsufficient handlers to call function (5)\n");
534 smp_call_wait(waiter0);
535 smp_call_wait(waiter1);
536 smp_call_wait(waiter2);
537 smp_call_wait(waiter3);
538 smp_call_wait(waiter4);
539 smp_call_wait(waiter5);
540 printk("\tMade it through!\n");
546 void test_lapic_status_bit(void)
548 register_interrupt_handler(interrupt_handlers, I_TESTING,
549 test_incrementer_handler, &a);
550 #define NUM_IPI 100000
552 printk("IPIs received (should be 0): %d\n", a);
553 for(int i = 0; i < NUM_IPI; i++) {
554 send_ipi(get_hw_coreid(7), I_TESTING);
555 lapic_wait_to_send();
557 // need to wait a bit to let those IPIs get there
559 printk("IPIs received (should be %d): %d\n", a, NUM_IPI);
560 // hopefully that handler never fires again. leaving it registered for now.
564 /************************************************************/
565 /* ISR Handler Functions */
567 void test_hello_world_handler(trapframe_t *tf, void* data)
570 #if defined(__i386__)
571 trapno = tf->tf_trapno;
572 #elif defined(__sparc_v8__)
573 trapno = (tf->tbr >> 4) & 0xFF;
578 cprintf("Incoming IRQ, ISR: %d on core %d with tf at 0x%08x\n",
579 trapno, core_id(), tf);
582 spinlock_t print_info_lock = SPINLOCK_INITIALIZER;
584 void test_print_info_handler(trapframe_t *tf, void* data)
586 uint64_t tsc = read_tsc();
588 spin_lock_irqsave(&print_info_lock);
589 cprintf("----------------------------\n");
590 cprintf("This is Core %d\n", core_id());
591 cprintf("Timestamp = %lld\n", tsc);
593 cprintf("Hardware core %d\n", hw_core_id());
594 cprintf("MTRR_DEF_TYPE = 0x%08x\n", read_msr(IA32_MTRR_DEF_TYPE));
595 cprintf("MTRR Phys0 Base = 0x%016llx, Mask = 0x%016llx\n",
596 read_msr(0x200), read_msr(0x201));
597 cprintf("MTRR Phys1 Base = 0x%016llx, Mask = 0x%016llx\n",
598 read_msr(0x202), read_msr(0x203));
599 cprintf("MTRR Phys2 Base = 0x%016llx, Mask = 0x%016llx\n",
600 read_msr(0x204), read_msr(0x205));
601 cprintf("MTRR Phys3 Base = 0x%016llx, Mask = 0x%016llx\n",
602 read_msr(0x206), read_msr(0x207));
603 cprintf("MTRR Phys4 Base = 0x%016llx, Mask = 0x%016llx\n",
604 read_msr(0x208), read_msr(0x209));
605 cprintf("MTRR Phys5 Base = 0x%016llx, Mask = 0x%016llx\n",
606 read_msr(0x20a), read_msr(0x20b));
607 cprintf("MTRR Phys6 Base = 0x%016llx, Mask = 0x%016llx\n",
608 read_msr(0x20c), read_msr(0x20d));
609 cprintf("MTRR Phys7 Base = 0x%016llx, Mask = 0x%016llx\n",
610 read_msr(0x20e), read_msr(0x20f));
612 cprintf("----------------------------\n");
613 spin_unlock_irqsave(&print_info_lock);
616 void test_barrier_handler(trapframe_t *tf, void* data)
618 cprintf("Round 1: Core %d\n", core_id());
619 waiton_barrier(&test_cpu_array);
620 waiton_barrier(&test_cpu_array);
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 cprintf("Round 2: Core %d\n", core_id());
626 waiton_barrier(&test_cpu_array);
627 cprintf("Round 3: Core %d\n", core_id());
628 // uncomment to see it fucked up
629 //cprintf("Round 4: Core %d\n", core_id());
633 static void test_waiting_handler(trapframe_t *tf, atomic_t *data)
635 static void test_waiting_handler(trapframe_t *tf, void *data)
644 cprintf("Starting test for PIT now (10s)\n");
645 udelay_pit(10000000);
646 cprintf("End now\n");
647 cprintf("Starting test for TSC (if stable) now (10s)\n");
649 cprintf("End now\n");
651 cprintf("Starting test for LAPIC (if stable) now (10s)\n");
653 lapic_set_timer(10000000, FALSE);
656 atomic_init(&waiting, 1);
657 register_interrupt_handler(interrupt_handlers, I_TESTING,
658 test_waiting_handler, &waiting);
659 while(atomic_read(&waiting))
661 cprintf("End now\n");
664 void test_circ_buffer(void)
666 int arr[5] = {0, 1, 2, 3, 4};
668 for (int i = 0; i < 5; i++) {
669 FOR_CIRC_BUFFER(i, 5, j)
670 printk("Starting with current = %d, each value = %d\n", i, j);
675 void test_km_handler(trapframe_t* tf, uint32_t srcid, void *a0, void *a1,
678 printk("Received KM on core %d from core %d: arg0= 0x%08x, arg1 = "
679 "0x%08x, arg2 = 0x%08x\n", core_id(), srcid, a0, a1, a2);
683 void test_kernel_messages(void)
685 printk("Testing Kernel Messages\n");
686 /* Testing sending multiples, sending different types, alternating, and
687 * precendence (the immediates should trump the others) */
688 printk("sending 5 IMMED to core 1, sending (#,deadbeef,0)\n");
689 for (int i = 0; i < 5; i++)
690 send_kernel_message(1, test_km_handler, (void*)i, (void*)0xdeadbeef,
691 (void*)0, KMSG_IMMEDIATE);
693 printk("sending 5 routine to core 1, sending (#,cafebabe,0)\n");
694 for (int i = 0; i < 5; i++)
695 send_kernel_message(1, test_km_handler, (void*)i, (void*)0xcafebabe,
696 (void*)0, KMSG_ROUTINE);
698 printk("sending 10 routine and 3 immediate to core 2\n");
699 for (int i = 0; i < 10; i++)
700 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xcafebabe,
701 (void*)0, KMSG_ROUTINE);
702 for (int i = 0; i < 3; i++)
703 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xdeadbeef,
704 (void*)0, KMSG_IMMEDIATE);
706 printk("sending 5 ea alternating to core 2\n");
707 for (int i = 0; i < 5; i++) {
708 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xdeadbeef,
709 (void*)0, KMSG_IMMEDIATE);
710 send_kernel_message(2, test_km_handler, (void*)i, (void*)0xcafebabe,
711 (void*)0, KMSG_ROUTINE);
718 static void test_single_cache(int iters, size_t size, int align, int flags,
719 void (*ctor)(void *, size_t),
720 void (*dtor)(void *, size_t))
722 struct kmem_cache *test_cache;
723 void *objects[iters];
724 test_cache = kmem_cache_create("test_cache", size, align, flags, ctor, dtor);
725 printk("Testing Kmem Cache:\n");
726 print_kmem_cache(test_cache);
727 for (int i = 0; i < iters; i++) {
728 objects[i] = kmem_cache_alloc(test_cache, 0);
729 printk("Buffer %d addr = %p\n", i, objects[i]);
731 for (int i = 0; i < iters; i++) {
732 kmem_cache_free(test_cache, objects[i]);
734 kmem_cache_destroy(test_cache);
738 void a_ctor(void *buf, size_t size)
740 printk("constructin tests\n");
742 void a_dtor(void *buf, size_t size)
744 printk("destructin tests\n");
749 test_single_cache(10, 128, 512, 0, 0, 0);
750 test_single_cache(10, 128, 4, 0, a_ctor, a_dtor);
751 test_single_cache(10, 1024, 16, 0, 0, 0);
754 void test_kmalloc(void)
756 printk("Testing Kmalloc\n");
757 void *bufs[NUM_KMALLOC_CACHES + 1];
759 for (int i = 0; i < NUM_KMALLOC_CACHES + 1; i++){
760 size = (KMALLOC_SMALLEST << i) - KMALLOC_OFFSET;
761 bufs[i] = kmalloc(size, 0);
762 printk("Size %d, Addr = %p\n", size, bufs[i]);
764 for (int i = 0; i < NUM_KMALLOC_CACHES; i++) {
765 printk("Freeing buffer %d\n", i);
768 printk("Testing a large kmalloc\n");
769 size = (KMALLOC_LARGEST << 2);
770 bufs[0] = kmalloc(size, 0);
771 printk("Size %d, Addr = %p\n", size, bufs[0]);
775 static size_t test_hash_fn_col(void *k)
777 return (size_t)k % 2; // collisions in slots 0 and 1
780 void test_hashtable(void)
782 struct test {int x; int y;};
783 struct test tstruct[10];
787 struct test *v = &tstruct[0];
789 h = create_hashtable(32, __generic_hash, __generic_eq);
791 // test inserting one item, then finding it again
792 printk("Tesing one item, insert, search, and removal\n");
793 if(!hashtable_insert(h, (void*)k, v))
794 printk("Failed to insert to hashtable!\n");
796 if (!(v = hashtable_search(h, (void*)k)))
797 printk("Failed to find in hashtable!\n");
798 if (v != &tstruct[0])
799 printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[0]);
801 if (!(v = hashtable_remove(h, (void*)k)))
802 printk("Failed to remove from hashtable!\n");
803 // shouldn't be able to find it again
804 if ((v = hashtable_search(h, (void*)k)))
805 printk("Should not have been able to find in hashtable!\n");
807 printk("Tesing a bunch of items, insert, search, and removal\n");
808 for (int i = 0; i < 10; i++) {
809 k = i; // vary the key, we don't do KEY collisions
810 if(!hashtable_insert(h, (void*)k, &tstruct[i]))
811 printk("Failed to insert iter %d to hashtable!\n", i);
813 // read out the 10 items
814 for (int i = 0; i < 10; i++) {
816 if (!(v = hashtable_search(h, (void*)k)))
817 printk("Failed to find in hashtable!\n");
818 if (v != &tstruct[i])
819 printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[i]);
821 if (hashtable_count(h) != 10)
822 printk("Wrong accounting of number of elements!\n");
823 // remove the 10 items
824 for (int i = 0; i < 10; i++) {
826 if (!(v = hashtable_remove(h, (void*)k)))
827 printk("Failed to remove from hashtable!\n");
829 // make sure they are all gone
830 for (int i = 0; i < 10; i++) {
832 if ((v = hashtable_search(h, (void*)k)))
833 printk("Should not have been able to find in hashtable!\n");
835 if (hashtable_count(h))
836 printk("Wrong accounting of number of elements!\n");
837 hashtable_destroy(h);
839 // same test of a bunch of items, but with collisions.
840 printk("Tesing a bunch of items with collisions, etc.\n");
841 h = create_hashtable(32, test_hash_fn_col, __generic_eq);
843 for (int i = 0; i < 10; i++) {
844 k = i; // vary the key, we don't do KEY collisions
845 if(!hashtable_insert(h, (void*)k, &tstruct[i]))
846 printk("Failed to insert iter %d to hashtable!\n", i);
848 // read out the 10 items
849 for (int i = 0; i < 10; i++) {
851 if (!(v = hashtable_search(h, (void*)k)))
852 printk("Failed to find in hashtable!\n");
853 if (v != &tstruct[i])
854 printk("Got the wrong item! (got %p, wanted %p)\n", v, &tstruct[i]);
856 if (hashtable_count(h) != 10)
857 printk("Wrong accounting of number of elements!\n");
858 // remove the 10 items
859 for (int i = 0; i < 10; i++) {
861 if (!(v = hashtable_remove(h, (void*)k)))
862 printk("Failed to remove from hashtable!\n");
864 // make sure they are all gone
865 for (int i = 0; i < 10; i++) {
867 if ((v = hashtable_search(h, (void*)k)))
868 printk("Should not have been able to find in hashtable!\n");
870 if (hashtable_count(h))
871 printk("Wrong accounting of number of elements!\n");
872 hashtable_destroy(h);
875 /* Ghetto test, only tests one prod or consumer at a time */
882 struct my_struct in_struct, out_struct;
884 DEFINE_BCQ_TYPES(test, struct my_struct, 16);
885 struct test_bcq t_bcq;
886 bcq_init(&t_bcq, struct my_struct, 16);
893 bcq_enqueue(&t_bcq, &in_struct, 16, 5);
894 bcq_dequeue(&t_bcq, &out_struct, 16);
895 printk("out x %d. out y %d\n", out_struct.x, out_struct.y);
897 DEFINE_BCQ_TYPES(my, int, 8);
899 bcq_init(&a_bcq, int, 8);
905 for (int i = 0; i < 15; i++) {
907 retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
908 printk("enqueued: %d, had retval %d \n", y, retval[i]);
911 for (int i = 0; i < 15; i++) {
912 retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
913 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
916 for (int i = 0; i < 3; i++) {
918 retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
919 printk("enqueued: %d, had retval %d \n", y, retval[i]);
922 for (int i = 0; i < 5; i++) {
923 retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
924 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
927 for (int i = 0; i < 5; i++) {
929 retval[i] = bcq_enqueue(&a_bcq, &y, 8, 10);
930 printk("enqueued: %d, had retval %d \n", y, retval[i]);
931 retval[i] = bcq_dequeue(&a_bcq, &output[i], 8);
932 printk("dequeued: %d with retval %d\n", output[i], retval[i]);
937 /* rudimentary tests. does the basics, create, merge, split, etc. Feel free to
938 * add more, esp for the error conditions and finding free slots. This is also
939 * a bit lazy with setting the caller's fields (perm, flags, etc). */
940 void test_vm_regions(void)
942 #define MAX_VMR_TESTS 10
943 struct proc pr, *p = ≺ /* too lazy to even create one */
945 TAILQ_INIT(&p->vm_regions);
951 int check_vmrs(struct proc *p, struct vmr_summary *results, int len, int n)
954 struct vm_region *vmr;
955 TAILQ_FOREACH(vmr, &p->vm_regions, vm_link) {
957 printk("More vm_regions than expected\n");
960 if ((vmr->vm_base != results[count].base) ||
961 (vmr->vm_end != results[count].end)) {
962 printk("VM test case %d failed!\n", n);
970 struct vm_region *vmrs[MAX_VMR_TESTS];
971 struct vmr_summary results[MAX_VMR_TESTS];
973 memset(results, 0, sizeof(results));
975 vmrs[0] = create_vmr(p, 0x2000, 0x1000);
976 results[0].base = 0x2000;
977 results[0].end = 0x3000;
978 check_vmrs(p, results, 1, n++);
980 grow_vmr(vmrs[0], 0x4000);
981 results[0].base = 0x2000;
982 results[0].end = 0x4000;
983 check_vmrs(p, results, 1, n++);
985 if (-1 != grow_vmr(vmrs[0], 0x3000))
986 printk("Bad grow test failed\n");
987 check_vmrs(p, results, 1, n++);
988 /* Make another right next to it */
989 vmrs[1] = create_vmr(p, 0x4000, 0x1000);
990 results[1].base = 0x4000;
991 results[1].end = 0x5000;
992 check_vmrs(p, results, 2, n++);
993 /* try to grow through it */
994 if (-1 != grow_vmr(vmrs[0], 0x5000))
995 printk("Bad grow test failed\n");
996 check_vmrs(p, results, 2, n++);
998 merge_vmr(vmrs[0], vmrs[1]);
999 results[0].end = 0x5000;
1000 results[1].base = 0;
1002 check_vmrs(p, results, 1, n++);
1003 vmrs[1]= create_vmr(p, 0x6000, 0x4000);
1004 results[1].base = 0x6000;
1005 results[1].end = 0xa000;
1006 check_vmrs(p, results, 2, n++);
1007 /* try to merge unmergables (just testing ranges) */
1008 if (-1 != merge_vmr(vmrs[0], vmrs[1]))
1009 printk("Bad merge test failed\n");
1010 check_vmrs(p, results, 2, n++);
1011 vmrs[2] = split_vmr(vmrs[1], 0x8000);
1012 results[1].end = 0x8000;
1013 results[2].base = 0x8000;
1014 results[2].end = 0xa000;
1015 check_vmrs(p, results, 3, n++);
1017 destroy_vmr(vmrs[1]);
1018 results[1].base = 0x8000;
1019 results[1].end = 0xa000;
1020 check_vmrs(p, results, 2, n++);
1022 shrink_vmr(vmrs[2], 0x9000);
1023 results[1].base = 0x8000;
1024 results[1].end = 0x9000;
1025 check_vmrs(p, results, 2, n++); /* 10 */
1026 if (vmrs[2] != find_vmr(p, 0x8500))
1027 printk("Failed to find the right vmr!\n");
1028 if (vmrs[2] != find_first_vmr(p, 0x8500))
1029 printk("Failed to find the right vmr!\n");
1030 if (vmrs[2] != find_first_vmr(p, 0x7500))
1031 printk("Failed to find the right vmr!\n");
1032 if (find_first_vmr(p, 0x9500))
1033 printk("Found a vmr when we shouldn't!\n");
1034 /* grow up to another */
1035 grow_vmr(vmrs[0], 0x8000);
1036 results[0].end = 0x8000;
1037 check_vmrs(p, results, 2, n++);
1038 vmrs[0]->vm_prot = 88;
1039 vmrs[2]->vm_prot = 77;
1040 /* should be unmergeable due to perms */
1041 if (-1 != merge_vmr(vmrs[0], vmrs[2]))
1042 printk("Bad merge test failed\n");
1043 check_vmrs(p, results, 2, n++);
1044 /* should merge now */
1045 vmrs[2]->vm_prot = 88;
1046 merge_vmr(vmrs[0], vmrs[2]);
1047 results[0].end = 0x9000;
1048 check_vmrs(p, results, 1, n++);
1049 destroy_vmr(vmrs[0]);
1050 check_vmrs(p, results, 0, n++);
1051 /* Check the automerge function */
1052 vmrs[0] = create_vmr(p, 0x2000, 0x1000);
1053 vmrs[1] = create_vmr(p, 0x3000, 0x1000);
1054 vmrs[2] = create_vmr(p, 0x4000, 0x1000);
1055 for (int i = 0; i < 3; i++) {
1056 vmrs[i]->vm_prot = PROT_READ;
1057 vmrs[i]->vm_flags = 0;
1058 vmrs[i]->vm_file = 0; /* would like to test this, it's a pain for now */
1060 vmrs[0] = merge_me(vmrs[1]);
1061 results[0].base = 0x2000;
1062 results[0].end = 0x5000;
1063 check_vmrs(p, results, 1, n++);
1064 destroy_vmr(vmrs[0]);
1065 check_vmrs(p, results, 0, n++);
1066 /* Check unfixed creation requests */
1067 vmrs[0] = create_vmr(p, 0x0000, 0x1000);
1068 vmrs[1] = create_vmr(p, 0x0000, 0x1000);
1069 vmrs[2] = create_vmr(p, 0x0000, 0x1000);
1070 results[0].base = 0x0000;
1071 results[0].end = 0x1000;
1072 results[1].base = 0x1000;
1073 results[1].end = 0x2000;
1074 results[2].base = 0x2000;
1075 results[2].end = 0x3000;
1076 check_vmrs(p, results, 3, n++);
1078 printk("Finished vm_regions test!\n");