smp_call wait / backend work
[akaros.git] / kern / testing.c
1 #ifdef __DEPUTY__
2 #pragma nodeputy
3 #endif
4
5 #include <inc/mmu.h>
6 #include <inc/x86.h>
7 #include <inc/stdio.h>
8 #include <inc/assert.h>
9 #include <inc/string.h>
10
11 #include <kern/testing.h>
12 #include <kern/trap.h>
13 #include <kern/apic.h>
14 #include <kern/atomic.h>
15 #include <kern/smp.h>
16
17 void test_ipi_sending(void)
18 {
19         extern isr_t interrupt_handlers[];
20         uint32_t i, amount = SMP_CALL_FUNCTION_TIMEOUT; // should calibrate this
21         int8_t state = 0;
22         register_interrupt_handler(interrupt_handlers, 0xf1, test_hello_world_handler);
23         enable_irqsave(&state);
24         
25         cprintf("\nCORE 0 sending broadcast\n");
26         send_broadcast_ipi(0xf1);
27         for (i = 0; i < amount; i++)
28                 asm volatile("nop;");
29         
30         cprintf("\nCORE 0 sending all others\n");
31         send_all_others_ipi(0xf1);
32         for (i = 0; i < amount; i++)
33                 asm volatile("nop;");
34         
35         cprintf("\nCORE 0 sending self\n");
36         send_self_ipi(0xf1);
37         for (i = 0; i < amount; i++)
38                 asm volatile("nop;");
39         
40         cprintf("\nCORE 0 sending ipi to physical 1\n");
41         send_ipi(0x01, 0, 0xf1);
42         for (i = 0; i < amount; i++)
43                 asm volatile("nop;");
44         
45         cprintf("\nCORE 0 sending ipi to physical 2\n");
46         send_ipi(0x02, 0, 0xf1);
47         for (i = 0; i < amount; i++)
48                 asm volatile("nop;");
49         
50         cprintf("\nCORE 0 sending ipi to physical 3\n");
51         send_ipi(0x03, 0, 0xf1);
52         for (i = 0; i < amount; i++)
53                 asm volatile("nop;");
54         
55         cprintf("\nCORE 0 sending ipi to physical 15\n");
56         send_ipi(0x0f, 0, 0xf1);
57         for (i = 0; i < amount; i++)
58                 asm volatile("nop;");
59         
60         cprintf("\nCORE 0 sending ipi to logical 2\n");
61         send_ipi(0x02, 1, 0xf1);
62         for (i = 0; i < amount; i++)
63                 asm volatile("nop;");
64         
65         cprintf("\nCORE 0 sending ipi to logical 1\n");
66         send_ipi(0x01, 1, 0xf1);
67         for (i = 0; i < amount; i++)
68                 asm volatile("nop;");
69
70         cprintf("\nDone!\n");
71         disable_irqsave(&state);
72 }
73
74 // Note this never returns and will muck with any other timer work
75 void test_pic_reception(void)
76 {
77         register_interrupt_handler(interrupt_handlers, 0x20, test_hello_world_handler);
78         pit_set_timer(100,TIMER_RATEGEN); // totally arbitrary time
79         pic_unmask_irq(0);
80         cprintf("PIC1 Mask = 0x%04x\n", inb(PIC1_DATA));
81         cprintf("PIC2 Mask = 0x%04x\n", inb(PIC2_DATA));
82         unmask_lapic_lvt(LAPIC_LVT_LINT0);
83         cprintf("Core %d's LINT0: 0x%08x\n", lapic_get_id(), read_mmreg32(LAPIC_LVT_LINT0));
84         enable_irq();
85         while(1);
86 }
87
88 void test_print_info(void)
89 {
90         cprintf("\nCORE 0 asking all cores to print info:\n");
91         smp_call_function_all(test_print_info_handler, 0);
92         cprintf("\nDone!\n");
93 }
94         
95
96 extern uint8_t num_cpus;
97 barrier_t test_cpu_array;
98
99 void test_barrier(void)
100 {
101         cprintf("Core 0 initializing barrier\n");
102         init_barrier(&test_cpu_array, num_cpus);
103         cprintf("Core 0 asking all cores to print ids, barrier, rinse, repeat\n");
104         smp_call_function_all(test_barrier_handler, 0);
105 }
106
107 void test_interrupts_irqsave(void)
108 {
109         int8_t state = 0;
110         printd("Testing Nesting Enabling first, turning ints off:\n");
111         disable_irq();
112         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
113         assert((read_eflags() & FL_IF) == 0);
114         printd("Enabling IRQSave\n");
115         enable_irqsave(&state);
116         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
117         assert((read_eflags() & FL_IF) == 0x200);
118         printd("Enabling IRQSave Again\n");
119         enable_irqsave(&state);
120         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
121         assert((read_eflags() & FL_IF) == 0x200);
122         printd("Disabling IRQSave Once\n");
123         disable_irqsave(&state);
124         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
125         assert((read_eflags() & FL_IF) == 0x200);
126         printd("Disabling IRQSave Again\n");
127         disable_irqsave(&state);
128         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
129         assert((read_eflags() & FL_IF) == 0);
130         printd("Done.  Should have been 0, 200, 200, 200, 0\n");        
131
132         printd("Testing Nesting Disabling first, turning ints on:\n");
133         state = 0;
134         enable_irq();
135         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
136         assert((read_eflags() & FL_IF) == 0x200);
137         printd("Disabling IRQSave Once\n");
138         disable_irqsave(&state);
139         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
140         assert((read_eflags() & FL_IF) == 0);
141         printd("Disabling IRQSave Again\n");
142         disable_irqsave(&state);
143         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
144         assert((read_eflags() & FL_IF) == 0);
145         printd("Enabling IRQSave Once\n");
146         enable_irqsave(&state);
147         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
148         assert((read_eflags() & FL_IF) == 0);
149         printd("Enabling IRQSave Again\n");
150         enable_irqsave(&state);
151         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
152         assert((read_eflags() & FL_IF) == 0x200);
153         printd("Done.  Should have been 200, 0, 0, 0, 200 \n"); 
154
155         state = 0;
156         disable_irq();
157         printd("Ints are off, enabling then disabling.\n");
158         enable_irqsave(&state);
159         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
160         assert((read_eflags() & FL_IF) == 0x200);
161         disable_irqsave(&state);
162         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
163         assert((read_eflags() & FL_IF) == 0);
164         printd("Done.  Should have been 200, 0\n");     
165
166         state = 0;
167         enable_irq();
168         printd("Ints are on, enabling then disabling.\n");
169         enable_irqsave(&state);
170         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
171         assert((read_eflags() & FL_IF) == 0x200);
172         disable_irqsave(&state);
173         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
174         assert((read_eflags() & FL_IF) == 0x200);
175         printd("Done.  Should have been 200, 200\n");   
176
177         state = 0;
178         disable_irq();
179         printd("Ints are off, disabling then enabling.\n");
180         disable_irqsave(&state);
181         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
182         assert((read_eflags() & FL_IF) == 0);
183         enable_irqsave(&state);
184         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
185         assert((read_eflags() & FL_IF) == 0);
186         printd("Done.  Should have been 0, 0\n");       
187
188         state = 0;
189         enable_irq();
190         printd("Ints are on, disabling then enabling.\n");
191         disable_irqsave(&state);
192         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
193         assert((read_eflags() & FL_IF) == 0);
194         enable_irqsave(&state);
195         printd("Interrupts are: %x\n", read_eflags() & FL_IF);
196         assert((read_eflags() & FL_IF) == 0x200);
197         printd("Done.  Should have been 0, 200\n");     
198
199         disable_irq();
200         cprintf("Passed enable_irqsave tests\n");
201 }
202
203 void test_bitmasks(void)
204 {
205 #define masksize 67
206         DECL_BITMASK(mask, masksize);
207         printk("size of mask %d\n", sizeof(mask));
208         CLR_BITMASK(mask, masksize);
209         PRINT_MASK(mask, masksize);
210         printk("cleared\n");
211         SET_BITMASK_BIT(mask, 0);
212         SET_BITMASK_BIT(mask, 11);
213         SET_BITMASK_BIT(mask, 17);
214         SET_BITMASK_BIT(mask, masksize-1);
215         printk("bits set\n");
216         PRINT_MASK(mask, masksize);
217         DECL_BITMASK(mask2, masksize);
218         COPY_BITMASK(mask2, mask, masksize);
219         printk("copy of original mask, should be the same as the prev\n");
220         PRINT_MASK(mask2, masksize);
221         CLR_BITMASK_BIT(mask, 11);
222         printk("11 cleared\n");
223         PRINT_MASK(mask, masksize);
224         printk("bit 17 is %d (should be 1)\n", GET_BITMASK_BIT(mask, 17));
225         printk("bit 11 is %d (should be 0)\n", GET_BITMASK_BIT(mask, 11));
226         FILL_BITMASK(mask, masksize);
227         PRINT_MASK(mask, masksize);
228         printk("should be all 1's, except for a few at the end\n");
229         printk("Is Clear?: %d (should be 0)\n", BITMASK_IS_CLEAR(mask,masksize));
230         CLR_BITMASK(mask, masksize);
231         PRINT_MASK(mask, masksize);
232         printk("Is Clear?: %d (should be 1)\n", BITMASK_IS_CLEAR(mask,masksize));
233         printk("should be cleared\n");
234 }
235
236 checklist_t* the_global_list;
237
238 void test_checklist_handler(trapframe_t *tf)
239 {
240         for (int i = 0; i < SMP_BOOT_TIMEOUT; i++);
241         for (int i = 0; i < SMP_BOOT_TIMEOUT; i++);
242         down_checklist(the_global_list);
243 }
244
245 extern uint8_t num_cpus;
246
247 void test_checklists(void)
248 {
249         INIT_CHECKLIST(a_list, MAX_NUM_CPUS);
250         the_global_list = &a_list;
251         printk("Checklist Build, mask size: %d\n", sizeof(a_list.mask.bits));
252         printk("mask\n");
253         PRINT_MASK(a_list.mask.bits, a_list.mask.size);
254         SET_BITMASK_BIT(a_list.mask.bits, 11);
255         printk("Set bit 11\n");
256         PRINT_MASK(a_list.mask.bits, a_list.mask.size);
257
258         CLR_BITMASK(a_list.mask.bits, a_list.mask.size);
259         INIT_CHECKLIST_MASK(a_mask, MAX_NUM_CPUS);
260         FILL_BITMASK(a_mask.bits, num_cpus);
261         //CLR_BITMASK_BIT(a_mask.bits, lapic_get_id());
262         //SET_BITMASK_BIT(a_mask.bits, 1);
263         //printk("New mask (1, 17, 25):\n");
264         PRINT_MASK(a_mask.bits, a_mask.size);
265         printk("committing new mask\n");
266         commit_checklist_wait(&a_list, &a_mask);
267         printk("Old mask (copied onto) (1, 17, 25):\n");
268         PRINT_MASK(a_list.mask.bits, a_list.mask.size);
269         //smp_call_function_single(1, test_checklist_handler, 0);       
270         smp_call_function_all(test_checklist_handler, 0);       
271
272         printk("Waiting on checklist\n");
273         waiton_checklist(&a_list);      
274         printk("Done Waiting!\n");
275
276 }
277
278 volatile uint32_t a = 0, b = 0, c = 0;
279
280 void test_A_incrementer_handler(struct Trapframe *tf)
281 {
282         atomic_inc(&a);
283 }
284
285 void test_B_incrementer_handler(struct Trapframe *tf)
286 {
287         atomic_inc(&b);
288 }
289
290 void test_C_incrementer_handler(struct Trapframe *tf)
291 {
292         atomic_inc(&c);
293 }
294
295 void test_null_handler(struct Trapframe *tf)
296 {
297         asm volatile("nop");
298 }
299
300 void test_smp_call_functions(void)
301 {
302         handler_wrapper_t *waiter, *waiter2;
303         uint8_t me = lapic_get_id();
304         printk("\nCore %d: SMP Call Self (nowait):\n", me);
305         printk("---------------------\n");
306         smp_call_function_self(test_hello_world_handler, 0);
307         printk("\nCore %d: SMP Call Self (wait):\n", me);
308         printk("---------------------\n");
309         smp_call_function_self(test_hello_world_handler, &waiter);
310         smp_call_wait(waiter);
311         printk("\nCore %d: SMP Call All (nowait):\n", me);
312         printk("---------------------\n");
313         smp_call_function_all(test_hello_world_handler, 0);
314         printk("\nCore %d: SMP Call All (wait):\n", me);
315         printk("---------------------\n");
316         smp_call_function_all(test_hello_world_handler, &waiter);
317         smp_call_wait(waiter);
318         printk("\nCore %d: SMP Call All-Else Individually, in order (nowait):\n", me);
319         printk("---------------------\n");
320         smp_call_function_single(1, test_hello_world_handler, 0);
321         smp_call_function_single(2, test_hello_world_handler, 0);
322         smp_call_function_single(3, test_hello_world_handler, 0);
323         smp_call_function_single(4, test_hello_world_handler, 0);
324         smp_call_function_single(5, test_hello_world_handler, 0);
325         smp_call_function_single(6, test_hello_world_handler, 0);
326         smp_call_function_single(7, test_hello_world_handler, 0);
327         printk("\nCore %d: SMP Call Self (wait):\n", me);
328         printk("---------------------\n");
329         smp_call_function_self(test_hello_world_handler, &waiter);
330         smp_call_wait(waiter);
331         printk("\nCore %d: SMP Call All-Else Individually, in order (wait):\n", me);
332         printk("---------------------\n");
333         smp_call_function_single(1, test_hello_world_handler, &waiter);
334         smp_call_wait(waiter);
335         smp_call_function_single(2, test_hello_world_handler, &waiter);
336         smp_call_wait(waiter);
337         smp_call_function_single(3, test_hello_world_handler, &waiter);
338         smp_call_wait(waiter);
339         smp_call_function_single(4, test_hello_world_handler, &waiter);
340         smp_call_wait(waiter);
341         smp_call_function_single(5, test_hello_world_handler, &waiter);
342         smp_call_wait(waiter);
343         smp_call_function_single(6, test_hello_world_handler, &waiter);
344         smp_call_wait(waiter);
345         smp_call_function_single(7, test_hello_world_handler, &waiter);
346         smp_call_wait(waiter);
347         printk("\nTesting to see if any IPI-functions are dropped when not waiting:\n");
348         printk("A: %d, B: %d, C: %d (should be 0,0,0)\n", a, b, c);
349         smp_call_function_all(test_A_incrementer_handler, 0);
350         smp_call_function_all(test_B_incrementer_handler, 0);
351         smp_call_function_all(test_C_incrementer_handler, 0);
352         // if i can clobber a previous IPI, the interleaving might do it
353         smp_call_function_single(1, test_A_incrementer_handler, 0);
354         smp_call_function_single(2, test_B_incrementer_handler, 0);
355         smp_call_function_single(3, test_C_incrementer_handler, 0);
356         smp_call_function_single(4, test_A_incrementer_handler, 0);
357         smp_call_function_single(5, test_B_incrementer_handler, 0);
358         smp_call_function_single(6, test_C_incrementer_handler, 0);
359         smp_call_function_all(test_A_incrementer_handler, 0);
360         smp_call_function_single(3, test_C_incrementer_handler, 0);
361         smp_call_function_all(test_B_incrementer_handler, 0);
362         smp_call_function_single(1, test_A_incrementer_handler, 0);
363         smp_call_function_all(test_C_incrementer_handler, 0);
364         smp_call_function_single(2, test_B_incrementer_handler, 0);
365         // wait, so we're sure the others finish before printing.
366         // without this, we could (and did) get 19,18,19, since the B_inc
367         // handler didn't finish yet
368         smp_call_function_self(test_null_handler, &waiter);
369         smp_call_wait(waiter);
370         printk("A: %d, B: %d, C: %d (should be 19,19,19)\n", a, b, c);
371         printk("Attempting to deadlock by smp_calling on a current wait: ");
372         smp_call_function_self(test_null_handler, &waiter);
373         smp_call_function_self(test_null_handler, &waiter2);
374         smp_call_wait(waiter);
375         smp_call_wait(waiter2);
376         printk("Made it through!\n");
377         printk("Done\n");
378 }
379
380 /* Helper Functions */
381
382 void test_hello_world_handler(trapframe_t *tf)
383 {
384         cprintf("Incoming IRQ, ISR: %d on core %d with tf at 0x%08x\n", 
385                 tf->tf_trapno, lapic_get_id(), tf);
386 }
387
388 uint32_t print_info_lock = 0;
389
390 void test_print_info_handler(trapframe_t *tf)
391 {
392         spin_lock_irqsave(&print_info_lock);
393         cprintf("----------------------------\n");
394         cprintf("This is Core %d\n", lapic_get_id());
395         cprintf("MTRR_DEF_TYPE = 0x%08x\n", read_msr(IA32_MTRR_DEF_TYPE));
396         cprintf("MTRR Phys0 Base = 0x%016llx, Mask = 0x%016llx\n",
397                 read_msr(0x200), read_msr(0x201));
398         cprintf("MTRR Phys1 Base = 0x%016llx, Mask = 0x%016llx\n",
399                 read_msr(0x202), read_msr(0x203));
400         cprintf("MTRR Phys2 Base = 0x%016llx, Mask = 0x%016llx\n",
401                 read_msr(0x204), read_msr(0x205));
402         cprintf("MTRR Phys3 Base = 0x%016llx, Mask = 0x%016llx\n",
403                 read_msr(0x206), read_msr(0x207));
404         cprintf("MTRR Phys4 Base = 0x%016llx, Mask = 0x%016llx\n",
405                 read_msr(0x208), read_msr(0x209));
406         cprintf("MTRR Phys5 Base = 0x%016llx, Mask = 0x%016llx\n",
407                 read_msr(0x20a), read_msr(0x20b));
408         cprintf("MTRR Phys6 Base = 0x%016llx, Mask = 0x%016llx\n",
409                 read_msr(0x20c), read_msr(0x20d));
410         cprintf("MTRR Phys7 Base = 0x%016llx, Mask = 0x%016llx\n",
411                 read_msr(0x20e), read_msr(0x20f));
412         cprintf("----------------------------\n");
413         spin_unlock_irqsave(&print_info_lock);
414 }
415
416 void test_barrier_handler(trapframe_t *tf)
417 {
418         cprintf("Round 1: Core %d\n", lapic_get_id());
419         waiton_barrier(&test_cpu_array);
420         waiton_barrier(&test_cpu_array);
421         waiton_barrier(&test_cpu_array);
422         waiton_barrier(&test_cpu_array);
423         waiton_barrier(&test_cpu_array);
424         waiton_barrier(&test_cpu_array);
425         cprintf("Round 2: Core %d\n", lapic_get_id());
426         waiton_barrier(&test_cpu_array);
427         cprintf("Round 3: Core %d\n", lapic_get_id());
428         // uncomment to see it fucked up
429         //cprintf("Round 4: Core %d\n", lapic_get_id());
430 }
431
432 void test_pit(void)
433 {
434         cprintf("starting now \n");
435         udelay(10000000);
436         cprintf("end now \n");
437         cprintf("starting now \n");
438         udelay(10000000);
439         cprintf("end now \n");
440 }