spin_trylock()
[akaros.git] / kern / arch / x86 / init.c
1 /* See COPYRIGHT for copyright information. */
2
3 #ifdef __SHARC__
4 #pragma nosharc
5 #endif
6
7 #include <smp.h>
8
9 #include <arch/mptables.h>
10 #include <arch/pci.h>
11 #include <arch/ioapic.h>
12 #include <arch/console.h>
13 #include <arch/perfmon.h>
14 #include <arch/init.h>
15 #include <console.h>
16 #include <monitor.h>
17
18 struct ancillary_state x86_default_fpu;
19
20 #define capchar2ctl(x) ((x) - '@')
21
22 /* irq handler for the console (kb, serial, etc) */
23 static void irq_console(struct hw_trapframe *hw_tf, void *data)
24 {
25         uint8_t c;
26         struct cons_dev *cdev = (struct cons_dev*)data;
27         assert(cdev);
28         if (cons_get_char(cdev, &c))
29                 return;
30         /* Control code intercepts */
31         switch (c) {
32                 case capchar2ctl('G'):
33                         /* traditional 'shift-g', will put you in the monitor gracefully */
34                         send_kernel_message(core_id(), __run_mon, 0, 0, 0, KMSG_ROUTINE);
35                         return;
36                 case capchar2ctl('Q'):
37                         /* force you into the monitor.  you might deadlock. */
38                         printk("\nForcing entry to the monitor\n");
39                         monitor(hw_tf);
40                         return;
41                 case capchar2ctl('B'):
42                         /* backtrace / debugging for the core receiving the irq */
43                         printk("\nForced trapframe and backtrace for core %d\n", core_id());
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         if (c == 'G')
51                 send_kernel_message(core_id(), __run_mon, 0, 0, 0, KMSG_ROUTINE);
52         else
53                 send_kernel_message(core_id(), __cons_add_char, (long)&cons_buf,
54                                     (long)c, 0, KMSG_ROUTINE);
55 }
56
57 static void cons_irq_init(void)
58 {
59         struct cons_dev *i;
60         /* Register interrupt handlers for all console devices */
61         SLIST_FOREACH(i, &cdev_list, next) {
62                 register_interrupt_handler(interrupt_handlers, i->irq + PIC1_OFFSET,
63                                            irq_console, i);
64                 /* Route any console IRQs to core 0 */
65         #ifdef CONFIG_ENABLE_MPTABLES
66                 ioapic_route_irq(i->irq, 0);
67         #else
68                 pic_unmask_irq(i->irq);
69                 unmask_lapic_lvt(LAPIC_LVT_LINT0);
70         #endif /* CONFIG_ENABLE_MPTABLES */
71                 printd("Registered handler for IRQ %d (ISR %d)\n", i->irq,
72                        i->irq + PIC1_OFFSET);
73         }
74 }
75
76 void arch_init()
77 {
78         /* need to reinit before saving, in case boot agents used the FPU or it is
79          * o/w dirty.  had this happen on c89, which had a full FP stack after
80          * booting. */
81         asm volatile ("fninit");
82         save_fp_state(&x86_default_fpu); /* used in arch/trap.h for fpu init */
83         pci_init();
84 #ifdef CONFIG_ENABLE_MPTABLES
85         mptables_parse();
86         ioapic_init(); // MUST BE AFTER PCI/ISA INIT!
87         // TODO: move these back to regular init.  requires fixing the 
88         // CONFIG_NETWORKING inits to not need multiple cores running.
89 #endif
90         // this returns when all other cores are done and ready to receive IPIs
91         #ifdef CONFIG_SINGLE_CORE
92                 smp_percpu_init();
93         #else
94                 smp_boot();
95         #endif
96         proc_init();
97
98         /* EXPERIMENTAL NETWORK FUNCTIONALITY
99          * To enable, define CONFIG_NETWORKING in your Makelocal
100          * If enabled, will load the rl8168 driver (if device exists)
101          * and will a boot into userland matrix, so remote syscalls can be performed.
102          * If in simulation, will do some debugging information with the ne2k device
103          *
104          * Note: If you use this, you should also define the mac address of the 
105          * teathered machine via USER_MAC_ADDRESS in Makelocal.
106          *
107          * Additionally, you should have a look at the syscall server in the tools directory
108          */
109         #ifdef CONFIG_NETWORKING
110         #ifdef CONFIG_SINGLE_CORE
111                 warn("You currently can't have networking if you boot into single core mode!!\n");
112         #else
113                 /* TODO: use something like linux's device_init() to call these. */
114                 #ifdef CONFIG_RL8168
115                 extern void rl8168_init(void);          
116                 rl8168_init();          
117                 #endif
118                 #ifdef CONFIG_NE2K
119                 extern void ne2k_init(void);            
120                 ne2k_init();
121                 #endif
122                 #ifdef CONFIG_E1000
123                 extern void e1000_init(void);           
124                 e1000_init();
125                 #endif
126         #endif // CONFIG_SINGLE_CORE
127         #endif // CONFIG_NETWORKING
128
129         perfmon_init();
130         cons_irq_init();
131         check_timing_stability();
132 }