Kernel context (IRQ, etc) tracking
[akaros.git] / kern / include / trap.h
1 /* See COPYRIGHT for copyright information. */
2
3 #ifndef ROS_KERN_TRAP_H
4 #define ROS_KERN_TRAP_H
5 #ifndef ROS_KERNEL
6 # error "This is an ROS kernel header; user programs should not #include it"
7 #endif
8
9 #include <arch/arch.h>
10 #include <arch/mmu.h>
11 #include <arch/trap.h>
12 #include <sys/queue.h>
13
14 // func ptr for interrupt service routines
15 typedef void ( *poly_isr_t)(trapframe_t* tf, TV(t) data);
16 typedef void (*isr_t)(trapframe_t* tf, void * data);
17 typedef struct InterruptHandler {
18         poly_isr_t isr;
19         TV(t) data;
20 } handler_t;
21
22 #ifdef __IVY__
23 #pragma cilnoremove("iht_lock")
24 extern spinlock_t iht_lock;
25 #endif
26 extern handler_t LCKD(&iht_lock) (CT(NUM_INTERRUPT_HANDLERS) RO interrupt_handlers)[];
27
28 void idt_init(void);
29 void
30 register_interrupt_handler(handler_t SSOMELOCK (CT(NUM_INTERRUPT_HANDLERS)table)[],
31                            uint8_t int_num,
32                            poly_isr_t handler, TV(t) data);
33 void print_trapframe(trapframe_t *tf);
34 void page_fault_handler(trapframe_t *tf);
35 /* Generic per-core timer interrupt handler.  set_percore_timer() will fire the
36  * timer_interrupt(). */
37 void set_core_timer(uint32_t usec, bool periodic);
38 void timer_interrupt(struct trapframe *tf, void *data);
39
40 void sysenter_init(void);
41 extern void sysenter_handler();
42
43 void save_fp_state(struct ancillary_state *silly);
44 void restore_fp_state(struct ancillary_state *silly);
45 /* Set stacktop for the current core to be the stack the kernel will start on
46  * when trapping/interrupting from userspace */
47 void set_stack_top(uintptr_t stacktop);
48 uintptr_t get_stack_top(void);
49
50 /* It's important that this is inline and that tf is not a stack variable */
51 static inline void save_kernel_tf(struct trapframe *tf)
52                    __attribute__((always_inline));
53 void pop_kernel_tf(struct trapframe *tf) __attribute__((noreturn));
54
55 /* Sends a non-maskable interrupt, which we have print a trapframe. */
56 void send_nmi(uint32_t os_coreid);
57
58 /* Kernel messages.  Each arch implements them in their own way.  Both should be
59  * guaranteeing in-order delivery.  Kept here in trap.h, since sparc is using
60  * trap.h for KMs.  Eventually, both arches will use the same implementation.
61  *
62  * These are different (for now) than the smp_calls in smp.h, since
63  * they will be executed immediately (for urgent messages), and in the order in
64  * which they are sent.  smp_calls are currently not run in order, and they must
65  * return (possibly passing the work to a workqueue, which is really just a
66  * routine message, so they really need to just return).
67  *
68  * Eventually, smp_call will be replaced by these.
69  *
70  * Also, a big difference is that smp_calls can use the same message (registered
71  * in the interrupt_handlers[] for x86) for every recipient, but the kernel
72  * messages require a unique message.  Also for now, but it might be like that
73  * for a while on x86 (til we have a broadcast). */
74
75 #define KMSG_IMMEDIATE                  1
76 #define KMSG_ROUTINE                    2
77
78 typedef void (*amr_t)(struct trapframe *tf, uint32_t srcid, long a0, long a1,
79                       long a2);
80
81 /* Must stay 8-byte aligned for sparc */
82 struct kernel_message
83 {
84         STAILQ_ENTRY(kernel_message) link;
85         uint32_t srcid;
86         uint32_t dstid;
87         amr_t pc;
88         long arg0;
89         long arg1;
90         long arg2;
91 }__attribute__((aligned(8)));
92
93 STAILQ_HEAD(kernel_msg_list, kernel_message);
94 typedef struct kernel_message kernel_message_t;
95
96 void kernel_msg_init(void);
97 uint32_t send_kernel_message(uint32_t dst, amr_t pc, long arg0, long arg1,
98                              long arg2, int type);
99 void handle_kmsg_ipi(struct trapframe *tf, void *data);
100 void process_routine_kmsg(void);
101 void print_kmsgs(uint32_t coreid);
102
103 /* Kernel context depths.  IRQ depth is how many nested IRQ stacks/contexts we
104  * are working on.  Kernel trap depth is how many nested kernel traps (not
105  * user-space traps) we have.
106  *
107  * Some examples:
108  *              (original context in parens, +(x, y) is the change to IRQ and ktrap
109  *              depth):
110  * - syscall (user): +(0, 0)
111  * - trap (user): +(0, 0)
112  * - irq (user): +(1, 0)
113  * - irq (kernel, handling syscall): +(1, 0)
114  * - trap (kernel, regardless of context): +(0, 1)
115  * - NMI (kernel): it's actually a kernel trap, even though it is
116  *   sent by IPI.  +(0, 1)
117  * - NMI (user): just a trap.  +(0, 0)
118  *
119  * So if the user traps in for a syscall (0, 0), then the kernel takes an IRQ
120  * (1, 0), and then another IRQ (2, 0), and then the kernel page faults (a
121  * trap), we're at (2, 1).
122  *
123  * Or if we're in userspace, then an IRQ arrives, we're in the kernel at (1, 0).
124  * Note that regardless of whether or not we are in userspace or the kernel when
125  * an irq arrives, we still are only at level 1 irq depth.  We don't care if we
126  * have one or 0 kernel contexts under us.  (The reason for this is that I care
127  * if it is *possible* for us to interrupt the kernel, not whether or not it
128  * actually happened). */
129
130 /* uint32_t __ctx_depth is laid out like so:
131  *
132  * +------8------+------8------+------8------+------8------+
133  * |    Flags    |    Unused   | Kernel Trap |  IRQ Depth  |
134  * |             |             |    Depth    |             |
135  * +-------------+-------------+-------------+-------------+
136  *
137  */
138 #define __CTX_IRQ_D_SHIFT                       0
139 #define __CTX_KTRAP_D_SHIFT                     8
140 #define __CTX_FLAG_SHIFT                        24
141 #define __CTX_IRQ_D_MASK                        ((1 << 8) - 1)
142 #define __CTX_KTRAP_D_MASK                      ((1 << 8) - 1)
143 #define __CTX_NESTED_CTX_MASK           ((1 << 16) - 1)
144 #define __CTX_EARLY_RKM                         (1 << __CTX_FLAG_SHIFT)
145
146 /* Basic functions to get or change depths */
147
148 #define irq_depth(pcpui)                                                       \
149         (((pcpui)->__ctx_depth >> __CTX_IRQ_D_SHIFT) & __CTX_IRQ_D_MASK)
150
151 #define ktrap_depth(pcpui)                                                     \
152         (((pcpui)->__ctx_depth >> __CTX_KTRAP_D_SHIFT) & __CTX_KTRAP_D_MASK)
153
154 #define inc_irq_depth(pcpui)                                                   \
155         ((pcpui)->__ctx_depth += 1 << __CTX_IRQ_D_SHIFT)
156
157 #define dec_irq_depth(pcpui)                                                   \
158         ((pcpui)->__ctx_depth -= 1 << __CTX_IRQ_D_SHIFT)
159
160 #define inc_ktrap_depth(pcpui)                                                 \
161         ((pcpui)->__ctx_depth += 1 << __CTX_KTRAP_D_SHIFT)
162
163 #define dec_ktrap_depth(pcpui)                                                 \
164         ((pcpui)->__ctx_depth -= 1 << __CTX_KTRAP_D_SHIFT)
165
166 #define set_rkmsg(pcpui)                                                       \
167         ((pcpui)->__ctx_depth |= __CTX_EARLY_RKM)
168
169 #define clear_rkmsg(pcpui)                                                     \
170         ((pcpui)->__ctx_depth &= ~__CTX_EARLY_RKM)
171
172 /* Functions to query the kernel context depth/state.  I haven't fully decided
173  * on whether or not 'default' context includes RKMs or not.  Will depend on
174  * how we use it.  Check the code below to see what the latest is. */
175
176 #define in_irq_ctx(pcpui)                                                      \
177         (irq_depth(pcpui))
178
179 #define in_early_rkmsg_ctx(pcpui)                                              \
180         ((pcpui)->__ctx_depth & __CTX_EARLY_RKM)
181
182 /* Right now, anything (KTRAP, IRQ, or RKM) makes us not 'default' */
183 #define in_default_ctx(pcpui)                                                  \
184         (!(pcpui)->__ctx_depth)
185
186 /* Can block only if we have no nested contexts (ktraps or irqs, (which are
187  * potentially nested contexts)) */
188 #define can_block(pcpui)                                                       \
189         (!((pcpui)->__ctx_depth & __CTX_NESTED_CTX_MASK))
190
191 /* TRUE if we are allowed to spin, given that the 'lock' was declared as not
192  * grabbable from IRQ context.  Meaning, we can't grab the lock from any nested
193  * context.  (And for most locks, we can never grab them from a kernel trap
194  * handler). 
195  *
196  * Example is a lock that is not declared as irqsave, but we later grab it from
197  * irq context.  This could deadlock the system, even if it doesn't do it this
198  * time.  This function will catch that. */
199 #define can_spinwait_noirq(pcpui)                                              \
200         (!((pcpui)->__ctx_depth & __CTX_NESTED_CTX_MASK))
201
202 /* TRUE if we are allowed to spin, given that the 'lock' was declared as
203  * potentially grabbable by IRQ context (such as with an irqsave lock).  We can
204  * never grab from a ktrap, since there is no way to prevent that.  And we must
205  * have IRQs disabled, since an IRQ handler could attempt to grab the lock. */
206 #define can_spinwait_irq(pcpui)                                                \
207         ((!ktrap_depth(pcpui) && !irq_is_enabled()))
208
209 /* Debugging */
210 void print_kctx_depths(const char *str);
211  
212 #endif /* ROS_KERN_TRAP_H */