Implemented Kernel Post-boot testing.
[akaros.git] / kern / src / manager.c
1 /*
2  * Copyright (c) 2009 The Regents of the University of California
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  */
6
7
8 #ifdef __SHARC__
9 #pragma nosharc
10 #endif
11
12 #include <ros/common.h>
13 #include <smp.h>
14 #include <arch/init.h>
15 #include <mm.h>
16 #include <elf.h>
17 #include <frontend.h>
18
19 #include <kmalloc.h>
20 #include <assert.h>
21 #include <manager.h>
22 #include <process.h>
23 #include <schedule.h>
24 #include <syscall.h>
25 #include <test_infrastructure.h>
26 #include <kfs.h>
27 #include <stdio.h>
28 #include <time.h>
29 #include <monitor.h>
30 #include <colored_caches.h>
31 #include <string.h>
32 #include <pmap.h>
33 #include <arch/console.h>
34 #include <time.h>
35 #include <ros/arch/membar.h>
36
37 char *kern_test_msg; // Variable defined in test_infrastructure.h.
38
39
40 void postboot_kernel_tests(void)
41 {
42         printk("\nRunning %d postboot Kernel tests:\n", 
43                    num_pb_kernel_tests);
44
45         // Do not remove this line, it is being used by Jenkins.
46         printk("<-- BEGIN_KERNEL_POSTBOOT_TESTS -->\n");
47         for (int i=0; i<num_pb_kernel_tests; i++) {
48                 struct pb_kernel_test *test = &pb_kernel_tests[i];
49                 if (test->enabled) {
50                         uint64_t start = read_tsc();
51                         bool result = test->func();
52                         uint64_t end = read_tsc();
53                         uint64_t et_us = tsc2usec(end - start) % 1000000;
54                         uint64_t et_s = tsc2sec(end - start);
55
56                         if (result) {
57                                 printk("\tPASSED   [%s](%llu.%06llus)\n", test->name, et_s, 
58                                        et_us);
59                         } else {
60                                 printk("\tFAILED   [%s](%llu.%06llus)  %s\n", test->name, et_s, 
61                                        et_us, kern_test_msg);
62                                 kfree(kern_test_msg);
63                         }
64                 } else {
65                         printk("\tDISABLED [%s]\n", test->name);
66                 }
67         }
68         // Do not remove this line, it is being used by Jenkins.
69         printk("<-- END_KERNEL_POSTBOOT_TESTS -->\n");
70 }
71
72 /*
73  * Currently, if you leave this function by way of proc_run (process_workqueue
74  * that proc_runs), you will never come back to where you left off, and the
75  * function will start from the top.  Hence the hack 'progress'.
76  */
77 void manager(void)
78 {
79         #ifndef DEVELOPER_NAME
80                 #define DEVELOPER_NAME brho
81         #endif
82
83         // LoL
84         #define PASTE(s1,s2) s1 ## s2
85         #define MANAGER_FUNC(dev) PASTE(manager_,dev)
86
87         // Run Kernel post boot tests (from tests_postboot_kernel.c)
88         #ifdef CONFIG_POSTBOOT_KERNEL_TESTING
89                 postboot_kernel_tests();
90         #endif
91
92         void MANAGER_FUNC(DEVELOPER_NAME)(void);
93         MANAGER_FUNC(DEVELOPER_NAME)();
94 }
95
96 char *p_argv[] = {0, 0, 0};
97 char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
98 /* Helper macro for quickly running a process.  Pass it a string, *file, and a
99  * *proc. */
100 #define quick_proc_run(x, p, f)                                                  \
101         (f) = do_file_open((x), 0, 0);                                               \
102         assert((f));                                                                 \
103         p_argv[0] = file_name((f));                                                  \
104         (p) = proc_create((f), p_argv, p_envp);                                      \
105         kref_put(&(f)->f_kref);                                                      \
106         spin_lock(&(p)->proc_lock);                                                  \
107         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
108         spin_unlock(&(p)->proc_lock);                                                \
109         proc_run_s((p));                                                             \
110         proc_decref((p));
111
112 #define quick_proc_create(x, p, f)                                               \
113         (f) = do_file_open((x), 0, 0);                                               \
114         assert((f));                                                                 \
115         p_argv[0] = file_name((f));                                                  \
116         (p) = proc_create((f), p_argv, p_envp);                                      \
117         kref_put(&(f)->f_kref);                                                      \
118         spin_lock(&(p)->proc_lock);                                                  \
119         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
120         spin_unlock(&(p)->proc_lock);
121
122 #define quick_proc_color_run(x, p, c, f)                                         \
123         (f) = do_file_open((x), 0, 0);                                               \
124         assert((f));                                                                 \
125         p_argv[0] = file_name((f));                                                  \
126         (p) = proc_create((f), p_argv, p_envp);                                      \
127         kref_put(&(f)->f_kref);                                                      \
128         spin_lock(&(p)->proc_lock);                                                  \
129         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
130         spin_unlock(&(p)->proc_lock);                                                \
131         p->cache_colors_map = cache_colors_map_alloc();                              \
132         for (int i = 0; i < (c); i++)                                                \
133                 cache_color_alloc(llc_cache, p->cache_colors_map);                       \
134         proc_run_s((p));                                                             \
135         proc_decref((p));
136
137 #define quick_proc_color_create(x, p, c, f)                                      \
138         (f) = do_file_open((x), 0, 0);                                               \
139         assert((f));                                                                 \
140         p_argv[0] = file_name((f));                                                  \
141         (p) = proc_create((f), p_argv, p_envp);                                      \
142         kref_put(&(f)->f_kref);                                                      \
143         spin_lock(&(p)->proc_lock);                                                  \
144         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
145         spin_unlock(&(p)->proc_lock);                                                \
146         p->cache_colors_map = cache_colors_map_alloc();                              \
147         for (int i = 0; i < (c); i++)                                                \
148                 cache_color_alloc(llc_cache, p->cache_colors_map);
149
150 void manager_brho(void)
151 {
152         static bool first = TRUE;
153         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
154
155         if (first) {    
156                 printk("*** IRQs must be enabled for input emergency codes ***\n");
157                 #ifdef CONFIG_X86
158                 printk("*** Hit ctrl-g to enter the monitor. ***\n");
159                 printk("*** Hit ctrl-q to force-enter the monitor. ***\n");
160                 printk("*** Hit ctrl-b for a backtrace of core 0 ***\n");
161                 #else
162                 printk("*** Hit ctrl-g to enter the monitor. ***\n");
163                 #warning "***** ctrl-g untested on riscv, check k/a/r/trap.c *****"
164                 #endif
165                 first = FALSE;
166         }
167         /* just idle, and deal with things via interrupts.  or via face. */
168         smp_idle();
169         /* whatever we do in the manager, keep in mind that we need to not do
170          * anything too soon (like make processes), since we'll drop in here during
171          * boot if the boot sequence required any I/O (like EXT2), and we need to
172          * PRKM() */
173         assert(0);
174
175 #if 0 /* ancient tests below: (keeping around til we ditch the manager) */
176         // for testing taking cores, check in case 1 for usage
177         uint32_t corelist[MAX_NUM_CPUS];
178         uint32_t num = 3;
179         struct file *temp_f;
180         static struct proc *p;
181
182         static uint8_t RACY progress = 0;       /* this will wrap around. */
183         switch (progress++) {
184                 case 0:
185                         printk("Top of the manager to ya!\n");
186                         /* 124 is half of the available boxboro colors (with the kernel
187                          * getting 8) */
188                         //quick_proc_color_run("msr_dumb_while", p, 124, temp_f);
189                         quick_proc_run("/bin/hello", p, temp_f);
190                         #if 0
191                         // this is how you can transition to a parallel process manually
192                         // make sure you don't proc run first
193                         __proc_set_state(p, PROC_RUNNING_S);
194                         __proc_set_state(p, PROC_RUNNABLE_M);
195                         p->resources[RES_CORES].amt_wanted = 5;
196                         spin_unlock(&p->proc_lock);
197                         core_request(p);
198                         panic("This is okay");
199                         #endif
200                         break;
201                 case 1:
202                         #if 0
203                         udelay(10000000);
204                         // this is a ghetto way to test restarting an _M
205                                 printk("\nattempting to ghetto preempt...\n");
206                                 spin_lock(&p->proc_lock);
207                                 proc_take_allcores(p, __death);
208                                 __proc_set_state(p, PROC_RUNNABLE_M);
209                                 spin_unlock(&p->proc_lock);
210                                 udelay(5000000);
211                                 printk("\nattempting to restart...\n");
212                                 core_request(p); // proc still wants the cores
213                         panic("This is okay");
214                         // this tests taking some cores, and later killing an _M
215                                 printk("taking 3 cores from p\n");
216                                 for (int i = 0; i < num; i++)
217                                         corelist[i] = 7-i; // 7, 6, and 5
218                                 spin_lock(&p->proc_lock);
219                                 proc_take_cores(p, corelist, &num, __death);
220                                 spin_unlock(&p->proc_lock);
221                                 udelay(5000000);
222                                 printk("Killing p\n");
223                                 enable_irq();
224                                 proc_destroy(p);
225                                 printk("Killed p\n");
226                         panic("This is okay");
227
228                         envs[0] = kfs_proc_create(kfs_lookup_path("roslib_hello"));
229                         __proc_set_state(envs[0], PROC_RUNNABLE_S);
230                         proc_run(envs[0]);
231                         warn("DEPRECATED");
232                         break;
233                         #endif
234                 case 2:
235                         /*
236                         test_smp_call_functions();
237                         test_checklists();
238                         test_barrier();
239                         test_print_info();
240                         test_lapic_status_bit();
241                         test_ipi_sending();
242                         test_pit();
243                         */
244                 default:
245                         printd("Manager Progress: %d\n", progress);
246                         // delay if you want to test rescheduling an MCP that yielded
247                         //udelay(15000000);
248                         run_scheduler();
249         }
250         panic("If you see me, then you probably screwed up");
251         monitor(0);
252
253         /*
254         printk("Servicing syscalls from Core 0:\n\n");
255         while (1) {
256                 process_generic_syscalls(&envs[0], 1);
257                 cpu_relax();
258         }
259         */
260         return;
261 #endif
262 }
263
264 void manager_klueska()
265 {
266         static struct proc *envs[256];
267         static volatile uint8_t progress = 0;
268
269         if (progress == 0) {
270                 progress++;
271                 panic("what do you want to do?");
272                 //envs[0] = kfs_proc_create(kfs_lookup_path("fillmeup"));
273                 __proc_set_state(envs[0], PROC_RUNNABLE_S);
274                 proc_run_s(envs[0]);
275                 warn("DEPRECATED");
276         }
277         run_scheduler();
278
279         panic("DON'T PANIC");
280 }
281
282 void manager_waterman()
283 {
284         static bool first = true;
285         if (first)
286                 mon_bb(0, 0, 0);
287         smp_idle();
288         assert(0);
289 }
290
291 void manager_yuzhu()
292 {
293         
294         static uint8_t RACY progress = 0;
295         static struct proc *p;
296
297         // for testing taking cores, check in case 1 for usage
298         uint32_t corelist[MAX_NUM_CPUS];
299         uint32_t num = 3;
300
301         //create_server(init_num_cores, loop);
302
303         monitor(0);
304
305         // quick_proc_run("hello", p);
306
307 }