Extended state AMD backwards compatibility updates (XCC)
[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                               237     /* Testing IPI (used in testing.c) */
67 #define I_POKE_CORE                             238
68 #define I_KERNEL_MSG                    239
69
70 /* 240-255 are LAPIC vectors (0xf0-0xff), hightest priority class */
71 #define IdtLAPIC                                240
72 #define IdtLAPIC_TIMER                  (IdtLAPIC + 0)
73 #define IdtLAPIC_THERMAL                (IdtLAPIC + 1)
74 #define IdtLAPIC_PCINT                  (IdtLAPIC + 2)
75 #define IdtLAPIC_LINT0                  (IdtLAPIC + 3)
76 #define IdtLAPIC_LINT1                  (IdtLAPIC + 4)
77 #define IdtLAPIC_ERROR                  (IdtLAPIC + 5)
78 /* Plan 9 apic note: the spurious vector number must have bits 3-0 0x0f
79  * unless the Extended Spurious Vector Enable bit is set in the
80  * HyperTransport Transaction Control register.  On some intel machines, those
81  * bits are hardwired to 1s (SDM 3-10.9). */
82 #define IdtLAPIC_SPURIOUS               (IdtLAPIC + 0xf) /* Aka 255, 0xff */
83 #define MaxIdtLAPIC                             (IdtLAPIC + 0xf)
84
85 #define IdtMAX                                  255
86
87 #define T_DEFAULT   0x0000beef          // catchall
88
89 /* Floating point constants */
90 #define FP_EXCP_IE                              (1 << 0)        /* invalid op */
91 #define FP_EXCP_DE                              (1 << 1)        /* denormalized op */
92 #define FP_EXCP_ZE                              (1 << 2)        /* div by zero */
93 #define FP_EXCP_OE                              (1 << 3)        /* numeric overflow */
94 #define FP_EXCP_UE                              (1 << 4)        /* numeric underflow */
95 #define FP_EXCP_PE                              (1 << 5)        /* precision */
96
97 #define FP_SW_SF                                (1 << 6)        /* stack fault */
98 #define FP_SW_ES                                (1 << 7)        /* error summary status */
99 #define FP_SW_C0                                (1 << 8)        /* condition codes */
100 #define FP_SW_C1                                (1 << 9)
101 #define FP_SW_C2                                (1 << 10)
102 #define FP_SW_C3                                (1 << 14)
103 #define FP_CW_TOP_SHIFT                 (11)
104 #define FP_CW_TOP_MASK                  (7 << FP_CW_TOP_SHIFT)
105
106 #define FP_CW_PC_SHIFT                  (8)
107 #define FP_CW_PC_MASK                   (3 << FP_CW_PC_SHIFT)
108 #define FP_CW_RC_SHIFT                  (10)
109 #define FP_CW_RC_MASK                   (3 << FP_CW_RC_SHIFT)
110 #define FP_CW_IC                                (1 << 12)
111
112 #ifndef __ASSEMBLER__
113
114 #ifndef ROS_KERN_TRAP_H
115 #error "Do not include include arch/trap.h directly"
116 #endif
117
118 #include <ros/common.h>
119 #include <arch/mmu.h>
120 #include <ros/trapframe.h>
121 #include <arch/pci.h>
122 #include <arch/pic.h>
123 #include <arch/topology.h>
124 #include <cpu_feat.h>
125 #include <arch/io.h>
126 #include <stdio.h>
127
128 struct irq_handler {
129         struct irq_handler *next;
130         void (*isr)(struct hw_trapframe *hw_tf, void *data);
131         void *data;
132         int apic_vector;
133
134         /* all handlers in the chain need to have the same func pointers.  we only
135          * really use the first one, and the latter are to catch bugs.  also, we
136          * won't be doing a lot of IRQ line sharing */
137         bool (*check_spurious)(int);
138         void (*eoi)(int);
139         void (*mask)(struct irq_handler *irq_h, int vec);
140         void (*unmask)(struct irq_handler *irq_h, int vec);
141         void (*route_irq)(struct irq_handler *irq_h, int vec, int dest);
142
143         int tbdf;
144         int dev_irq;
145
146         void *dev_private;
147         char *type;
148         #define IRQ_NAME_LEN 26
149         char name[IRQ_NAME_LEN];
150 };
151
152 /* The kernel's interrupt descriptor table */
153 extern gatedesc_t idt[];
154 extern pseudodesc_t idt_pd;
155 extern taskstate_t ts;
156 int bus_irq_setup(struct irq_handler *irq_h);   /* ioapic.c */
157 extern const char *x86_trapname(int trapno);
158 extern void sysenter_handler(void);
159
160 /* Defined and set up in in arch/init.c, used for XMM initialization */
161 extern struct ancillary_state x86_default_fpu;
162 extern uint64_t x86_default_xcr0;
163
164 static inline void save_fp_state(struct ancillary_state *silly)
165 {
166         uint32_t eax, edx;
167
168         if (cpu_has_feat(CPU_FEAT_X86_XSAVEOPT)) {
169                 edx = x86_default_xcr0 >> 32;
170                 eax = x86_default_xcr0;
171                 asm volatile("xsaveopt64 %0" : : "m"(*silly), "a"(eax), "d"(edx));
172         } else if (cpu_has_feat(CPU_FEAT_X86_XSAVE)) {
173                 edx = x86_default_xcr0 >> 32;
174                 eax = x86_default_xcr0;
175                 asm volatile("xsave64 %0" : : "m"(*silly), "a"(eax), "d"(edx));
176         } else {
177                 asm volatile("fxsave64 %0" : : "m"(*silly));
178         }
179 }
180
181 static inline void init_fp_state(void);
182 static inline void restore_fp_state(struct ancillary_state *silly)
183 {
184         int err = 0;
185         uint32_t eax, edx;
186
187         if (cpu_has_feat(CPU_FEAT_X86_XSAVE)) {
188                 edx = x86_default_xcr0 >> 32;
189                 eax = x86_default_xcr0;
190                 asm volatile(ASM_STAC               ";"
191                              "1: xrstor64 %1         ;"
192                              "2: " ASM_CLAC "        ;"
193                              ".section .fixup, \"ax\";"
194                              "3: mov %4, %0          ;"
195                              "   jmp 2b              ;"
196                              ".previous              ;"
197                              _ASM_EXTABLE(1b, 3b)
198                              : "=r" (err)
199                              : "m"(*silly), "a"(eax), "d"(edx),
200                                "i" (-EINVAL), "0" (err));
201         } else {
202                 asm volatile(ASM_STAC               ";"
203                              "1: fxrstor64 %1         ;"
204                              "2: " ASM_CLAC "        ;"
205                              ".section .fixup, \"ax\";"
206                              "3: mov %2, %0          ;"
207                              "   jmp 2b              ;"
208                              ".previous              ;"
209                              _ASM_EXTABLE(1b, 3b)
210                              : "=r" (err)
211                              : "m"(*silly),
212                                "i" (-EINVAL), "0" (err));
213         }
214
215
216         if (err) {
217                 printk("Error restoring fp state!");
218                 printk("Likely a bad ancillary_state argument.\n");
219                 printk("Re-initializing fp state to default due to error.\n");
220                 init_fp_state();
221         }
222 }
223
224 /* A regular fninit only initializes the control, status, tag, ip,
225  * and data pointer registers. Since it leaves the data registers,
226  * MXCSR, etc. unchanged, we use init_fp_state to restore a default
227  * state that we save at boot time.
228  *
229  * If you're looking for a workout, you could also fninit, ldmxcsr with
230  * a default value, and 0 all the registers by hand.
231  */
232 static inline void init_fp_state(void)
233 {
234         restore_fp_state(&x86_default_fpu);
235 }
236
237 static inline void __attribute__((always_inline))
238 set_stack_pointer(uintptr_t sp)
239 {
240         asm volatile("mov %0,%%"X86_REG_SP"" : : "r"(sp) : "memory", X86_REG_SP);
241 }
242
243 static inline void __attribute__((always_inline))
244 set_frame_pointer(uintptr_t fp)
245 {
246         /* note we can't list BP as a clobber - the compiler will flip out.  makes
247          * me wonder if clobbering SP above makes a difference (probably not) */
248         asm volatile("mov %0,%%"X86_REG_BP"" : : "r"(fp) : "memory");
249 }
250
251 extern segdesc_t *gdt;
252
253 #include <arch/trap64.h>
254
255 #endif /* !__ASSEMBLER__ */