tests/linux: use Akaros's CFLAGS
[akaros.git] / kern / arch / x86 / trap.h
1 #pragma once
2
3 #define ROS_KERN_ARCH_TRAP_H
4
5 #include <ros/arch/msr-index.h>
6 #include <ros/errno.h>
7 #include <arch/fixup.h>
8
9 #define NUM_IRQS                                        256
10
11 /* 0-31 are hardware traps */
12 #define T_DIVIDE     0          // divide error
13 #define T_DEBUG      1          // debug exception
14 #define T_NMI        2          // non-maskable interrupt
15 #define T_BRKPT      3          // breakpoint
16 #define T_OFLOW      4          // overflow
17 #define T_BOUND      5          // bounds check
18 #define T_ILLOP      6          // illegal opcode
19 #define T_DEVICE     7          // device not available
20 #define T_DBLFLT     8          // double fault
21 /* #define T_COPROC  9 */       // reserved (not generated by recent processors)
22 #define T_TSS       10          // invalid task switch segment
23 #define T_SEGNP     11          // segment not present
24 #define T_STACK     12          // stack exception
25 #define T_GPFLT     13          // genernal protection fault
26 #define T_PGFLT     14          // page fault
27 /* #define T_RES    15 */       // reserved
28 #define T_FPERR     16          // floating point error
29 #define T_ALIGN     17          // aligment check
30 #define T_MCHK      18          // machine check
31 #define T_SIMDERR   19          // SIMD floating point error
32
33 /* 32-47 are PIC/8259 IRQ vectors */
34 #define IdtPIC                  32
35 #define IrqCLOCK                0
36 #define IrqKBD                  1
37 #define IrqUART1                3
38 #define IrqUART0                4
39 #define IrqPCMCIA               5
40 #define IrqFLOPPY               6
41 #define IrqLPT                  7
42 #define IrqAUX                  12      /* PS/2 port */
43 #define IrqIRQ13                13      /* coprocessor on 386 */
44 #define IrqATA0                 14
45 #define IrqATA1                 15
46 #define MaxIrqPIC               15
47 #define MaxIdtPIC               (IdtPIC + MaxIrqPIC)
48
49 /* T_SYSCALL is defined by the following include (48) */
50 #include <ros/arch/syscall.h>
51
52 /* 49-223 are IOAPIC routing vectors (from IOAPIC to LAPIC) */
53 #define IdtIOAPIC               (T_SYSCALL + 1)
54 #define MaxIdtIOAPIC            223
55
56 /* 224-239 are OS IPI vectors (0xe0-0xef) */
57 /* smp_call_function IPIs, keep in sync with NUM_HANDLER_WRAPPERS.
58  * SMP_CALL0 needs to be 16-aligned (we mask in x86/trap.c).  If you move these,
59  * also change INIT_HANDLER_WRAPPER */
60 #define I_SMP_CALL0             224
61 #define I_SMP_CALL1             (I_SMP_CALL0 + 1)
62 #define I_SMP_CALL2             (I_SMP_CALL0 + 2)
63 #define I_SMP_CALL3             (I_SMP_CALL0 + 3)
64 #define I_SMP_CALL4             (I_SMP_CALL0 + 4)
65 #define I_SMP_CALL_LAST         I_SMP_CALL4
66 #define I_TESTING               236     /* Testing IPI (used in testing.c) */
67 #define I_POKE_GUEST            237
68 #define I_POKE_CORE             238
69 #define I_KERNEL_MSG            239
70
71 /* 240-255 are LAPIC vectors (0xf0-0xff), hightest priority class */
72 #define IdtLAPIC                240
73 #define IdtLAPIC_TIMER          (IdtLAPIC + 0)
74 #define IdtLAPIC_THERMAL        (IdtLAPIC + 1)
75 #define IdtLAPIC_PCINT          (IdtLAPIC + 2)
76 #define IdtLAPIC_LINT0          (IdtLAPIC + 3)
77 #define IdtLAPIC_LINT1          (IdtLAPIC + 4)
78 #define IdtLAPIC_ERROR          (IdtLAPIC + 5)
79 /* Plan 9 apic note: the spurious vector number must have bits 3-0 0x0f
80  * unless the Extended Spurious Vector Enable bit is set in the
81  * HyperTransport Transaction Control register.  On some intel machines, those
82  * bits are hardwired to 1s (SDM 3-10.9). */
83 #define IdtLAPIC_SPURIOUS       (IdtLAPIC + 0xf) /* Aka 255, 0xff */
84 #define MaxIdtLAPIC             (IdtLAPIC + 0xf)
85
86 #define IdtMAX                  255
87
88 #define T_DEFAULT   0x0000beef  // catchall
89
90 /* Floating point constants */
91 #define FP_EXCP_IE              (1 << 0)        /* invalid op */
92 #define FP_EXCP_DE              (1 << 1)        /* denormalized op */
93 #define FP_EXCP_ZE              (1 << 2)        /* div by zero */
94 #define FP_EXCP_OE              (1 << 3)        /* numeric overflow */
95 #define FP_EXCP_UE              (1 << 4)        /* numeric underflow */
96 #define FP_EXCP_PE              (1 << 5)        /* precision */
97
98 #define FP_SW_SF                (1 << 6)        /* stack fault */
99 #define FP_SW_ES                (1 << 7)        /* error summary status */
100 #define FP_SW_C0                (1 << 8)        /* condition codes */
101 #define FP_SW_C1                (1 << 9)
102 #define FP_SW_C2                (1 << 10)
103 #define FP_SW_C3                (1 << 14)
104 #define FP_CW_TOP_SHIFT         (11)
105 #define FP_CW_TOP_MASK          (7 << FP_CW_TOP_SHIFT)
106
107 #define FP_CW_PC_SHIFT          (8)
108 #define FP_CW_PC_MASK           (3 << FP_CW_PC_SHIFT)
109 #define FP_CW_RC_SHIFT          (10)
110 #define FP_CW_RC_MASK           (3 << FP_CW_RC_SHIFT)
111 #define FP_CW_IC                (1 << 12)
112
113 #ifndef __ASSEMBLER__
114
115 #ifndef ROS_KERN_TRAP_H
116 #error "Do not include include arch/trap.h directly"
117 #endif
118
119 #include <ros/common.h>
120 #include <arch/mmu.h>
121 #include <ros/trapframe.h>
122 #include <arch/pci.h>
123 #include <arch/pic.h>
124 #include <arch/topology.h>
125 #include <cpu_feat.h>
126 #include <arch/io.h>
127 #include <stdio.h>
128
129 struct irq_handler {
130         struct irq_handler *next;
131         void (*isr)(struct hw_trapframe *hw_tf, void *data);
132         void *data;
133         int apic_vector;
134
135         /* all handlers in the chain need to have the same func pointers.  we
136          * only really use the first one, and the latter are to catch bugs.
137          * also, we won't be doing a lot of IRQ line sharing */
138         bool (*check_spurious)(int);
139         void (*eoi)(int);
140         void (*mask)(struct irq_handler *irq_h, int vec);
141         void (*unmask)(struct irq_handler *irq_h, int vec);
142         void (*route_irq)(struct irq_handler *irq_h, int vec, int dest);
143         void (*cleanup)(struct irq_handler *irq_h);
144
145         int tbdf;
146         int dev_irq;
147
148         void *dev_private;
149         char *type;
150         #define IRQ_NAME_LEN 26
151         char name[IRQ_NAME_LEN];
152 };
153
154 /* The kernel's interrupt descriptor table */
155 extern gatedesc_t idt[];
156 extern pseudodesc_t idt_pd;
157 extern taskstate_t ts;
158 int bus_irq_setup(struct irq_handler *irq_h);   /* ioapic.c */
159 extern const char *x86_trapname(int trapno);
160 extern void sysenter_handler(void);
161
162 /* Defined and set up in in arch/init.c, used for XMM initialization */
163 extern struct ancillary_state x86_default_fpu;
164
165 static inline void save_fp_state(struct ancillary_state *silly)
166 {
167         uint64_t x86_default_xcr0 = __proc_global_info.x86_default_xcr0;
168         uint32_t eax, edx;
169
170         /* PLEASE NOTE:
171          * AMD CPUs ignore the FOP/FIP/FDP fields when there is
172          * no pending exception. When you are on AMD, we zero these fields in
173          * the ancillary_state argument before saving. This way, if you are on
174          * AMD and re-using an ancillary_state memory region, an old save's
175          * information won't leak into your new data. The side-effect of this is
176          * that you can't trust these fields to report accurate information on
177          * AMD unless an exception was pending. Granted, AMD says that only
178          * exception handlers should care about FOP/FIP/FDP, so that's probably
179          * okay.
180          *
181          * You should also note that on newer Intel 64 processors, while the
182          * value of the FOP is always saved and restored, it contains the opcode
183          * of the most recent x87 FPU instruction that triggered an unmasked
184          * exception, rather than simply the most recent opcode. Some older
185          * Xeons and P4s had the fopcode compatibility mode feature, which you
186          * could use to make the FOP update on every x87 non-control
187          * instruction, but that has been eliminated in newer hardware.
188          *
189          */
190         if (cpu_has_feat(CPU_FEAT_X86_VENDOR_AMD)) {
191                 silly->fp_head_64d.fop      = 0x0;
192                 silly->fp_head_64d.fpu_ip   = 0x0;
193                 silly->fp_head_64d.cs       = 0x0;
194                 // padding1 is FIP or rsvd, proc dep.
195                 silly->fp_head_64d.padding1 = 0x0;
196                 silly->fp_head_64d.fpu_dp   = 0x0;
197                 silly->fp_head_64d.ds       = 0x0;
198                 // padding2 is FDP or rsvd, proc dep.
199                 silly->fp_head_64d.padding2 = 0x0;
200         }
201
202
203         if (cpu_has_feat(CPU_FEAT_X86_XSAVEOPT)) {
204                 edx = x86_default_xcr0 >> 32;
205                 eax = x86_default_xcr0;
206                 asm volatile("xsaveopt64 %0" : : "m"(*silly), "a"(eax),
207                              "d"(edx));
208         } else if (cpu_has_feat(CPU_FEAT_X86_XSAVE)) {
209                 edx = x86_default_xcr0 >> 32;
210                 eax = x86_default_xcr0;
211                 asm volatile("xsave64 %0" : : "m"(*silly), "a"(eax), "d"(edx));
212         } else {
213                 asm volatile("fxsave64 %0" : : "m"(*silly));
214         }
215 }
216
217 static inline void init_fp_state(void);
218 static inline void restore_fp_state(struct ancillary_state *silly)
219 {
220         uint64_t x86_default_xcr0 = __proc_global_info.x86_default_xcr0;
221         int err = 0;
222         uint32_t eax, edx;
223
224         /*
225          * Since AMD CPUs ignore the FOP/FIP/FDP fields when there is
226          * no pending exception, we clear those fields before restoring
227          * when we are both on AMD and there is no pending exception in
228          * the ancillary_state argument to restore_fp_state.
229          * If there is a pending exception in the ancillary_state,
230          * these fields will be written to the FPU upon executing
231          * a restore instruction, and there is nothing to worry about.
232          *
233          * See CVE-2006-1056 and CVE-2013-2076 on cve.mitre.org.
234          *
235          * We check for a pending exception by checking FSW.ES (bit 7)
236          *
237          * FNINIT clears FIP and FDP and, even though it is technically a
238          * control instruction, it clears FOP because it is initializing the
239          * FPU.
240          *
241          * NOTE: This might not be the most efficient way to do things, and
242          *       could be an optimization target for context switch performance
243          *       on AMD processors in the future.
244          */
245         if (!(silly->fp_head_64d.fsw & 0x80)
246             && cpu_has_feat(CPU_FEAT_X86_VENDOR_AMD))
247                 asm volatile ("fninit;");
248
249         if (cpu_has_feat(CPU_FEAT_X86_XSAVE)) {
250                 edx = x86_default_xcr0 >> 32;
251                 eax = x86_default_xcr0;
252                 asm volatile(ASM_STAC               ";"
253                              "1: xrstor64 %1         ;"
254                              "2: " ASM_CLAC "        ;"
255                              ".section .fixup, \"ax\";"
256                              "3: mov %4, %0          ;"
257                              "   jmp 2b              ;"
258                              ".previous              ;"
259                              _ASM_EXTABLE(1b, 3b)
260                              : "=r" (err)
261                              : "m"(*silly), "a"(eax), "d"(edx),
262                                "i" (-EINVAL), "0" (err));
263         } else {
264                 asm volatile(ASM_STAC               ";"
265                              "1: fxrstor64 %1         ;"
266                              "2: " ASM_CLAC "        ;"
267                              ".section .fixup, \"ax\";"
268                              "3: mov %2, %0          ;"
269                              "   jmp 2b              ;"
270                              ".previous              ;"
271                              _ASM_EXTABLE(1b, 3b)
272                              : "=r" (err)
273                              : "m"(*silly),
274                                "i" (-EINVAL), "0" (err));
275         }
276
277
278         if (err) {
279                 printk("Error restoring fp state!\n");
280                 printk("Likely a bad ancillary_state argument.\n");
281                 printk("Re-initializing fp state to default due to error.\n");
282                 init_fp_state();
283         }
284 }
285
286 /* A regular fninit only initializes the control, status, tag, ip,
287  * and data pointer registers. Since it leaves the data registers,
288  * MXCSR, etc. unchanged, we use init_fp_state to restore a default
289  * state that we save at boot time.
290  *
291  * If you're looking for a workout, you could also fninit, ldmxcsr with
292  * a default value, and 0 all the registers by hand.
293  */
294 static inline void init_fp_state(void)
295 {
296         restore_fp_state(&x86_default_fpu);
297 }
298
299 static inline void __attribute__((always_inline))
300 set_stack_pointer(uintptr_t sp)
301 {
302         asm volatile("mov %0,%%"X86_REG_SP"" : : "r"(sp)
303                      : "memory", X86_REG_SP);
304 }
305
306 static inline void __attribute__((always_inline))
307 set_frame_pointer(uintptr_t fp)
308 {
309         /* note we can't list BP as a clobber - the compiler will flip out.
310          * makes me wonder if clobbering SP above makes a difference (probably
311          * not) */
312         asm volatile("mov %0,%%"X86_REG_BP"" : : "r"(fp) : "memory");
313 }
314
315 extern segdesc_t *gdt;
316
317 #include <arch/trap64.h>
318
319 #endif /* !__ASSEMBLER__ */