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