b1d179e524a6449af1a46abb5d2ddadffd58f83d
[akaros.git] / kern / arch / i686 / trap.h
1 #ifndef ROS_KERN_ARCH_TRAP_H
2 #define ROS_KERN_ARCH_TRAP_H
3
4 #define MSR_IA32_SYSENTER_CS 0x174
5 #define MSR_IA32_SYSENTER_ESP 0x175
6 #define MSR_IA32_SYSENTER_EIP 0x176
7
8 // Trap numbers
9 // These are processor defined:
10 #define T_DIVIDE     0          // divide error
11 #define T_DEBUG      1          // debug exception
12 #define T_NMI        2          // non-maskable interrupt
13 #define T_BRKPT      3          // breakpoint
14 #define T_OFLOW      4          // overflow
15 #define T_BOUND      5          // bounds check
16 #define T_ILLOP      6          // illegal opcode
17 #define T_DEVICE     7          // device not available 
18 #define T_DBLFLT     8          // double fault
19 /* #define T_COPROC  9 */       // reserved (not generated by recent processors)
20 #define T_TSS       10          // invalid task switch segment
21 #define T_SEGNP     11          // segment not present
22 #define T_STACK     12          // stack exception
23 #define T_GPFLT     13          // genernal protection fault
24 #define T_PGFLT     14          // page fault
25 /* #define T_RES    15 */       // reserved
26 #define T_FPERR     16          // floating point error
27 #define T_ALIGN     17          // aligment check
28 #define T_MCHK      18          // machine check
29 #define T_SIMDERR   19          // SIMD floating point error
30
31 // These are arbitrarily chosen, but with care not to overlap
32 // processor defined exceptions or interrupt vectors.
33
34 // T_SYSCALL is defined by the following include:
35 #include <ros/arch/syscall.h>
36
37 #define T_DEFAULT   0xdeadbeef          // catchall
38
39 /* Page faults return the nature of the fault in the bits of the error code: */
40 #define PF_ERROR_PRESENT                0x01
41 #define PF_ERROR_WRITE                  0x02
42 #define PF_ERROR_USER                   0x04
43
44 /* IPIs */
45 /* Testing IPI (used in testing.c) */
46 #define I_TESTING               230
47 /* smp_call_function IPIs, keep in sync with NUM_HANDLER_WRAPPERS (and < 16)
48  * it's important that this begins with 0xf0.  check i386/trap.c for details. */
49 #define I_SMP_CALL0     0xf0 // 240
50 #define I_SMP_CALL1     0xf1
51 #define I_SMP_CALL2     0xf2
52 #define I_SMP_CALL3     0xf3
53 #define I_SMP_CALL4     0xf4
54 #define I_SMP_CALL_LAST I_SMP_CALL4
55 /* Direct/Hardwired IPIs.  Hardwired in trapentry.S */
56 #define I_KERNEL_MSG    255
57
58 #ifndef __ASSEMBLER__
59
60 #ifndef ROS_KERN_TRAP_H
61 #error "Do not include include arch/trap.h directly"
62 #endif
63
64 #include <ros/common.h>
65 #include <arch/mmu.h>
66 #include <ros/trapframe.h>
67
68 /* The kernel's interrupt descriptor table */
69 extern gatedesc_t idt[];
70 extern taskstate_t ts;
71
72 /* Defined and set up in in arch/init.c, used for XMM initialization */
73 extern struct ancillary_state x86_default_fpu;
74
75 /* Determines if the given TF was in the kernel or not. */
76 static inline bool in_kernel(struct hw_trapframe *hw_tf)
77 {
78         return (hw_tf->tf_cs & ~3) == GD_KT;
79 }
80
81 static inline void save_fp_state(struct ancillary_state *silly)
82 {
83         asm volatile("fxsave %0" : : "m"(*silly));
84 }
85
86 /* TODO: this can trigger a GP fault if MXCSR reserved bits are set.  Callers
87  * will need to handle intercepting the kernel fault. */
88 static inline void restore_fp_state(struct ancillary_state *silly)
89 {
90         asm volatile("fxrstor %0" : : "m"(*silly));
91 }
92
93 /* A regular fninit will only initialize the x87 part of the FPU, not the XMM
94  * registers and the MXCSR state.  So to init, we'll just keep around a copy of
95  * the default FPU state, which we grabbed during boot, and can copy that over
96  * Alternatively, we can fninit, ldmxcsr with the default value, and 0 out the
97  * XMM registers. */
98 static inline void init_fp_state(void)
99 {
100         restore_fp_state(&x86_default_fpu);
101 }
102
103 static inline void __attribute__((always_inline))
104 set_stack_pointer(uintptr_t sp)
105 {
106         asm volatile("mov %0,%%esp" : : "r"(sp) : "memory","esp");
107 }
108
109 /* Save's the current kernel context into tf, setting the PC to the end of this
110  * function.  Note the kernel doesn't need to save a lot. */
111 static inline void save_kernel_ctx(struct kernel_ctx *ctx)
112 {
113         /* Save the regs and the future esp. */
114         asm volatile("movl %%esp,(%0);       " /* save esp in it's slot*/
115                      "pushl %%eax;           " /* temp save eax */
116                      "leal 1f,%%eax;         " /* get future eip */
117                      "movl %%eax,(%1);       " /* store future eip */
118                      "popl %%eax;            " /* restore eax */
119                      "movl %2,%%esp;         " /* move to the beginning of the tf */
120                      "addl $0x20,%%esp;      " /* move to after the push_regs */
121                      "pushal;                " /* save regs */
122                      "addl $0x44,%%esp;      " /* move to esp slot */
123                      "popl %%esp;            " /* restore esp */
124                      "1:                     " /* where this tf will restart */
125                      : 
126                      : "r"(&ctx->hw_tf.tf_esp), "r"(&ctx->hw_tf.tf_eip),
127                        "g"(&ctx->hw_tf)
128                      : "eax", "memory", "cc");
129 }
130
131 #endif /* !__ASSEMBLER__ */
132
133 #endif /* !ROS_INC_ARCH_TRAP_H */