fish: add missing include to unbreak build
[barrelfish] / usr / drivers / cpuboot / main.c
1 /**
2  * \file
3  * \brief Core boot main
4  */
5 /*
6  * Copyright (c) 2013, ETH Zurich.
7  * All rights reserved.
8  *
9  * This file is distributed under the terms in the attached LICENSE file.
10  * If you do not find this file, copies can be found by writing to:
11  * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12  */
13
14 #include <getopt.h>
15 #include "coreboot.h"
16 #include <hw_records.h>
17
18
19 coreid_t my_arch_id;
20 struct capref ipi_cap;
21
22 coreid_t core_count = 0;
23 coreid_t core_max = 0;
24 bool done = false;
25
26 bool benchmark_flag = false;
27 bool debug_flag = false;
28 bool new_kcb_flag = false;
29 bool nomsg_flag = false;
30
31 struct bench_data *bench_data = NULL;
32
33 char* cmd_kernel_binary = NULL;
34 char* cmd_monitor_binary = NULL;
35 char* cmd_kernel_args = "loglevel=2 logmask=0";
36
37 #define APIC_INTER_HALT_VECTOR 248
38
39 static void load_arch_id(void)
40 {
41     struct monitor_blocking_rpc_client *mc = get_monitor_blocking_rpc_client();
42     errval_t err = mc->vtbl.get_arch_core_id(mc, (uintptr_t *)&my_arch_id);
43     if (err_is_fail(err)) {
44         USER_PANIC_ERR(err, "get_arch_core_id failed.");
45     }
46     DEBUG("%s:%d: my_arch_id is %"PRIuCOREID"\n", __FILE__, __LINE__, my_arch_id);
47 }
48
49 static void setup_monitor_messaging(void)
50 {
51     struct monitor_binding *st = get_monitor_binding();
52     st->rx_vtbl.boot_core_reply = boot_core_reply;
53 }
54
55 static void load_ipi_cap(void)
56 {
57     struct monitor_blocking_rpc_client *mc = get_monitor_blocking_rpc_client();
58     errval_t err = mc->vtbl.get_ipi_cap(mc, &ipi_cap);
59     if (err_is_fail(err)) {
60         USER_PANIC_ERR(err, "get_ipi_cap failed.");
61     }
62 }
63
64 static void initialize(void)
65 {
66     errval_t err;
67
68     vfs_init();
69     bench_init();
70
71 #if defined(__x86__) && !defined(__k1om__)
72     err = connect_to_acpi();
73     if (err_is_fail(err)) {
74         USER_PANIC_ERR(err, "connect to acpi failed.");
75     }
76 #endif
77
78     err = oct_init();
79     if (err_is_fail(err)) {
80         USER_PANIC_ERR(err, "Octopus initialization failed.");
81     }
82
83     setup_monitor_messaging();
84     load_arch_id();
85     load_ipi_cap();
86 }
87
88
89 typedef int(*cmd_fn)(int argc, char** argv);
90 struct cmd {
91     char* name;
92     char* desc;
93     char* help;
94     cmd_fn fn;
95     int argc;
96 };
97
98 static int parse_core_list(char *list, coreid_t *from, coreid_t *to, coreid_t *step)
99 {
100     assert(from && to && step);
101
102     int num, parsed_from,parsed_to,parsed_step;
103     num = sscanf(list, "%i:%i:%i", &parsed_from, &parsed_to, &parsed_step);
104     switch(num) {
105         case 1:
106             *from = (coreid_t)parsed_from;
107             *to = (coreid_t)parsed_from;
108             *step = 1;
109             break;
110         case 2:
111             *from = (coreid_t)parsed_from;
112             *to = (coreid_t)parsed_to;
113             *step = 1;
114             break;
115         case 3:
116             *from = (coreid_t)parsed_from;
117             *to = (coreid_t)parsed_to;
118             *step = (coreid_t)parsed_step;
119             break;
120         default:
121             return 0;
122             break;
123     }
124     return num;
125 }
126
127 static int list_kcb(int argc, char **argv) {
128     char** names;
129     size_t len;
130     errval_t err = oct_get_names(&names, &len, "r'kcb\\.[0-9]+'");
131     assert(err_is_ok(err));
132
133     for (size_t i=0; i<len; i++) {
134         char* record;
135         err = oct_get(&record, names[i]);
136         assert(err_is_ok(err));
137
138         uint64_t barrelfish_id, kcb_id;
139         char* cap_key;
140         err = oct_read(record, "_ { kcb_id: %d, barrelfish_id: %d, cap_key: %s }",
141                        &barrelfish_id, &kcb_id, &cap_key);
142         assert(err_is_ok(err));
143
144         printf("KCB %"PRIu64": CORE_ID=%"PRIu64" CAP_STORAGE_KEY=%s\n",
145                kcb_id, barrelfish_id, cap_key);
146
147         free(cap_key);
148         free(record);
149     }
150     if (len == 0) {
151         DEBUG("%s:%s:%d: No KCB found?\n",
152               __FILE__, __FUNCTION__, __LINE__);
153     }
154
155     done = true;
156     oct_free_names(names, len);
157     return 0;
158 }
159
160 static int list_cpu(int argc, char **argv) {
161     char** names;
162     size_t len;
163     errval_t err = oct_get_names(&names, &len, "r'hw\\.processor\\.[0-9]+'");
164     assert(err_is_ok(err));
165
166     for (size_t i=0; i<len; i++) {
167         char* record;
168         err = oct_get(&record, names[i]);
169         assert(err_is_ok(err));
170
171         uint64_t barrelfish_id, hw_id, enabled, type;
172         err = oct_read(record, "_ { " HW_PROCESSOR_GENERIC_FIELDS "}",
173                        &enabled, &barrelfish_id, &hw_id, &type);
174         assert(err_is_ok(err));
175
176         printf("CPU %"PRIu64": HW_ID=%"PRIu64" TYPE=%s ENABLED=%"PRIu64"\n",
177                barrelfish_id, hw_id, cpu_type_to_archstr(type), enabled);
178
179         free(record);
180     }
181     if (len == 0) {
182         DEBUG("%s:%s:%d: No cpus found?\n",
183               __FILE__, __FUNCTION__, __LINE__);
184     }
185
186     done = true;
187     oct_free_names(names, len);
188     return 0;
189 }
190
191 static int boot_cpu(int argc, char **argv)
192 {
193     coreid_t core_from = 0, core_to = 0, core_step = 0;
194     int parsed = parse_core_list(argv[1], &core_from, &core_to, &core_step);
195
196     if (parsed == 0) {
197         USER_PANIC("invalid CPU ID: %s", argv[1]);
198     }
199
200     core_count = 0;
201     if (core_step == 1) {
202         core_max = (core_to - core_from + 1);
203     } else {
204         core_max = (core_to - core_from + core_step) / core_step;
205     }
206
207     for (coreid_t target_id = core_from; target_id<=core_to; target_id += core_step) {
208         assert(target_id < MAX_COREID);
209
210         archid_t target_apic_id;
211         enum cpu_type cpu_type;
212         errval_t err = get_core_info(target_id, &target_apic_id, &cpu_type);
213         if (err_is_fail(err)) {
214             USER_PANIC_ERR(err, "get_apic_id failed.");
215         }
216
217         struct capref kcb;
218         err = create_or_get_kcb_cap(target_id, &kcb);
219         if (err_is_fail(err)) {
220             USER_PANIC_ERR(err, "Can not get KCB.");
221         }
222
223         struct capref frame;
224         size_t framesize;
225         struct frame_identity urpc_frame_id;
226         err = frame_alloc_identify(&frame, MON_URPC_SIZE, &framesize, &urpc_frame_id);
227         if (err_is_fail(err)) {
228             USER_PANIC_ERR(err, "frame_alloc_identify failed.");
229         }
230
231         err = cap_mark_remote(frame);
232         if (err_is_fail(err)) {
233             USER_PANIC_ERR(err, "Can not mark cap remote.");
234         }
235
236         struct monitor_binding *mb = get_monitor_binding();
237         err = mb->tx_vtbl.boot_core_request(mb, NOP_CONT, target_id, frame);
238         if (err_is_fail(err)) {
239             USER_PANIC_ERR(err, "boot_core_request failed");
240         }
241
242         err = spawn_xcore_monitor(target_id, target_apic_id,
243                                   cpu_type, cmd_kernel_args,
244                                   urpc_frame_id, kcb);
245         if (err_is_fail(err)) {
246             USER_PANIC_ERR(err, "spawn xcore monitor failed.");
247         }
248
249     }
250     return 0;
251 }
252
253
254 static int update_cpu(int argc, char** argv)
255 {
256     coreid_t target_id = (coreid_t) strtol(argv[1], NULL, 0);
257     assert(target_id < MAX_COREID);
258
259     archid_t target_apic_id;
260     enum cpu_type cpu_type;
261     errval_t err = get_core_info(target_id, &target_apic_id, &cpu_type);
262     if (err_is_fail(err)) {
263         USER_PANIC_ERR(err, "get_apic_id failed.");
264     }
265
266     struct capref kcb;
267     err = create_or_get_kcb_cap(target_id, &kcb);
268     if (err_is_fail(err)) {
269         USER_PANIC_ERR(err, "Can not get KCB.");
270     }
271
272     struct capref frame;
273     size_t framesize;
274     struct frame_identity urpc_frame_id;
275     err = frame_alloc_identify(&frame, MON_URPC_SIZE, &framesize, &urpc_frame_id);
276     if (err_is_fail(err)) {
277         USER_PANIC_ERR(err, "frame_alloc_identify  failed.");
278     }
279     err = cap_mark_remote(frame);
280     if (err_is_fail(err)) {
281         DEBUG_ERR(err, "Can not mark cap remote.");
282         return err;
283     }
284
285     // do clean shutdown
286     err = sys_debug_send_ipi(target_apic_id, 0, APIC_INTER_HALT_VECTOR);
287     if (err_is_fail(err)) {
288         USER_PANIC_ERR(err, "debug_send_ipi to power it down failed.");
289     }
290
291     done = true;
292     err = spawn_xcore_monitor(target_id, target_apic_id, cpu_type,
293                               cmd_kernel_args,
294                               urpc_frame_id, kcb);
295     if (err_is_fail(err)) {
296         USER_PANIC_ERR(err, "spawn xcore monitor failed.");
297     }
298
299     //TODO(gz): while (*ap_dispatch != 1);
300     return 0;
301 }
302
303 static int stop_cpu(int argc, char** argv)
304 {
305     coreid_t target_id = (coreid_t) strtol(argv[1], NULL, 0);
306     assert(target_id < MAX_COREID);
307
308     archid_t target_apic_id;
309     enum cpu_type cpu_type;
310     errval_t err = get_core_info(target_id, &target_apic_id, &cpu_type);
311     if (err_is_fail(err)) {
312         USER_PANIC_ERR(err, "get_apic_id failed.");
313     }
314
315     err = sys_debug_send_ipi(target_apic_id, 0, APIC_INTER_HALT_VECTOR);
316     if (err_is_fail(err)) {
317         USER_PANIC_ERR(err, "debug_send_ipi to power it down failed.");
318     }
319     done = true;
320
321     // The next line is crucial for harness test to pass
322     printf("Core %"PRIuCOREID" stopped.\n", target_id);
323     return 0;
324 }
325
326 static int give_kcb(int argc, char** argv)
327 {
328     assert (argc == 3);
329     DEBUG("%s:%d: Give KCB from core %s to core %s...\n",
330           __FILE__, __LINE__, argv[1], argv[2]);
331
332     coreid_t target_id = (coreid_t) strtol(argv[1], NULL, 0);
333     assert(target_id < MAX_COREID);
334     struct capref kcb;
335     errval_t err = create_or_get_kcb_cap(target_id, &kcb);
336     if (err_is_fail(err)) {
337         USER_PANIC_ERR(err, "Can not get KCB.");
338     }
339
340     coreid_t destination_id = (coreid_t) strtol(argv[2], NULL, 0);
341     assert(destination_id < MAX_COREID);
342
343     /*err = sys_debug_send_ipi(target_id, 0, APIC_INTER_HALT_VECTOR);
344     if (err_is_fail(err)) {
345         USER_PANIC_ERR(err, "debug_send_ipi to power it down failed.");
346     }*/
347     done = true;
348
349     err = give_kcb_to_new_core(destination_id, kcb);
350     if (err_is_fail(err)) {
351         USER_PANIC_ERR(err, "Can not send KCB to another core.");
352     }
353
354     return 0;
355 }
356
357 static int remove_kcb(int argc, char** argv)
358 {
359     assert (argc == 2);
360     DEBUG("%s:%s:%d: Stopping kcb.%s\n", __FILE__,
361           __FUNCTION__, __LINE__, argv[1]);
362
363     coreid_t target_id = (coreid_t) strtol(argv[1], NULL, 0);
364     assert(target_id < MAX_COREID);
365     struct capref kcb;
366     errval_t err = create_or_get_kcb_cap(target_id, &kcb);
367     if (err_is_fail(err)) {
368         USER_PANIC_ERR(err, "Can not get KCB.");
369     }
370
371     struct monitor_blocking_rpc_client *mc = get_monitor_blocking_rpc_client();
372     // send message to monitor to be relocated -> don't switch kcb ->
373     // remove kcb from ring -> msg ->
374     // (disp_save_rm_kcb -> next/home/... kcb -> enable switching)
375     errval_t ret_err;
376     err = mc->vtbl.forward_kcb_rm_request(mc, target_id, kcb, &ret_err);
377     if (err_is_fail(err)) {
378         USER_PANIC_ERR(err, "forward_kcb_request failed.");
379     }
380     if (err_is_fail(ret_err)) {
381         USER_PANIC_ERR(ret_err, "forward_kcb_request failed.");
382     }
383     done = true;
384
385     //coreid_t destination_id = (coreid_t) strtol(argv[3], NULL, 0);
386     //assert(destination_id < MAX_COREID);
387     //
388     // Move KCB to a core that is currently running
389     //
390     /*
391     err = give_kcb_to_new_core(destination_id, kcb);
392     if (err_is_fail(err)) {
393         USER_PANIC_ERR(err, "Can not send KCB to another core.");
394     }
395     */
396
397     //
398     // Boot the removed KCB on a core that is currently not running
399     //
400     /*
401     struct capref frame;
402     size_t framesize;
403     struct frame_identity urpc_frame_id;
404     err = frame_alloc_identify(&frame, MON_URPC_SIZE, &framesize, &urpc_frame_id);
405     if (err_is_fail(err)) {
406         USER_PANIC_ERR(err, "frame_alloc_identify failed.");
407     }
408     err = cap_mark_remote(frame);
409     if (err_is_fail(err)) {
410         DEBUG_ERR(err, "Can not mark cap remote.");
411         return err;
412     }
413
414     struct monitor_binding *mb = get_monitor_binding();
415     err = mb->tx_vtbl.boot_core_request(mb, NOP_CONT, target_id, frame);
416     if (err_is_fail(err)) {
417         USER_PANIC_ERR(err, "boot_core_request failed");
418     }
419
420     err = spawn_xcore_monitor(target_id, target_id,
421                               CPU_X86_64,
422                               cmd_kernel_args,
423                               urpc_frame_id, kcb);
424     if (err_is_fail(err)) {
425         USER_PANIC_ERR(err, "spawn xcore monitor failed.");
426     }*/
427
428     return 0;
429 }
430
431 /*
432  * Do stop and then give in one call to corectrl
433  * args: <kcb_id to stop> <kcb_id to give to>
434  */
435 static int park_kcb(int argc, char *argv[])
436 {
437     int r;
438     assert (argc == 3);
439     printf("Stopping core %lu\n", strtol(argv[1], NULL, 0));
440     r = stop_cpu(2, argv);
441     if (r) { return r; }
442     printf("Parking KCB on core %lu\n", strtol(argv[2], NULL, 0));
443     return give_kcb(3, argv);
444 }
445
446 /*
447  * Do rm and boot -m in one call to corectrl
448  * args: <kcb_id to remove> <core_id to boot>
449  */
450 static int unpark_kcb(int argc, char *argv[])
451 {
452     int r;
453     assert (argc == 2);
454     coreid_t c = (coreid_t)strtol(argv[1], NULL, 0);
455     printf("Removing KCB %u from its core\n", c);
456     r = remove_kcb(2, argv);
457     if (r) { return r; }
458     // set nomsg_flag to emulate -m option for boot
459     nomsg_flag = true;
460     printf("Booting KCB %u on core %u\n", c,c);
461     return boot_cpu(2, argv);
462 }
463
464 static struct cmd commands[] = {
465     {
466         "boot",
467         "Boot a fresh core with a KCB.",
468         "boot <target core_id>",
469         boot_cpu,
470         2
471     },
472     {
473         "update",
474         "Update the kernel on an existing core.",
475         "update <target core_id>",
476         update_cpu,
477         2
478     },
479     {
480         "stop",
481         "Stop execution on an existing core.",
482         "stop <target core_id>",
483         stop_cpu,
484         2
485     },
486     {
487         "give",
488         "Give kcb from one core to another.",
489         "give <from kcb_id> <to kcb_id>",
490         give_kcb,
491         3
492     },
493     {
494         "rmkcb",
495         "Remove a running KCB from a core.",
496         "rm <kcb_id>",
497         remove_kcb,
498         2
499     },
500     {
501         "park",
502         "Stop execution on an existing core and park KCB on another core.",
503         "park <kcb_id to stop> <recv kcb_id>",
504         park_kcb,
505         3
506     },
507     {
508         "unpark",
509         "Reestablish parked KCB on its original core.",
510         "unpark <kcb_id to unpark>",
511         unpark_kcb,
512         2
513     },
514     {
515         "lscpu",
516         "List current status of all cores.",
517         "lscpu",
518         list_cpu,
519         1
520     },
521     {
522         "lskcb",
523         "List current KCBs.",
524         "lskcb",
525         list_kcb,
526         1
527     },
528     {NULL, NULL, NULL, NULL, 0},
529 };
530
531 static struct option long_options[] = {
532     {"debug",   no_argument,       0, 'd'},
533     {"kernel",  required_argument, 0, 'k'},
534     {"monitor", required_argument, 0, 'x'},
535     {"kargs",   required_argument, 0, 'a'},
536     {"newkcb",  no_argument,       0, 'n'},
537     {"nomsg",   no_argument,       0, 'm'},
538     {"help",    no_argument,       0, 'h'},
539     {0, 0, 0, 0}
540 };
541
542 static void print_help(char* argv0)
543 {
544     printf("Usage: %s [OPTIONS] <COMMAND> [<args>]\n", argv0);
545     printf("Options:\n");
546     printf("\t -d, --debug\n");
547     printf("\t\t Print debug information\n");
548     printf("\t -k, --kernel\n");
549     printf("\t\t Overwrite default kernel binary\n");
550     printf("\t -x, --monitor\n");
551     printf("\t\t Overwrite default monitor binary\n");
552     printf("\t -a, --kargs\n");
553     printf("\t\t Overwrite default kernel cmd arguments\n");
554     printf("\t -n, --newkcb\n");
555     printf("\t\t Create a new KCB even if there is already one for that core\n");
556     printf("\t -m, --nomsg\n");
557     printf("\t\t Don't wait for monitor message at the end\n");
558     printf("\n");
559     printf("Commands:\n");
560     for (size_t i = 0; commands[i].name != NULL; i++) {
561         printf("\t %s\t\t%s\n", commands[i].name, commands[i].desc);
562     }
563 }
564
565 static void print_cmd_help(char* cmd)
566 {
567     size_t i = 0;
568     for (; commands[i].name != NULL; i++) {
569         if (strcmp(cmd, commands[i].name) == 0) {
570             break;
571         }
572     }
573
574     printf("%s - %s\n", commands[i].name, commands[i].desc);
575     printf("%s\n", commands[i].help);
576 }
577
578 int main (int argc, char **argv)
579 {
580     errval_t err;
581
582     initialize();
583     int ret = -1;
584
585     DEBUG("corectrl start\n");
586
587 #if defined(__x86__) && !defined(__k1om__)
588     // ENSURE_SEQUENTIAL
589     char *lock;
590     err = oct_lock("corectrl.lock", &lock);
591     if (err_is_fail(err)) {
592         USER_PANIC_ERR(err, "can lock corectrl.");
593     }
594     //
595 #endif
596
597     for (int i=0; i<argc; i++) {
598         DEBUG("%s:%s:%d: argv[%d] = %s\n",
599                __FILE__, __FUNCTION__, __LINE__, i, argv[i]);
600     }
601
602
603     DEBUG("corectrl got lock\n");
604     // Parse arguments, call handler function
605     int c;
606     while (1) {
607         /* getopt_long stores the option index here. */
608         int option_index = 0;
609
610         c = getopt_long (argc, argv, "k:a:x:hnmd",
611                          long_options, &option_index);
612         if (c == -1) {
613             break; // End of the options
614         }
615
616         switch (c) {
617         case 0:
618             // Long options handled by their short handles
619             break;
620
621         case 'k':
622             cmd_kernel_binary = optarg;
623             break;
624
625         case 'a':
626             cmd_kernel_args = optarg;
627             break;
628
629         case 'x':
630             cmd_monitor_binary = optarg;
631             break;
632
633         case 'm':
634             nomsg_flag = true;
635             break;
636
637         case 'n':
638             new_kcb_flag = true;
639             break;
640
641         case 'd':
642             debug_flag = true;
643             break;
644
645         case '?':
646         case 'h':
647             print_help(argv[0]);
648             goto out;
649             break;
650         default:
651             abort();
652             break;
653         }
654     }
655
656     if (optind < argc) {
657         for (; optind < argc; optind++) {
658             for (size_t i = 0; commands[i].name != NULL; i++) {
659                 if (strcmp(argv[optind], commands[i].name) == 0) {
660                     if (argc - optind < commands[i].argc) {
661                         print_cmd_help(commands[i].name);
662                         goto out;
663                     }
664                     else {
665                         ret = commands[i].fn(argc-optind, argv+optind);
666                         break;
667                     }
668                 }
669             }
670         }
671     }
672
673     if (ret == -1) {
674         print_help(argv[0]);
675     }
676     else if (!nomsg_flag) {
677         DEBUG("%s:%s:%d: Wait for message.\n",
678               __FILE__, __FUNCTION__, __LINE__);
679         while(!done) {
680             err = event_dispatch(get_default_waitset());
681             if (err_is_fail(err)) {
682                 USER_PANIC_ERR(err, "error in event_dispatch");
683             }
684         }
685     }
686
687 out:
688 #if defined(__x86__) && !defined(__k1om__)
689     // END ENSURE SEQUENTIAL
690     err = oct_unlock(lock);
691     if (err_is_fail(err)) {
692         USER_PANIC_ERR(err, "can not unlock corectrl.");
693     }
694     //
695 #endif
696
697     DEBUG("corectrl is done.");
698     return ret;
699 }