udelay_sched() -> kthread_usleep()
[akaros.git] / kern / arch / x86 / init.c
1 /* See COPYRIGHT for copyright information. */
2
3 #include <smp.h>
4
5 #include <arch/pci.h>
6 #include <arch/console.h>
7 #include <arch/perfmon.h>
8 #include <arch/init.h>
9 #include <console.h>
10 #include <monitor.h>
11 #include <arch/usb.h>
12
13 struct ancillary_state x86_default_fpu;
14 uint32_t kerndate;
15
16 #define capchar2ctl(x) ((x) - '@')
17
18 /* irq handler for the console (kb, serial, etc) */
19 static void irq_console(struct hw_trapframe *hw_tf, void *data)
20 {
21         uint8_t c;
22         struct cons_dev *cdev = (struct cons_dev*)data;
23         assert(cdev);
24         if (cons_get_char(cdev, &c))
25                 return;
26         /* Control code intercepts */
27         switch (c) {
28                 case capchar2ctl('G'):
29                         /* traditional 'ctrl-g', will put you in the monitor gracefully */
30                         send_kernel_message(core_id(), __run_mon, 0, 0, 0, KMSG_ROUTINE);
31                         return;
32                 case capchar2ctl('Q'):
33                         /* force you into the monitor.  you might deadlock. */
34                         printk("\nForcing entry to the monitor\n");
35                         monitor(hw_tf);
36                         return;
37                 case capchar2ctl('B'):
38                         /* backtrace / debugging for the core receiving the irq */
39                         printk("\nForced trapframe and backtrace for core %d\n", core_id());
40                         if (!hw_tf) {
41                                 printk("(no hw_tf, we probably polled the console)\n");
42                                 return;
43                         }
44                         print_trapframe(hw_tf);
45                         backtrace_kframe(hw_tf);
46                         return;
47         }
48         /* Do our work in an RKM, instead of interrupt context.  Note the RKM will
49          * cast 'c' to a char. */
50         send_kernel_message(core_id(), __cons_add_char, (long)&cons_buf, (long)c,
51                             0, KMSG_ROUTINE);
52 }
53
54 static void cons_poller(void *arg)
55 {
56         while (1) {
57                 kthread_usleep(10000);
58                 irq_console(0, arg);
59         }
60 }
61
62 static void cons_irq_init(void)
63 {
64         struct cons_dev *i;
65         /* Register interrupt handlers for all console devices */
66         SLIST_FOREACH(i, &cdev_list, next) {
67                 register_irq(i->irq, irq_console, i, MKBUS(BusISA, 0, 0, 0));
68 #ifdef CONFIG_POLL_CONSOLE
69                 ktask("cons_poller", cons_poller, i);
70 #endif /* CONFIG_POLL_CONSOLE */
71         }
72 }
73
74 void arch_init()
75 {
76         /* need to reinit before saving, in case boot agents used the FPU or it is
77          * o/w dirty.  had this happen on c89, which had a full FP stack after
78          * booting. */
79         asm volatile ("fninit");
80         save_fp_state(&x86_default_fpu); /* used in arch/trap.h for fpu init */
81         pci_init();
82         vmm_init();
83         // this returns when all other cores are done and ready to receive IPIs
84         #ifdef CONFIG_SINGLE_CORE
85                 smp_percpu_init();
86         #else
87                 smp_boot();
88         #endif
89         proc_init();
90
91         perfmon_init();
92         cons_irq_init();
93         intel_lpc_init();
94         usb_disable_legacy();
95         check_timing_stability();
96 }