9ns: mnt: Don't use a 'bogus' struct
[akaros.git] / kern / arch / x86 / init.c
1 /* See COPYRIGHT for copyright information. */
2
3 #include <ros/common.h>
4 #include <smp.h>
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 <monitor.h>
11 #include <arch/usb.h>
12 #include <assert.h>
13 #include <ros/procinfo.h>
14 #include <cpu_feat.h>
15
16
17 struct ancillary_state x86_default_fpu;
18 uint32_t kerndate;
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 'ctrl-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                         if (!hw_tf) {
45                                 printk("(no hw_tf, we probably polled the console)\n");
46                                 return;
47                         }
48                         print_trapframe(hw_tf);
49                         backtrace_hwtf(hw_tf);
50                         return;
51         }
52         cons_add_char(c);
53 }
54
55 static void cons_poller(void *arg)
56 {
57         while (1) {
58                 kthread_usleep(10000);
59                 irq_console(0, arg);
60         }
61 }
62
63 static void cons_irq_init(void)
64 {
65         struct cons_dev *i;
66         /* Register interrupt handlers for all console devices */
67         SLIST_FOREACH(i, &cdev_list, next) {
68                 register_irq(i->irq, irq_console, i, MKBUS(BusISA, 0, 0, 0));
69                 irq_console(0, i);
70         }
71 }
72
73 /* Init x86 processor extended state */
74 void ancillary_state_init(void)
75 {
76         uint32_t eax, ebx, ecx, edx;
77         uint64_t proc_supported_features; /* proc supported user state components */
78
79         // If you don't at least have FXSAVE and FXRSTOR
80         // (includes OSFXSR), you don't boot.
81         if (!cpu_has_feat(CPU_FEAT_X86_FXSR))
82                 panic("No FXSAVE/FXRSTOR (FXSR) support! Refusing to boot.");
83
84         if (cpu_has_feat(CPU_FEAT_X86_XSAVE)) {
85                 // Next determine the user state components supported
86                 // by the processor and set x86_default_xcr0 in proc_global_info.
87                 cpuid(0x0d, 0x00, &eax, 0, 0, &edx);
88                 proc_supported_features = ((uint64_t)edx << 32) | eax;
89
90                 // Intersection of processor-supported and Akaros-supported
91                 // features is the Akaros-wide default at runtime.
92                 __proc_global_info.x86_default_xcr0 = X86_MAX_XCR0 &
93                                                       proc_supported_features;
94
95                 /*
96                  * Make sure CR4.OSXSAVE is set and set the local xcr0 to the default.
97                  * We will do both of these things again during per-cpu init,
98                  * but we are about to use XSAVE to build our default extended state
99                  * record, so we need them enabled.
100                  * You must set CR4_OSXSAVE before setting xcr0, or a #UD fault occurs.
101                  */
102                 lcr4(rcr4() | CR4_OSXSAVE);
103                 lxcr0(__proc_global_info.x86_default_xcr0);
104
105                 /* Build a default set of extended state values that we can later use
106                  * to initialize extended state on other cores, or restore on this
107                  * core.  FNINIT won't actually do it - if you xsave after fninit, x87
108                  * will show up as active in xstate_bv[0].  Instead, we just need
109                  * the xstate_bv bits zeroed (and memset the rest for sanity's sake).
110                  */
111                 memset(&x86_default_fpu, 0x00, sizeof(struct ancillary_state));
112
113                 /* We must set the MXCSR field in the default state struct to its
114                  * power-on value of 0x1f80. This masks all SIMD floating
115                  * point exceptions and clears all SIMD floating-point exception
116                  * flags, sets rounding control to round-nearest, disables
117                  * flush-to-zero mode, and disables denormals-are-zero mode.
118                  *
119                  * We don't actually have to set the MXCSR itself here,
120                  * because it will be set from the default state struct when
121                  * we perform per-cpu init.
122                  *
123                  * Right now, we set the MXCSR through fp_head_64d. Since
124                  * the mxcsr is at the same offset in all fp header formats
125                  * implemented for Akaros, this will function correctly for
126                  * all supported operating modes.
127                  */
128                 x86_default_fpu.fp_head_64d.mxcsr = 0x1f80;
129         } else {
130                 // Since no program should try to use XSAVE features
131                 // on this processor, we set x86_default_xcr0 to 0x0
132                 __proc_global_info.x86_default_xcr0 = 0x0;
133
134                 /*
135                  * Build a default set of extended state values that we can later use to
136                  * initialize extended state on other cores, or restore on this core.
137                  * We need to use FNINIT to reset the FPU before saving, in case boot
138                  * agents used the FPU or it is dirty for some reason. An old comment
139                  * that used to be here said "had this happen on c89, which had a full
140                  * FP stack after booting." Note that FNINIT does not clear the data
141                  * registers, but it tags them all as empty (0b11).
142                  */
143
144                 // Zero the default extended state memory region before saving.
145                 // It may be possible for memset to clobber SSE registers.
146                 memset(&x86_default_fpu, 0x00, sizeof(struct ancillary_state));
147
148                 /*
149                  * FNINIT clears FIP and FDP and, even though it is technically a
150                  * control instruction, it clears FOP while initializing the FPU.
151                  *
152                  * This marks the STX/MMX registers as empty in the FPU tag word,
153                  * but does not actually clear the values in the registers,
154                  * so we manually clear them in the xsave area after saving.
155                  */
156                 asm volatile ("fninit");
157
158                 // Save the x87 FPU state
159                 asm volatile("fxsave64 %0" : : "m"(x86_default_fpu));
160
161                 /*
162                  * Clear junk that might have been saved from the STX/MMX registers.
163                  *
164                  * FXSAVE may have also saved junk from the XMM registers,
165                  * depending on how the hardware was implemented and the setting
166                  * of CR4.OSFXSR. So we clear that too.
167                  *
168                  * MMX: 128 bytes, XMM: 256 bytes
169                  */
170                 memset(&(x86_default_fpu.st0_mm0), 0x00, 128 + 256);
171
172                 /*
173                  * Finally, because Only the Paranoid Survive, we set the MXCSR
174                  * for our default state. It should have been saved by FXSAVE,
175                  * but who knows if the default value is still there at this
176                  * point in the boot process.
177                  */
178                 x86_default_fpu.fp_head_64d.mxcsr = 0x1f80;
179         }
180
181 }
182
183 void arch_init(void)
184 {
185         ancillary_state_init();
186         pci_init();
187         vmm_init();
188         perfmon_global_init();
189         // this returns when all other cores are done and ready to receive IPIs
190         #ifdef CONFIG_SINGLE_CORE
191                 smp_percpu_init();
192         #else
193                 smp_boot();
194         #endif
195         proc_init();
196
197         cons_irq_init();
198         intel_lpc_init();
199 #ifdef CONFIG_ENABLE_LEGACY_USB
200         printk("Legacy USB support enabled, expect SMM interference!\n");
201 #else
202         usb_disable_legacy();
203 #endif
204         check_timing_stability();
205 }