Added automatic userspace test launching capability to AKAROS.
[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         // Run userspace tests (from config specified path).
92         if (strlen(CONFIG_USERSPACE_TESTING) != 0)
93         {
94                 printk("'%s' is %d chars long", CONFIG_USERSPACE_TESTING,
95                            strlen(STRINGIFY(CONFIG_USERSPACE_TESTING)));
96                 char *usp_args[] = {"bin_run", "ash", CONFIG_USERSPACE_TESTING};
97                 mon_bin_run(3, usp_args, NULL);
98         } 
99
100         void MANAGER_FUNC(DEVELOPER_NAME)(void);
101         MANAGER_FUNC(DEVELOPER_NAME)();
102 }
103
104 char *p_argv[] = {0, 0, 0};
105 char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
106 /* Helper macro for quickly running a process.  Pass it a string, *file, and a
107  * *proc. */
108 #define quick_proc_run(x, p, f)                                                  \
109         (f) = do_file_open((x), 0, 0);                                               \
110         assert((f));                                                                 \
111         p_argv[0] = file_name((f));                                                  \
112         (p) = proc_create((f), p_argv, p_envp);                                      \
113         kref_put(&(f)->f_kref);                                                      \
114         spin_lock(&(p)->proc_lock);                                                  \
115         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
116         spin_unlock(&(p)->proc_lock);                                                \
117         proc_run_s((p));                                                             \
118         proc_decref((p));
119
120 #define quick_proc_create(x, p, f)                                               \
121         (f) = do_file_open((x), 0, 0);                                               \
122         assert((f));                                                                 \
123         p_argv[0] = file_name((f));                                                  \
124         (p) = proc_create((f), p_argv, p_envp);                                      \
125         kref_put(&(f)->f_kref);                                                      \
126         spin_lock(&(p)->proc_lock);                                                  \
127         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
128         spin_unlock(&(p)->proc_lock);
129
130 #define quick_proc_color_run(x, p, c, f)                                         \
131         (f) = do_file_open((x), 0, 0);                                               \
132         assert((f));                                                                 \
133         p_argv[0] = file_name((f));                                                  \
134         (p) = proc_create((f), p_argv, p_envp);                                      \
135         kref_put(&(f)->f_kref);                                                      \
136         spin_lock(&(p)->proc_lock);                                                  \
137         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
138         spin_unlock(&(p)->proc_lock);                                                \
139         p->cache_colors_map = cache_colors_map_alloc();                              \
140         for (int i = 0; i < (c); i++)                                                \
141                 cache_color_alloc(llc_cache, p->cache_colors_map);                       \
142         proc_run_s((p));                                                             \
143         proc_decref((p));
144
145 #define quick_proc_color_create(x, p, c, f)                                      \
146         (f) = do_file_open((x), 0, 0);                                               \
147         assert((f));                                                                 \
148         p_argv[0] = file_name((f));                                                  \
149         (p) = proc_create((f), p_argv, p_envp);                                      \
150         kref_put(&(f)->f_kref);                                                      \
151         spin_lock(&(p)->proc_lock);                                                  \
152         __proc_set_state((p), PROC_RUNNABLE_S);                                      \
153         spin_unlock(&(p)->proc_lock);                                                \
154         p->cache_colors_map = cache_colors_map_alloc();                              \
155         for (int i = 0; i < (c); i++)                                                \
156                 cache_color_alloc(llc_cache, p->cache_colors_map);
157
158 void manager_brho(void)
159 {
160         static bool first = TRUE;
161         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
162
163         if (first) {    
164                 printk("*** IRQs must be enabled for input emergency codes ***\n");
165                 #ifdef CONFIG_X86
166                 printk("*** Hit ctrl-g to enter the monitor. ***\n");
167                 printk("*** Hit ctrl-q to force-enter the monitor. ***\n");
168                 printk("*** Hit ctrl-b for a backtrace of core 0 ***\n");
169                 #else
170                 printk("*** Hit ctrl-g to enter the monitor. ***\n");
171                 #warning "***** ctrl-g untested on riscv, check k/a/r/trap.c *****"
172                 #endif
173                 first = FALSE;
174         }
175         /* just idle, and deal with things via interrupts.  or via face. */
176         smp_idle();
177         /* whatever we do in the manager, keep in mind that we need to not do
178          * anything too soon (like make processes), since we'll drop in here during
179          * boot if the boot sequence required any I/O (like EXT2), and we need to
180          * PRKM() */
181         assert(0);
182
183 #if 0 /* ancient tests below: (keeping around til we ditch the manager) */
184         // for testing taking cores, check in case 1 for usage
185         uint32_t corelist[MAX_NUM_CPUS];
186         uint32_t num = 3;
187         struct file *temp_f;
188         static struct proc *p;
189
190         static uint8_t RACY progress = 0;       /* this will wrap around. */
191         switch (progress++) {
192                 case 0:
193                         printk("Top of the manager to ya!\n");
194                         /* 124 is half of the available boxboro colors (with the kernel
195                          * getting 8) */
196                         //quick_proc_color_run("msr_dumb_while", p, 124, temp_f);
197                         quick_proc_run("/bin/hello", p, temp_f);
198                         #if 0
199                         // this is how you can transition to a parallel process manually
200                         // make sure you don't proc run first
201                         __proc_set_state(p, PROC_RUNNING_S);
202                         __proc_set_state(p, PROC_RUNNABLE_M);
203                         p->resources[RES_CORES].amt_wanted = 5;
204                         spin_unlock(&p->proc_lock);
205                         core_request(p);
206                         panic("This is okay");
207                         #endif
208                         break;
209                 case 1:
210                         #if 0
211                         udelay(10000000);
212                         // this is a ghetto way to test restarting an _M
213                                 printk("\nattempting to ghetto preempt...\n");
214                                 spin_lock(&p->proc_lock);
215                                 proc_take_allcores(p, __death);
216                                 __proc_set_state(p, PROC_RUNNABLE_M);
217                                 spin_unlock(&p->proc_lock);
218                                 udelay(5000000);
219                                 printk("\nattempting to restart...\n");
220                                 core_request(p); // proc still wants the cores
221                         panic("This is okay");
222                         // this tests taking some cores, and later killing an _M
223                                 printk("taking 3 cores from p\n");
224                                 for (int i = 0; i < num; i++)
225                                         corelist[i] = 7-i; // 7, 6, and 5
226                                 spin_lock(&p->proc_lock);
227                                 proc_take_cores(p, corelist, &num, __death);
228                                 spin_unlock(&p->proc_lock);
229                                 udelay(5000000);
230                                 printk("Killing p\n");
231                                 enable_irq();
232                                 proc_destroy(p);
233                                 printk("Killed p\n");
234                         panic("This is okay");
235
236                         envs[0] = kfs_proc_create(kfs_lookup_path("roslib_hello"));
237                         __proc_set_state(envs[0], PROC_RUNNABLE_S);
238                         proc_run(envs[0]);
239                         warn("DEPRECATED");
240                         break;
241                         #endif
242                 case 2:
243                         /*
244                         test_smp_call_functions();
245                         test_checklists();
246                         test_barrier();
247                         test_print_info();
248                         test_lapic_status_bit();
249                         test_ipi_sending();
250                         test_pit();
251                         */
252                 default:
253                         printd("Manager Progress: %d\n", progress);
254                         // delay if you want to test rescheduling an MCP that yielded
255                         //udelay(15000000);
256                         run_scheduler();
257         }
258         panic("If you see me, then you probably screwed up");
259         monitor(0);
260
261         /*
262         printk("Servicing syscalls from Core 0:\n\n");
263         while (1) {
264                 process_generic_syscalls(&envs[0], 1);
265                 cpu_relax();
266         }
267         */
268         return;
269 #endif
270 }
271
272 void manager_klueska()
273 {
274         static struct proc *envs[256];
275         static volatile uint8_t progress = 0;
276
277         if (progress == 0) {
278                 progress++;
279                 panic("what do you want to do?");
280                 //envs[0] = kfs_proc_create(kfs_lookup_path("fillmeup"));
281                 __proc_set_state(envs[0], PROC_RUNNABLE_S);
282                 proc_run_s(envs[0]);
283                 warn("DEPRECATED");
284         }
285         run_scheduler();
286
287         panic("DON'T PANIC");
288 }
289
290 void manager_waterman()
291 {
292         static bool first = true;
293         if (first)
294                 mon_bb(0, 0, 0);
295         smp_idle();
296         assert(0);
297 }
298
299 void manager_yuzhu()
300 {
301         
302         static uint8_t RACY progress = 0;
303         static struct proc *p;
304
305         // for testing taking cores, check in case 1 for usage
306         uint32_t corelist[MAX_NUM_CPUS];
307         uint32_t num = 3;
308
309         //create_server(init_num_cores, loop);
310
311         monitor(0);
312
313         // quick_proc_run("hello", p);
314
315 }